diff options
author | Adrian Cumiskey <acumiskey@apache.org> | 2008-11-28 11:13:12 +0000 |
---|---|---|
committer | Adrian Cumiskey <acumiskey@apache.org> | 2008-11-28 11:13:12 +0000 |
commit | 635e2238df2084d2921e92b2c5437b3271bc6bd1 (patch) | |
tree | 98dfda8171ce604fd01cac08ef2de8d086bcb6f9 | |
parent | 0d4aac57ebb98f2a40dce9ccd24027d8ab268782 (diff) | |
parent | 392d02e2db1041986b3874968727dee298fd33fd (diff) | |
download | xmlgraphics-fop-635e2238df2084d2921e92b2c5437b3271bc6bd1.tar.gz xmlgraphics-fop-635e2238df2084d2921e92b2c5437b3271bc6bd1.zip |
MERGE of https://svn.apache.org/repos/asf/xmlgraphics/fop/{branches/AFP_GOCAResources,trunk}.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@721430 13f79535-47bb-0310-9956-ffa450edef68
294 files changed, 22085 insertions, 8436 deletions
@@ -612,6 +612,7 @@ list of possible build targets. <exclude name="org/apache/fop/render/pdf/PDFRenderer.class"/> <exclude name="org/apache/fop/render/pdf/PDFXMLHandler*"/> <include name="org/apache/fop/render/*RendererConfigurator**"/> + <include name="org/apache/fop/util/AbstractPaintingState**"/> <include name="org/apache/fop/pdf/**"/> </patternset> <!-- PS transcoder --> diff --git a/conf/fop.xconf b/conf/fop.xconf index 19415e7a4..86b72a811 100644 --- a/conf/fop.xconf +++ b/conf/fop.xconf @@ -87,6 +87,318 @@ the location of this file. </renderer> + <renderer mime="application/x-afp"> + <!-- + The bit depth and type of images produced + (this is the default setting) + --> + <images mode="b+w" bits-per-pixel="8"/> + <renderer-resolution>240</renderer-resolution> + <resource-group-file>resources.afp</resource-group-file> + + <fonts> + <!-- + Below is an example using raster font configuration using FOP builtin base-14 font metrics. + for Times Roman, Helvetica and Courier. + + Depending on AFP raster and outline font availability on your installation you will + most likely need to modify the configuration provided below. + + See http://xmlgraphics.apache.org/fop/trunk/output.html#afp-configuration + for details of FOP configuration for AFP + --> + + <!-- Times Roman --> + <font> + <afp-font name="Times Roman" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0N20060" base14-font="TimesRoman"/> + <afp-raster-font size="7" characterset="C0N20070" base14-font="TimesRoman"/> + <afp-raster-font size="8" characterset="C0N20080" base14-font="TimesRoman"/> + <afp-raster-font size="9" characterset="C0N20090" base14-font="TimesRoman"/> + <afp-raster-font size="10" characterset="C0N20000" base14-font="TimesRoman"/> + <afp-raster-font size="11" characterset="C0N200A0" base14-font="TimesRoman"/> + <afp-raster-font size="12" characterset="C0N200B0" base14-font="TimesRoman"/> + <afp-raster-font size="14" characterset="C0N200D0" base14-font="TimesRoman"/> + <afp-raster-font size="16" characterset="C0N200F0" base14-font="TimesRoman"/> + <afp-raster-font size="18" characterset="C0N200H0" base14-font="TimesRoman"/> + <afp-raster-font size="20" characterset="C0N200J0" base14-font="TimesRoman"/> + <afp-raster-font size="24" characterset="C0N200N0" base14-font="TimesRoman"/> + <afp-raster-font size="30" characterset="C0N200T0" base14-font="TimesRoman"/> + <afp-raster-font size="36" characterset="C0N200Z0" base14-font="TimesRoman"/> + </afp-font> + <font-triplet name="Times" style="normal" weight="normal"/> + <font-triplet name="TimesRoman" style="normal" weight="normal"/> + <font-triplet name="Times Roman" style="normal" weight="normal"/> + <font-triplet name="Times-Roman" style="normal" weight="normal"/> + <font-triplet name="Times New Roman" style="normal" weight="normal"/> + <font-triplet name="TimesNewRoman" style="normal" weight="normal"/> + <font-triplet name="serif" style="normal" weight="normal"/> + </font> + + <!-- Times Roman Italic --> + <font> + <afp-font name="Times Roman Italic" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0N30060" base14-font="TimesItalic"/> + <afp-raster-font size="7" characterset="C0N30070" base14-font="TimesItalic"/> + <afp-raster-font size="8" characterset="C0N30080" base14-font="TimesItalic"/> + <afp-raster-font size="9" characterset="C0N30090" base14-font="TimesItalic"/> + <afp-raster-font size="10" characterset="C0N30000" base14-font="TimesItalic"/> + <afp-raster-font size="11" characterset="C0N300A0" base14-font="TimesItalic"/> + <afp-raster-font size="12" characterset="C0N300B0" base14-font="TimesItalic"/> + <afp-raster-font size="14" characterset="C0N300D0" base14-font="TimesItalic"/> + <afp-raster-font size="16" characterset="C0N300F0" base14-font="TimesItalic"/> + <afp-raster-font size="18" characterset="C0N300H0" base14-font="TimesItalic"/> + <afp-raster-font size="20" characterset="C0N300J0" base14-font="TimesItalic"/> + <afp-raster-font size="24" characterset="C0N300N0" base14-font="TimesItalic"/> + <afp-raster-font size="30" characterset="C0N300T0" base14-font="TimesItalic"/> + <afp-raster-font size="36" characterset="C0N300Z0" base14-font="TimesItalic"/> + </afp-font> + <font-triplet name="Times" style="italic" weight="normal"/> + <font-triplet name="TimesRoman" style="italic" weight="normal"/> + <font-triplet name="Times Roman" style="italic" weight="normal"/> + <font-triplet name="Times-Roman" style="italic" weight="normal"/> + <font-triplet name="Times New Roman" style="italic" weight="normal"/> + <font-triplet name="TimesNewRoman" style="italic" weight="normal"/> + <font-triplet name="serif" style="italic" weight="normal"/> + </font> + + <!-- Times Roman Bold --> + <font> + <afp-font name="Times Roman Bold" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0N40060" base14-font="TimesBold"/> + <afp-raster-font size="7" characterset="C0N40070" base14-font="TimesBold"/> + <afp-raster-font size="8" characterset="C0N40080" base14-font="TimesBold"/> + <afp-raster-font size="9" characterset="C0N40090" base14-font="TimesBold"/> + <afp-raster-font size="10" characterset="C0N40000" base14-font="TimesBold"/> + <afp-raster-font size="11" characterset="C0N400A0" base14-font="TimesBold"/> + <afp-raster-font size="12" characterset="C0N400B0" base14-font="TimesBold"/> + <afp-raster-font size="14" characterset="C0N400D0" base14-font="TimesBold"/> + <afp-raster-font size="16" characterset="C0N400F0" base14-font="TimesBold"/> + <afp-raster-font size="18" characterset="C0N400H0" base14-font="TimesBold"/> + <afp-raster-font size="20" characterset="C0N400J0" base14-font="TimesBold"/> + <afp-raster-font size="24" characterset="C0N400N0" base14-font="TimesBold"/> + <afp-raster-font size="30" characterset="C0N400T0" base14-font="TimesBold"/> + <afp-raster-font size="36" characterset="C0N400Z0" base14-font="TimesBold"/> + </afp-font> + <font-triplet name="Times" style="normal" weight="bold"/> + <font-triplet name="TimesRoman" style="normal" weight="bold"/> + <font-triplet name="Times Roman" style="normal" weight="bold"/> + <font-triplet name="Times-Roman" style="normal" weight="bold"/> + <font-triplet name="Times New Roman" style="normal" weight="bold"/> + <font-triplet name="TimesNewRoman" style="normal" weight="bold"/> + <font-triplet name="serif" style="normal" weight="bold"/> + </font> + + <!-- Times Roman Italic Bold --> + <font> + <afp-font name="Times Roman Italic Bold" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0N50060" base14-font="TimesBoldItalic"/> + <afp-raster-font size="7" characterset="C0N50070" base14-font="TimesBoldItalic"/> + <afp-raster-font size="8" characterset="C0N50080" base14-font="TimesBoldItalic"/> + <afp-raster-font size="9" characterset="C0N50090" base14-font="TimesBoldItalic"/> + <afp-raster-font size="10" characterset="C0N50000" base14-font="TimesBoldItalic"/> + <afp-raster-font size="11" characterset="C0N500A0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="12" characterset="C0N500B0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="14" characterset="C0N500D0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="16" characterset="C0N500F0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="18" characterset="C0N500H0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="20" characterset="C0N500J0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="24" characterset="C0N500N0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="30" characterset="C0N500T0" base14-font="TimesBoldItalic"/> + <afp-raster-font size="36" characterset="C0N500Z0" base14-font="TimesBoldItalic"/> + </afp-font> + <font-triplet name="Times" style="italic" weight="bold"/> + <font-triplet name="TimesRoman" style="italic" weight="bold"/> + <font-triplet name="Times Roman" style="italic" weight="bold"/> + <font-triplet name="Times-Roman" style="italic" weight="bold"/> + <font-triplet name="Times New Roman" style="italic" weight="bold"/> + <font-triplet name="TimesNewRoman" style="italic" weight="bold"/> + <font-triplet name="serif" style="italic" weight="bold"/> + </font> + + <!-- Helvetica --> + <font> + <afp-font name="Helvetica" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0H20060" base14-font="Helvetica"/> + <afp-raster-font size="7" characterset="C0H20070" base14-font="Helvetica"/> + <afp-raster-font size="8" characterset="C0H20080" base14-font="Helvetica"/> + <afp-raster-font size="9" characterset="C0H20090" base14-font="Helvetica"/> + <afp-raster-font size="10" characterset="C0H20000" base14-font="Helvetica"/> + <afp-raster-font size="11" characterset="C0H200A0" base14-font="Helvetica"/> + <afp-raster-font size="12" characterset="C0H200B0" base14-font="Helvetica"/> + <afp-raster-font size="14" characterset="C0H200D0" base14-font="Helvetica"/> + <afp-raster-font size="16" characterset="C0H200F0" base14-font="Helvetica"/> + <afp-raster-font size="18" characterset="C0H200H0" base14-font="Helvetica"/> + <afp-raster-font size="20" characterset="C0H200J0" base14-font="Helvetica"/> + <afp-raster-font size="24" characterset="C0H200N0" base14-font="Helvetica"/> + <afp-raster-font size="30" characterset="C0H200T0" base14-font="Helvetica"/> + <afp-raster-font size="36" characterset="C0H200Z0" base14-font="Helvetica"/> + </afp-font> + <font-triplet name="Helvetica" style="normal" weight="normal"/> + <font-triplet name="Arial" style="normal" weight="normal"/> + <font-triplet name="sans-serif" style="normal" weight="normal"/> + <font-triplet name="any" style="normal" weight="normal"/> + </font> + + <!-- Helvetica Italic --> + <font> + <afp-font name="Helvetica Italic" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0H30060" base14-font="HelveticaOblique"/> + <afp-raster-font size="7" characterset="C0H30070" base14-font="HelveticaOblique"/> + <afp-raster-font size="8" characterset="C0H30080" base14-font="HelveticaOblique"/> + <afp-raster-font size="9" characterset="C0H30090" base14-font="HelveticaOblique"/> + <afp-raster-font size="10" characterset="C0H30000" base14-font="HelveticaOblique"/> + <afp-raster-font size="11" characterset="C0H300A0" base14-font="HelveticaOblique"/> + <afp-raster-font size="12" characterset="C0H300B0" base14-font="HelveticaOblique"/> + <afp-raster-font size="14" characterset="C0H300D0" base14-font="HelveticaOblique"/> + <afp-raster-font size="16" characterset="C0H300F0" base14-font="HelveticaOblique"/> + <afp-raster-font size="18" characterset="C0H300H0" base14-font="HelveticaOblique"/> + <afp-raster-font size="20" characterset="C0H300J0" base14-font="HelveticaOblique"/> + <afp-raster-font size="24" characterset="C0H300N0" base14-font="HelveticaOblique"/> + <afp-raster-font size="30" characterset="C0H300T0" base14-font="HelveticaOblique"/> + <afp-raster-font size="36" characterset="C0H300Z0" base14-font="HelveticaOblique"/> + </afp-font> + <font-triplet name="Helvetica" style="italic" weight="normal"/> + <font-triplet name="Arial" style="italic" weight="normal"/> + <font-triplet name="sans-serif" style="italic" weight="normal"/> + </font> + + <!-- Helvetica (Semi) Bold --> + <font> + <afp-font name="Helvetica (Semi) Bold" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0H40060" base14-font="HelveticaBold"/> + <afp-raster-font size="7" characterset="C0H40070" base14-font="HelveticaBold"/> + <afp-raster-font size="8" characterset="C0H40080" base14-font="HelveticaBold"/> + <afp-raster-font size="9" characterset="C0H40090" base14-font="HelveticaBold"/> + <afp-raster-font size="10" characterset="C0H40000" base14-font="HelveticaBold"/> + <afp-raster-font size="11" characterset="C0H400A0" base14-font="HelveticaBold"/> + <afp-raster-font size="12" characterset="C0H400B0" base14-font="HelveticaBold"/> + <afp-raster-font size="14" characterset="C0H400D0" base14-font="HelveticaBold"/> + <afp-raster-font size="16" characterset="C0H400F0" base14-font="HelveticaBold"/> + <afp-raster-font size="18" characterset="C0H400H0" base14-font="HelveticaBold"/> + <afp-raster-font size="20" characterset="C0H400J0" base14-font="HelveticaBold"/> + <afp-raster-font size="24" characterset="C0H400N0" base14-font="HelveticaBold"/> + <afp-raster-font size="30" characterset="C0H400T0" base14-font="HelveticaBold"/> + <afp-raster-font size="36" characterset="C0H400Z0" base14-font="HelveticaBold"/> + </afp-font> + <font-triplet name="Helvetica" style="normal" weight="bold"/> + <font-triplet name="Arial" style="normal" weight="bold"/> + <font-triplet name="sans-serif" style="normal" weight="bold"/> + </font> + + <!-- Helvetica Italic (Semi) Bold --> + <font> + <afp-font name="Helvetica Italic (Semi) Bold" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0H50060" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="7" characterset="C0H50070" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="8" characterset="C0H50080" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="9" characterset="C0H50090" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="10" characterset="C0H50000" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="11" characterset="C0H500A0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="12" characterset="C0H500B0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="14" characterset="C0H500D0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="16" characterset="C0H500F0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="18" characterset="C0H500H0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="20" characterset="C0H500J0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="24" characterset="C0H500N0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="30" characterset="C0H500T0" base14-font="HelveticaBoldOblique"/> + <afp-raster-font size="36" characterset="C0H500Z0" base14-font="HelveticaBoldOblique"/> + </afp-font> + <font-triplet name="Helvetica" style="italic" weight="bold"/> + <font-triplet name="Arial" style="italic" weight="bold"/> + <font-triplet name="sans-serif" style="italic" weight="bold"/> + </font> + + <!-- Courier --> + <font> + <afp-font name="Courier" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0420060" base14-font="Courier"/> + <afp-raster-font size="7" characterset="C0420070" base14-font="Courier"/> + <afp-raster-font size="8" characterset="C0420080" base14-font="Courier"/> + <afp-raster-font size="9" characterset="C0420090" base14-font="Courier"/> + <afp-raster-font size="10" characterset="C0420000" base14-font="Courier"/> + <afp-raster-font size="11" characterset="C04200A0" base14-font="Courier"/> + <afp-raster-font size="12" characterset="C04200B0" base14-font="Courier"/> + <afp-raster-font size="14" characterset="C04200D0" base14-font="Courier"/> + <afp-raster-font size="16" characterset="C04200F0" base14-font="Courier"/> + <afp-raster-font size="18" characterset="C04200H0" base14-font="Courier"/> + <afp-raster-font size="20" characterset="C04200J0" base14-font="Courier"/> + <afp-raster-font size="24" characterset="C04200N0" base14-font="Courier"/> + <afp-raster-font size="30" characterset="C04200T0" base14-font="Courier"/> + <afp-raster-font size="36" characterset="C04200Z0" base14-font="Courier"/> + </afp-font> + <font-triplet name="Courier" style="normal" weight="normal"/> + <font-triplet name="monospace" style="normal" weight="normal"/> + </font> + + <!-- Courier Italic --> + <font> + <afp-font name="Courier Italic" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0430060" base14-font="CourierOblique"/> + <afp-raster-font size="7" characterset="C0430070" base14-font="CourierOblique"/> + <afp-raster-font size="8" characterset="C0430080" base14-font="CourierOblique"/> + <afp-raster-font size="9" characterset="C0430090" base14-font="CourierOblique"/> + <afp-raster-font size="10" characterset="C0430000" base14-font="CourierOblique"/> + <afp-raster-font size="11" characterset="C04300A0" base14-font="CourierOblique"/> + <afp-raster-font size="12" characterset="C04300B0" base14-font="CourierOblique"/> + <afp-raster-font size="14" characterset="C04300D0" base14-font="CourierOblique"/> + <afp-raster-font size="16" characterset="C04300F0" base14-font="CourierOblique"/> + <afp-raster-font size="18" characterset="C04300H0" base14-font="CourierOblique"/> + <afp-raster-font size="20" characterset="C04300J0" base14-font="CourierOblique"/> + <afp-raster-font size="24" characterset="C04300N0" base14-font="CourierOblique"/> + <afp-raster-font size="30" characterset="C04300T0" base14-font="CourierOblique"/> + <afp-raster-font size="36" characterset="C04300Z0" base14-font="CourierOblique"/> + </afp-font> + <font-triplet name="Courier" style="italic" weight="normal"/> + <font-triplet name="monospace" style="italic" weight="normal"/> + </font> + + <!-- Courier Bold --> + <font> + <afp-font name="Courier Bold" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0440060" base14-font="CourierBold"/> + <afp-raster-font size="7" characterset="C0440070" base14-font="CourierBold"/> + <afp-raster-font size="8" characterset="C0440080" base14-font="CourierBold"/> + <afp-raster-font size="9" characterset="C0440090" base14-font="CourierBold"/> + <afp-raster-font size="10" characterset="C0440000" base14-font="CourierBold"/> + <afp-raster-font size="11" characterset="C04400A0" base14-font="CourierBold"/> + <afp-raster-font size="12" characterset="C04400B0" base14-font="CourierBold"/> + <afp-raster-font size="14" characterset="C04400D0" base14-font="CourierBold"/> + <afp-raster-font size="16" characterset="C04400F0" base14-font="CourierBold"/> + <afp-raster-font size="18" characterset="C04400H0" base14-font="CourierBold"/> + <afp-raster-font size="20" characterset="C04400J0" base14-font="CourierBold"/> + <afp-raster-font size="24" characterset="C04400N0" base14-font="CourierBold"/> + <afp-raster-font size="30" characterset="C04400T0" base14-font="CourierBold"/> + <afp-raster-font size="36" characterset="C04400Z0" base14-font="CourierBold"/> + </afp-font> + <font-triplet name="Courier" style="normal" weight="bold"/> + <font-triplet name="monospace" style="normal" weight="bold"/> + </font> + + <!-- Courier Italic Bold --> + <font> + <afp-font name="Courier Italic Bold" type="raster" codepage="T1V10500" encoding="Cp500"> + <afp-raster-font size="6" characterset="C0450060" base14-font="CourierBoldOblique"/> + <afp-raster-font size="7" characterset="C0450070" base14-font="CourierBoldOblique"/> + <afp-raster-font size="8" characterset="C0450080" base14-font="CourierBoldOblique"/> + <afp-raster-font size="9" characterset="C0450090" base14-font="CourierBoldOblique"/> + <afp-raster-font size="10" characterset="C0450000" base14-font="CourierBoldOblique"/> + <afp-raster-font size="11" characterset="C04500A0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="12" characterset="C04500B0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="14" characterset="C04500D0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="16" characterset="C04500F0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="18" characterset="C04500H0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="20" characterset="C04500J0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="24" characterset="C04500N0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="30" characterset="C04500T0" base14-font="CourierBoldOblique"/> + <afp-raster-font size="36" characterset="C04500Z0" base14-font="CourierBoldOblique"/> + </afp-font> + <font-triplet name="Courier" style="italic" weight="bold"/> + <font-triplet name="monospace" style="italic" weight="bold"/> + </font> + </fonts> + </renderer> + <renderer mime="application/postscript"> <!-- This option forces the PS renderer to rotate landscape pages --> <!--auto-rotate-landscape>true</auto-rotate-landscape--> diff --git a/lib/README.txt b/lib/README.txt index 2f307b2cf..db0c2cdcf 100644 --- a/lib/README.txt +++ b/lib/README.txt @@ -190,4 +190,4 @@ Additional development-time dependencies (not bundled, to be added to your Apache Ant installation) http://xmlunit.sourceforge.net/ - BSD style license
\ No newline at end of file + BSD style license diff --git a/src/documentation/content/xdocs/team.xml b/src/documentation/content/xdocs/team.xml index 777881494..b211c58b0 100644 --- a/src/documentation/content/xdocs/team.xml +++ b/src/documentation/content/xdocs/team.xml @@ -78,6 +78,11 @@ from the TeX/LaTeX world. See his <fork href="http://www.leverkruid.eu">home page</fork> for some of his private projects.</li> <li id="jp"><link href="mailto:pietsch@apache.org">Jörg Pietschmann</link> (JP)</li> + <li id="mb"><link href="mailto:max AT berger DOT name">Max Berger</link> (MB) is currently a + PostDoc pursuing an academic career in computer science. His main interest in FOP is to + improve the DocBook to PDF tool-chain to produce high quality output, while still + conforming to given style-guides. See his <link href="http://max.berger.name">home + page</link> for more information.</li> </ul> </section> <section id="contribute-active"> diff --git a/src/documentation/content/xdocs/trunk/configuration.xml b/src/documentation/content/xdocs/trunk/configuration.xml index 8d6b1f1c8..08463b9b9 100644 --- a/src/documentation/content/xdocs/trunk/configuration.xml +++ b/src/documentation/content/xdocs/trunk/configuration.xml @@ -368,6 +368,36 @@ to "bitmap" which causes all text to be rendered as bitmaps. </p> </section> + <section id="afp-renderer"> + <title>Special Settings for the AFP Renderer</title> + <p> + </p> + <p> + Additionally, there are certain settings that control how the renderer handles various elements. + </p> +<source><![CDATA[<renderer mime="application/x-afp"> + <images mode="b+w" bits-per-pixel="8" native="true"/> + <renderer-resolution>240</renderer-resolution> + + <!-- a default external resource group file --> + <resource-group-file>resources.afp</resource-group-file> +</renderer>]]></source> + <p> + The default value for the images "mode" setting is "b+w" (black and white). When the images "mode" setting is "b+w" a "bits-per-pixel" setting can be provided to aid the grayscale conversion process. With this setting all images referenced in your source document are converted to an IOCA FS45 grayscale bitmap image form. + When the setting is "color" all images are converted to an IOCA FS45 color bitmap image form. When "native" setting is "true", all images encountered (TIFF, GIF, JPEG and Encapsulated Postscript etc.) will be embedded directly in the datastream in their native form using a MO:DCA Object Container. + </p> + <p> + The default value for the "renderer-resolution" is 240 dpi. + </p> + <!-- + <p> + The default value for the MO:DCA "interchange-set" is "MO:DCA-L". Other compliance settings include presentation interchange sets "MO:DCA-P IS/1" and "MO:DCA-P IS/2" (Resource Groups). + </p> + --> + <p> + By default if there is no configuration definition for "resource-group-file", external resources will be placed in a file called resources.afp. + </p> + </section> </section> <section> diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml index b9916e198..d8f396a42 100644 --- a/src/documentation/content/xdocs/trunk/output.xml +++ b/src/documentation/content/xdocs/trunk/output.xml @@ -479,7 +479,7 @@ out = proc.getOutputStream();]]></source> <section id="afp-configuration"> <title>Configuration</title> <section id="afp-font-config"> - <title>Fonts</title> + <title>Fonts</title> <p>The AFP Renderer requires special configuration particularly related to fonts. AFP Render configuration is done through the normal FOP configuration file. The MIME type for the AFP Renderer is application/x-afp which means the AFP Renderer section in the FOP configuration file @@ -615,16 +615,33 @@ out = proc.getOutputStream();]]></source> <section id="afp-image-config"> <title>Images</title> <p>By default the AFP Renderer converts all images to 8 bit grey level. - This can be overridden by the <images> configuration element. Example:</p> + This can be overridden by the <images/> configuration element. Example:</p> <source><![CDATA[ <images mode="color" /> ]]></source> <p>This will put images as RGB images into the AFP output stream. The default setting is:</p> <source><![CDATA[ - <images mode="b+w" bits-per-pixel="8" /> + <images mode="b+w" bits-per-pixel="8" native="true"/> +]]></source> + <p>Only the values "color" and "b+w" are allowed for the mode attribute.</p> + <p>The bits-per-pixel attribute is ignored if mode is "color". For "b+w" mode is must be 1, 4, or 8.</p> + <source><![CDATA[ + <images native="true"/> +]]></source> + <p>When the native attribute is specified and set to "true", all image resources will be natively injected + into the datastream using an object container rather than being converted into an IOCA FS45 image. + Support for native image formats (e.g. JPEG, GIF) is not always available on printer implementations + so by default this configuration option is set to "false".</p> + </section> + <section id="afp-resource-group-file"> + <title>Resource Group File</title> + <p>By default the AFP Renderer will place all data resource objects such as images within + the document of the main output datastream. An external resource group file where document resources + may be specified with the <resource-group-file/> configuration element. Example:</p> + <source><![CDATA[ + <resource-group-file>external_resources.afp</resource-group-file> ]]></source> - <p>Only the values "color" and "b+w" are allowed for the mode attribute. The bits-per-pixel - attribute is ignored if mode is "color". For "b+w" mode is must be 1, 4, or 8.</p> + <note>Be careful when using this option not to overwrite existing resource files from previous rendering runs.</note> </section> </section> <section id="afp-extensions"> @@ -709,6 +726,43 @@ out = proc.getOutputStream();]]></source> </p> </section> </section> + <section id="afp-foreign-attributes"> + <title>Foreign Attributes</title> + <section id="afp-foreign-attributes-resource"> + <title>Resource</title> + <p>The resource foreign attributes provides the ability to name and control where data object resources + (e.g. images/scalable vector graphics) will reside in the AFP output. + The afp foreign attributes are only used in conjuntion with <fo:external-graphic/> and <instream-foreign-object/>. + Example:</p> + <source><![CDATA[ + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" + xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp"> + ... + <fo:block> + <fo:external-graphic width="2.0cm" content-width="2.0cm" height="1.8cm" content-height="1.8cm" + src="examples/fo/graphics/xml_feather.gif" + afp:resource-name="feather" afp:resource-level="external" afp:resource-group-file="resources.afp"/> + </fo:block> + <fo:block> + <fo:instream-foreign-object height="758.047pt" content-height="758.047pt" width="576.96pt" content-width="576.96pt" + afp:resource-name"circles" afp:resource-level="inline"> + <svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm"> + <g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;"> + <circle cx="6cm" cy="2cm" r="100" style="fill:red;" transform="translate(0,50)" /> + <circle cx="6cm" cy="2cm" r="100" style="fill:blue;" transform="translate(70,150)" /> + <circle cx="6cm" cy="2cm" r="100" style="fill:green;" transform="translate(-70,150)"/> + </g> + </svg> + </fo:instream-foreign-object> + </fo:block> +]]></source> + <p>The resource-level attribute where the resource object will reside in the AFP output datastream. + The possible values for this are "inline", "print-file" and "external". + When no resource-level attribute is provided, resources are by default placed at "print-file" level. + When "external" is used a resource-group-file attribute must also be specified.</p> + <p></p> + </section> + </section> </section> <section id="rtf"> <title>RTF</title> diff --git a/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler b/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler new file mode 100644 index 000000000..deab7d259 --- /dev/null +++ b/src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler @@ -0,0 +1,5 @@ +org.apache.fop.render.afp.AFPImageHandlerRenderedImage
+org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax
+org.apache.fop.render.afp.AFPImageHandlerRawStream
+org.apache.fop.render.afp.AFPImageHandlerGraphics2D
+org.apache.fop.render.afp.AFPImageHandlerXML
diff --git a/src/java/org/apache/fop/afp/AFPBorderPainter.java b/src/java/org/apache/fop/afp/AFPBorderPainter.java new file mode 100644 index 000000000..4c56c0def --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPBorderPainter.java @@ -0,0 +1,194 @@ +/* + * 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.afp; + +import java.awt.geom.AffineTransform; + +import org.apache.fop.fo.Constants; +import org.apache.fop.util.ColorUtil; + +/** + * Handles the drawing of borders/lines in AFP + */ +public class AFPBorderPainter extends AbstractAFPPainter { + + /** + * Main constructor + * + * @param paintingState the AFP painting state converter + * @param dataStream the AFP datastream + */ + public AFPBorderPainter(AFPPaintingState paintingState, DataStream dataStream) { + super(paintingState, dataStream); + } + + /** {@inheritDoc} */ + public void paint(PaintingInfo paintInfo) { + BorderPaintingInfo borderPaintInfo = (BorderPaintingInfo)paintInfo; + float w = borderPaintInfo.getX2() - borderPaintInfo.getX1(); + float h = borderPaintInfo.getY2() - borderPaintInfo.getY1(); + if ((w < 0) || (h < 0)) { + log.error("Negative extent received. Border won't be painted."); + return; + } + + int pageWidth = dataStream.getCurrentPage().getWidth(); + int pageHeight = dataStream.getCurrentPage().getHeight(); + AFPUnitConverter unitConv = paintingState.getUnitConverter(); + AffineTransform at = paintingState.getData().getTransform(); + + float x1 = unitConv.pt2units(borderPaintInfo.getX1()); + float y1 = unitConv.pt2units(borderPaintInfo.getY1()); + float x2 = unitConv.pt2units(borderPaintInfo.getX2()); + float y2 = unitConv.pt2units(borderPaintInfo.getY2()); + + switch (paintingState.getRotation()) { + case 0: + x1 += at.getTranslateX(); + y1 += at.getTranslateY(); + x2 += at.getTranslateX(); + y2 += at.getTranslateY(); + break; + case 90: + x1 += at.getTranslateY(); + y1 += (float) (pageWidth - at.getTranslateX()); + x2 += at.getTranslateY(); + y2 += (float) (pageWidth - at.getTranslateX()); + break; + case 180: + x1 += (float) (pageWidth - at.getTranslateX()); + y1 += (float) (pageHeight - at.getTranslateY()); + x2 += (float) (pageWidth - at.getTranslateX()); + y2 += (float) (pageHeight - at.getTranslateY()); + break; + case 270: + x1 = (float) (pageHeight - at.getTranslateY()); + y1 += (float) at.getTranslateX(); + x2 += x1; + y2 += (float) at.getTranslateX(); + break; + } + + AFPLineDataInfo lineDataInfo = new AFPLineDataInfo(); + lineDataInfo.setColor(borderPaintInfo.getColor()); + lineDataInfo.setRotation(paintingState.getRotation()); + lineDataInfo.x1 = Math.round(x1); + lineDataInfo.y1 = Math.round(y1); + if (borderPaintInfo.isHorizontal()) { + lineDataInfo.setThickness(Math.round(y2 - y1)); + } else { + lineDataInfo.setThickness(Math.round(x2 - x1)); + } + + // handle border-*-style + switch (borderPaintInfo.getStyle()) { + case Constants.EN_DOUBLE: + if (borderPaintInfo.isHorizontal()) { + lineDataInfo.x2 = Math.round(x2); + lineDataInfo.y2 = lineDataInfo.y1; + dataStream.createLine(lineDataInfo); + lineDataInfo.y1 += Math.round((lineDataInfo.thickness / 3) * 2); + dataStream.createLine(lineDataInfo); + } else { + lineDataInfo.x2 = lineDataInfo.x1; + lineDataInfo.y2 = Math.round(y2); + dataStream.createLine(lineDataInfo); + lineDataInfo.x1 += Math.round((lineDataInfo.thickness / 3) * 2); + dataStream.createLine(lineDataInfo); + } + break; + case Constants.EN_DASHED: + int thick = lineDataInfo.thickness * 3; + if (borderPaintInfo.isHorizontal()) { + lineDataInfo.x2 = lineDataInfo.x1 + thick; + lineDataInfo.y2 = lineDataInfo.y1; + int ex2 = Math.round(x2); + while (lineDataInfo.x1 + thick < ex2) { + dataStream.createLine(lineDataInfo); + lineDataInfo.x1 += 2 * thick; + lineDataInfo.x2 = lineDataInfo.x1 + thick; + } + } else { + lineDataInfo.x2 = lineDataInfo.x1; + lineDataInfo.y2 = lineDataInfo.y1 + thick; + int ey2 = Math.round(y2); + while (lineDataInfo.y1 + thick < ey2) { + dataStream.createLine(lineDataInfo); + lineDataInfo.y1 += 2 * thick; + lineDataInfo.y2 = lineDataInfo.y1 + thick; + } + } + break; + case Constants.EN_DOTTED: + if (borderPaintInfo.isHorizontal()) { + lineDataInfo.x2 = lineDataInfo.x1 + lineDataInfo.thickness; + lineDataInfo.y2 = lineDataInfo.y1; + int ex2 = Math.round(x2); + while (lineDataInfo.x1 + lineDataInfo.thickness < ex2) { + dataStream.createLine(lineDataInfo); + lineDataInfo.x1 += 3 * lineDataInfo.thickness; + lineDataInfo.x2 = lineDataInfo.x1 + lineDataInfo.thickness; + } + } else { + lineDataInfo.x2 = lineDataInfo.x1; + lineDataInfo.y2 = lineDataInfo.y1 + lineDataInfo.thickness; + int ey2 = Math.round(y2); + while (lineDataInfo.y1 + lineDataInfo.thickness < ey2) { + dataStream.createLine(lineDataInfo); + lineDataInfo.y1 += 3 * lineDataInfo.thickness; + lineDataInfo.y2 = lineDataInfo.y1 + lineDataInfo.thickness; + } + } + break; + case Constants.EN_GROOVE: + case Constants.EN_RIDGE: + //TODO + lineDataInfo.x2 = Math.round(x2); + float colFactor = (borderPaintInfo.getStyle() == Constants.EN_GROOVE ? 0.4f : -0.4f); + float h3 = (y2 - y1) / 3; + lineDataInfo.color = ColorUtil.lightenColor(borderPaintInfo.getColor(), -colFactor); + lineDataInfo.thickness = Math.round(h3); + lineDataInfo.y1 = lineDataInfo.y2 = Math.round(y1); + dataStream.createLine(lineDataInfo); + lineDataInfo.color = borderPaintInfo.getColor(); + lineDataInfo.y1 = lineDataInfo.y2 = Math.round(y1 + h3); + dataStream.createLine(lineDataInfo); + lineDataInfo.color = ColorUtil.lightenColor(borderPaintInfo.getColor(), colFactor); + lineDataInfo.y1 = lineDataInfo.y2 = Math.round(y1 + h3 + h3); + dataStream.createLine(lineDataInfo); + break; + case Constants.EN_HIDDEN: + break; + case Constants.EN_INSET: + case Constants.EN_OUTSET: + case Constants.EN_SOLID: + default: + if (borderPaintInfo.isHorizontal()) { + lineDataInfo.x2 = Math.round(x2); + lineDataInfo.y2 = lineDataInfo.y1; + } else { + lineDataInfo.x2 = lineDataInfo.x1; + lineDataInfo.y2 = Math.round(y2); + } + dataStream.createLine(lineDataInfo); + } + } + +} diff --git a/src/java/org/apache/fop/render/afp/modca/AFPConstants.java b/src/java/org/apache/fop/afp/AFPConstants.java index 73c39f2f0..3462ddfe6 100644 --- a/src/java/org/apache/fop/render/afp/modca/AFPConstants.java +++ b/src/java/org/apache/fop/afp/AFPConstants.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp; /** * Constants used by the AFP renderer. @@ -34,4 +34,20 @@ public interface AFPConstants { * The encoding to use to convert to ASCII */ String ASCII_ENCODING = "Cp1252"; + + /** + * The encoding to use to convert to US ASCII (7 bit) + */ + String US_ASCII_ENCODING = "US-ASCII"; + + /** + * The scaling of the default transform is set to + * approximately 72 user space coordinates per square inch + */ + int DPI_72 = 72; + + /** + * 72dpi in millipoints + */ + int DPI_72_MPTS = DPI_72 * 1000; } diff --git a/src/java/org/apache/fop/afp/AFPDataObjectFactory.java b/src/java/org/apache/fop/afp/AFPDataObjectFactory.java new file mode 100644 index 000000000..80cb40713 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPDataObjectFactory.java @@ -0,0 +1,272 @@ +/* + * 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.afp; + +import java.awt.geom.Rectangle2D; + +import org.apache.fop.afp.ioca.ImageContent; +import org.apache.fop.afp.modca.AbstractDataObject; +import org.apache.fop.afp.modca.AbstractNamedAFPObject; +import org.apache.fop.afp.modca.Document; +import org.apache.fop.afp.modca.GraphicsObject; +import org.apache.fop.afp.modca.ImageObject; +import org.apache.fop.afp.modca.IncludeObject; +import org.apache.fop.afp.modca.ObjectContainer; +import org.apache.fop.afp.modca.Overlay; +import org.apache.fop.afp.modca.PageSegment; +import org.apache.fop.afp.modca.Registry; +import org.apache.fop.afp.modca.ResourceObject; +import org.apache.fop.afp.modca.triplets.MappingOptionTriplet; +import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + +/** + * Factory for high level data objects (Image/Graphics etc) + */ +public class AFPDataObjectFactory { + + private final Factory factory; + + /** + * Main constructor + * + * @param factory an object factory + */ + public AFPDataObjectFactory(Factory factory) { + this.factory = factory; + } + + /** + * Creates and configures an ObjectContainer. + * + * @param dataObjectInfo the object container info + * @return a newly created Object Container + */ + public ObjectContainer createObjectContainer(AFPDataObjectInfo dataObjectInfo) { + ObjectContainer objectContainer = factory.createObjectContainer(); + + // set data object viewport (i.e. position, rotation, dimension, resolution) + objectContainer.setViewport(dataObjectInfo); + + // set object classification + Registry.ObjectType objectType = dataObjectInfo.getObjectType(); + AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + AFPResourceLevel resourceLevel = resourceInfo.getLevel(); + final boolean dataInContainer = true; + final boolean containerHasOEG = resourceLevel.isInline(); + final boolean dataInOCD = true; + objectContainer.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, + objectType, dataInContainer, containerHasOEG, dataInOCD); + + objectContainer.setData(dataObjectInfo.getData()); + return objectContainer; + } + + /** + * Creates and configures an IOCA Image Object. + * + * @param imageObjectInfo the image object info + * @return a newly created IOCA Image Object + */ + public ImageObject createImage(AFPImageObjectInfo imageObjectInfo) { + // IOCA bitmap image + ImageObject imageObj = factory.createImageObject(); + + // set data object viewport (i.e. position, rotation, dimension, resolution) + imageObj.setViewport(imageObjectInfo); + + if (imageObjectInfo.hasCompression()) { + int compression = imageObjectInfo.getCompression(); + switch (compression) { + case TIFFImage.COMP_FAX_G3_1D: + imageObj.setEncoding(ImageContent.COMPID_G3_MH); + break; + case TIFFImage.COMP_FAX_G3_2D: + imageObj.setEncoding(ImageContent.COMPID_G3_MR); + break; + case TIFFImage.COMP_FAX_G4_2D: + imageObj.setEncoding(ImageContent.COMPID_G3_MMR); + break; + default: + throw new IllegalStateException( + "Invalid compression scheme: " + compression); + } + } + + if (imageObjectInfo.isColor()) { + imageObj.setIDESize((byte) 24); + } else { + imageObj.setIDESize((byte) imageObjectInfo.getBitsPerPixel()); + } + + imageObj.setData(imageObjectInfo.getData()); + + return imageObj; + } + + /** + * Creates and returns a new graphics object. + * + * @param graphicsObjectInfo the graphics object info + * @return a new graphics object + */ + public GraphicsObject createGraphic(AFPGraphicsObjectInfo graphicsObjectInfo) { + // set newly created graphics object in g2d + GraphicsObject graphicsObj = factory.createGraphicsObject(); + + // set data object viewport (i.e. position, rotation, dimension, resolution) + graphicsObj.setViewport(graphicsObjectInfo); + + AFPGraphics2D g2d = graphicsObjectInfo.getGraphics2D(); + g2d.setGraphicsObject(graphicsObj); + + // paint to graphics object + Graphics2DImagePainter painter = graphicsObjectInfo.getPainter(); + Rectangle2D area = graphicsObjectInfo.getArea(); + g2d.scale(1, -1); + g2d.translate(0, -area.getHeight()); + + painter.paint(g2d, area); + + graphicsObj.setComplete(true); + + // return painted graphics object + return graphicsObj; + } + + /** + * Creates and returns a new include object. + * + * @param includeName the include name + * @param dataObjectInfo a data object info + * + * @return a new include object + */ + public IncludeObject createInclude(String includeName, AFPDataObjectInfo dataObjectInfo) { + IncludeObject includeObj = factory.createInclude(includeName); + + if (dataObjectInfo instanceof AFPImageObjectInfo) { + // IOCA image object + includeObj.setObjectType(IncludeObject.TYPE_IMAGE); + } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) { + // graphics object + includeObj.setObjectType(IncludeObject.TYPE_GRAPHIC); + } else { + // object container + includeObj.setObjectType(IncludeObject.TYPE_OTHER); + + // set mandatory object classification (type other) + Registry.ObjectType objectType = dataObjectInfo.getObjectType(); + if (objectType != null) { + // set object classification + final boolean dataInContainer = true; + final boolean containerHasOEG = false; // environment parameters set in include + final boolean dataInOCD = true; + includeObj.setObjectClassification( + // object scope not defined + ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT, + objectType, dataInContainer, containerHasOEG, dataInOCD); + } else { + throw new IllegalStateException( + "Failed to set Object Classification Triplet on Object Container."); + } + } + + AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); + + int xOffset = objectAreaInfo.getX(); + int yOffset = objectAreaInfo.getY(); + includeObj.setObjectAreaOffset(xOffset, yOffset); + + int width = objectAreaInfo.getWidth(); + int height = objectAreaInfo.getHeight(); + includeObj.setObjectAreaSize(width, height); + + int rotation = objectAreaInfo.getRotation(); + includeObj.setObjectAreaOrientation(rotation); + + int widthRes = objectAreaInfo.getWidthRes(); + int heightRes = objectAreaInfo.getHeightRes(); + includeObj.setMeasurementUnits(widthRes, heightRes); + + includeObj.setMappingOption(MappingOptionTriplet.SCALE_TO_FIT); + + return includeObj; + } + + /** + * Creates a resource object wrapper for named includable data objects + * + * @param namedObj an named object + * @param resourceInfo resource information + * @param objectType the object type + * @return a new resource object wrapper + */ + public ResourceObject createResource(AbstractNamedAFPObject namedObj, + AFPResourceInfo resourceInfo, Registry.ObjectType objectType) { + ResourceObject resourceObj = null; + String resourceName = resourceInfo.getName(); + if (resourceName != null) { + resourceObj = factory.createResource(resourceName); + } else { + resourceObj = factory.createResource(); + } + + if (namedObj instanceof Document) { + resourceObj.setType(ResourceObject.TYPE_DOCUMENT); + } else if (namedObj instanceof PageSegment) { + resourceObj.setType(ResourceObject.TYPE_PAGE_SEGMENT); + } else if (namedObj instanceof Overlay) { + resourceObj.setType(ResourceObject.TYPE_OVERLAY_OBJECT); + } else if (namedObj instanceof AbstractDataObject) { + AbstractDataObject dataObj = (AbstractDataObject)namedObj; + if (namedObj instanceof ObjectContainer) { + resourceObj.setType(ResourceObject.TYPE_OBJECT_CONTAINER); + + // set object classification + final boolean dataInContainer = true; + final boolean containerHasOEG = false; // must be included + final boolean dataInOCD = true; + // mandatory triplet for object container + resourceObj.setObjectClassification( + ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT, + objectType, dataInContainer, containerHasOEG, dataInOCD); + } else if (namedObj instanceof ImageObject) { + // ioca image type + resourceObj.setType(ResourceObject.TYPE_IMAGE); + } else if (namedObj instanceof GraphicsObject) { + resourceObj.setType(ResourceObject.TYPE_GRAPHIC); + } else { + throw new UnsupportedOperationException( + "Unsupported resource object for data object type " + dataObj); + } + } else { + throw new UnsupportedOperationException( + "Unsupported resource object type " + namedObj); + } + + // set the resource information/classification on the data object + resourceObj.setDataObject(namedObj); + return resourceObj; + } + +} diff --git a/src/java/org/apache/fop/afp/AFPDataObjectInfo.java b/src/java/org/apache/fop/afp/AFPDataObjectInfo.java new file mode 100644 index 000000000..f6ff0046a --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPDataObjectInfo.java @@ -0,0 +1,247 @@ +/* + * 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.afp; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.modca.Registry; + +/** + * A list of parameters associated with an AFP data objects + */ +public class AFPDataObjectInfo { + private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp"); + + /** the object area info */ + private AFPObjectAreaInfo objectAreaInfo; + + /** resource info */ + private AFPResourceInfo resourceInfo; + + /** the data object width */ + private int dataWidth; + + /** the data object height */ + private int dataHeight; + + /** the object registry mimetype */ + private String mimeType; + + /** the object data in a byte array */ + private byte[] data; + + /** the object data height resolution */ + private int dataHeightRes; + + /** the object data width resolution */ + private int dataWidthRes; + + /** + * Default constructor + */ + public AFPDataObjectInfo() { + } + + /** + * Sets the image mime type + * + * @param mimeType the image mime type + */ + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + /** + * Returns the mime type of this data object + * + * @return the mime type of this data object + */ + public String getMimeType() { + return mimeType; + } + + /** + * Convenience method to return the object type + * + * @return the object type + */ + public Registry.ObjectType getObjectType() { + return Registry.getInstance().getObjectType(getMimeType()); + } + + /** + * Returns the resource level at which this data object should reside + * + * @return the resource level at which this data object should reside + */ + public AFPResourceInfo getResourceInfo() { + if (resourceInfo == null) { + this.resourceInfo = new AFPResourceInfo(); + } + return resourceInfo; + } + + /** + * Sets the resource level at which this object should reside + * + * @param resourceInfo the resource level at which this data object should reside + */ + public void setResourceInfo(AFPResourceInfo resourceInfo) { + this.resourceInfo = resourceInfo; + } + + /** + * Sets the object area info + * + * @param objectAreaInfo the object area info + */ + public void setObjectAreaInfo(AFPObjectAreaInfo objectAreaInfo) { + this.objectAreaInfo = objectAreaInfo; + } + + /** + * Returns the object area info + * + * @return the object area info + */ + public AFPObjectAreaInfo getObjectAreaInfo() { + return this.objectAreaInfo; + } + + /** + * Returns the uri of this data object + * + * @return the uri of this data object + */ + public String getUri() { + return getResourceInfo().getUri(); + } + + /** + * Sets the data object uri + * + * @param uri the data object uri + */ + public void setUri(String uri) { + getResourceInfo().setUri(uri); + } + + /** + * Returns the image data width + * + * @return the image data width + */ + public int getDataWidth() { + return dataWidth; + } + + /** + * Sets the image data width + * + * @param imageDataWidth the image data width + */ + public void setDataWidth(int imageDataWidth) { + this.dataWidth = imageDataWidth; + } + + /** + * Returns the image data height + * + * @return the image data height + */ + public int getDataHeight() { + return dataHeight; + } + + /** + * Sets the image data height + * + * @param imageDataHeight the image data height + */ + public void setDataHeight(int imageDataHeight) { + this.dataHeight = imageDataHeight; + } + + /** + * Returns the data height resolution + * + * @return the data height resolution + */ + public int getDataHeightRes() { + return this.dataHeightRes; + } + + /** + * Sets the data width resolution + * + * @param dataWidthRes the data width resolution + */ + public void setDataHeightRes(int dataHeightRes) { + this.dataHeightRes = dataHeightRes; + } + + /** + * Returns the data width resolution + * + * @return the data width resolution + */ + public int getDataWidthRes() { + return this.dataWidthRes; + } + + /** + * Sets the data width resolution + * + * @param dataWidthRes the data width resolution + */ + public void setDataWidthRes(int dataWidthRes) { + this.dataWidthRes = dataWidthRes; + } + + /** + * Sets the object data + * + * @param data the object data + */ + public void setData(byte[] data) { + this.data = data; + } + + /** + * Returns the object data + * + * @return the object data + */ + public byte[] getData() { + return this.data; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPDataObjectInfo{" + + "mimeType=" + mimeType + + ", dataWidth=" + dataWidth + + ", dataHeight=" + dataHeight + + ", dataWidthRes=" + dataWidthRes + + ", dataHeightRes=" + dataHeightRes + + (objectAreaInfo != null ? ", objectAreaInfo=" + objectAreaInfo : "") + + (resourceInfo != null ? ", resourceInfo=" + resourceInfo : ""); + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPEventProducer.java b/src/java/org/apache/fop/afp/AFPEventProducer.java index 08641b20e..49792183f 100644 --- a/src/java/org/apache/fop/render/afp/AFPEventProducer.java +++ b/src/java/org/apache/fop/afp/AFPEventProducer.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp; +package org.apache.fop.afp; import org.apache.fop.events.EventBroadcaster; import org.apache.fop.events.EventProducer; @@ -55,9 +55,29 @@ public interface AFPEventProducer extends EventProducer { /** * Warn about using default font setup. + * * @param source the event source * @event.severity WARN */ void warnDefaultFontSetup(Object source); + /** + * Warn about a missing default "any" font configuration. + * + * @param source the event source + * @param style the font style + * @param weight the font weight + * @event.severity WARN + */ + void warnMissingDefaultFont(Object source, String style, int weight); + + /** + * A character set encoding error occurred. + * + * @param source the event source + * @param charSetName the character set name + * @param encoding the encoding + * @event.severity ERROR + */ + void characterSetEncodingError(Object source, String charSetName, String encoding); } diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.xml b/src/java/org/apache/fop/afp/AFPEventProducer.xml new file mode 100644 index 000000000..8e6bb5429 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPEventProducer.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<catalogue xml:lang="en"> + <message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup">No AFP fonts configured. Using default setup.</message> + <message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont">No AFP default "any", {style}, {weight} font configured.</message> + <message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError">An error occurred when attempting to encode character set {charSetName} with encoding scheme {encoding}.</message> +</catalogue> diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java new file mode 100644 index 000000000..ee160feca --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java @@ -0,0 +1,698 @@ +/* + * 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.afp; + +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.TexturePaint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Line2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.io.IOException; + +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.goca.GraphicsSetLineType; +import org.apache.fop.afp.modca.GraphicsObject; +import org.apache.fop.afp.svg.AFPGraphicsConfiguration; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.svg.NativeImageHandler; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.java2d.AbstractGraphics2D; +import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.StrokingTextHandler; +import org.apache.xmlgraphics.java2d.TextHandler; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and + * therefore of <tt>Graphics2D</tt>) which is able to generate GOCA byte + * codes. + * + * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D + */ +public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHandler { + + private static final Log log = LogFactory.getLog(AFPGraphics2D.class); + + private static final int X = 0; + + private static final int Y = 1; + + private static final int X1 = 0; + + private static final int Y1 = 1; + + private static final int X2 = 2; + + private static final int Y2 = 3; + + private static final int X3 = 4; + + private static final int Y3 = 5; + + /** graphics object */ + private GraphicsObject graphicsObj = null; + + /** Fallback text handler */ + protected TextHandler fallbackTextHandler = new StrokingTextHandler(); + + /** Custom text handler */ + protected TextHandler customTextHandler = null; + + /** AFP resource manager */ + private AFPResourceManager resourceManager = null; + + /** AFP resource info */ + private AFPResourceInfo resourceInfo = null; + + /** Current AFP state */ + private AFPPaintingState paintingState = null; + + /** AFP graphics configuration */ + private final AFPGraphicsConfiguration graphicsConfig = new AFPGraphicsConfiguration(); + + /** The AFP FontInfo */ + private FontInfo fontInfo; + + /** + * Main constructor + * + * @param textAsShapes + * if true, all text is turned into shapes in the convertion. No + * text is output. + * @param paintingState painting state + * @param resourceManager resource manager + * @param resourceInfo resource info + * @param fontInfo font info + */ + public AFPGraphics2D(boolean textAsShapes, AFPPaintingState paintingState, + AFPResourceManager resourceManager, AFPResourceInfo resourceInfo, + FontInfo fontInfo) { + super(textAsShapes); + this.paintingState = paintingState; + this.resourceManager = resourceManager; + this.resourceInfo = resourceInfo; + this.fontInfo = fontInfo; + } + + /** + * Copy Constructor + * + * @param g2d + * a AFPGraphics2D whose properties should be copied + */ + public AFPGraphics2D(AFPGraphics2D g2d) { + super(g2d); + this.paintingState = g2d.paintingState; + this.resourceManager = g2d.resourceManager; + this.resourceInfo = g2d.resourceInfo; + this.fontInfo = g2d.fontInfo; + + this.graphicsObj = g2d.graphicsObj; + this.fallbackTextHandler = g2d.fallbackTextHandler; + this.customTextHandler = g2d.customTextHandler; + } + + /** + * Sets the AFP resource manager + * + * @param resourceManager the AFP resource manager + */ + public void setResourceManager(AFPResourceManager resourceManager) { + this.resourceManager = resourceManager; + } + + /** + * Sets the AFP resource info + * + * @param resourceInfo the AFP resource info + */ + public void setResourceInfo(AFPResourceInfo resourceInfo) { + this.resourceInfo = resourceInfo; + } + + /** + * Sets the GraphicContext + * + * @param gc + * GraphicContext to use + */ + public void setGraphicContext(GraphicContext gc) { + this.gc = gc; + } + + /** + * Apply the stroke to the AFP graphics object. + * This takes the java stroke and outputs the appropriate settings + * to the AFP graphics object so that the stroke attributes are handled. + * + * @param stroke the java stroke + */ + protected void applyStroke(Stroke stroke) { + if (stroke instanceof BasicStroke) { + BasicStroke basicStroke = (BasicStroke) stroke; + + // set line width + float lineWidth = basicStroke.getLineWidth(); + graphicsObj.setLineWidth(Math.round(lineWidth / 2)); + + // set line type/style (note: this is an approximation at best!) + float[] dashArray = basicStroke.getDashArray(); + if (paintingState.setDashArray(dashArray)) { + byte type = GraphicsSetLineType.DEFAULT; // normally SOLID + if (dashArray != null) { + type = GraphicsSetLineType.DOTTED; // default to plain DOTTED if dashed line + // float offset = basicStroke.getDashPhase(); + if (dashArray.length == 2) { + if (dashArray[0] < dashArray[1]) { + type = GraphicsSetLineType.SHORT_DASHED; + } else if (dashArray[0] > dashArray[1]) { + type = GraphicsSetLineType.LONG_DASHED; + } + } else if (dashArray.length == 4) { + if (dashArray[0] > dashArray[1] + && dashArray[2] < dashArray[3]) { + type = GraphicsSetLineType.DASH_DOT; + } else if (dashArray[0] < dashArray[1] + && dashArray[2] < dashArray[3]) { + type = GraphicsSetLineType.DOUBLE_DOTTED; + } + } else if (dashArray.length == 6) { + if (dashArray[0] > dashArray[1] + && dashArray[2] < dashArray[3] + && dashArray[4] < dashArray[5]) { + type = GraphicsSetLineType.DASH_DOUBLE_DOTTED; + } + } + } + graphicsObj.setLineType(type); + } + } else { + log.warn("Unsupported Stroke: " + stroke.getClass().getName()); + } + } + + /** + * Apply the java paint to the AFP. + * This takes the java paint sets up the appropriate AFP commands + * for the drawing with that paint. + * Currently this supports the gradients and patterns from batik. + * + * @param paint the paint to convert to AFP + * @param fill true if the paint should be set for filling + * @return true if the paint is handled natively, false if the paint should be rasterized + */ + private boolean applyPaint(Paint paint, boolean fill) { + if (paint instanceof Color) { + return true; + } + log.debug("NYI: applyPaint() " + paint + " fill=" + fill); + if (paint instanceof TexturePaint) { +// TexturePaint texturePaint = (TexturePaint)paint; +// BufferedImage bufferedImage = texturePaint.getImage(); +// AffineTransform at = paintingState.getTransform(); +// int x = (int)Math.round(at.getTranslateX()); +// int y = (int)Math.round(at.getTranslateY()); +// drawImage(bufferedImage, x, y, null); + } + return false; + } + + + /** + * Handle the Batik drawing event + * + * @param shape + * the shape to draw + * @param fill + * true if the shape is to be drawn filled + */ + private void doDrawing(Shape shape, boolean fill) { + if (!fill) { + graphicsObj.newSegment(); + } + + graphicsObj.setColor(gc.getColor()); + + applyPaint(gc.getPaint(), fill); + + if (fill) { + graphicsObj.beginArea(); + } else { + applyStroke(gc.getStroke()); + } + + AffineTransform trans = gc.getTransform(); + PathIterator iter = shape.getPathIterator(trans); + if (shape instanceof Line2D) { + double[] dstPts = new double[6]; + iter.currentSegment(dstPts); + int[] coords = new int[4]; + coords[X1] = (int) Math.round(dstPts[X]); + coords[Y1] = (int) Math.round(dstPts[Y]); + iter.next(); + iter.currentSegment(dstPts); + coords[X2] = (int) Math.round(dstPts[X]); + coords[Y2] = (int) Math.round(dstPts[Y]); + graphicsObj.addLine(coords); + } else if (shape instanceof Rectangle2D) { + double[] dstPts = new double[6]; + iter.currentSegment(dstPts); + int[] coords = new int[4]; + coords[X2] = (int) Math.round(dstPts[X]); + coords[Y2] = (int) Math.round(dstPts[Y]); + iter.next(); + iter.next(); + iter.currentSegment(dstPts); + coords[X1] = (int) Math.round(dstPts[X]); + coords[Y1] = (int) Math.round(dstPts[Y]); + graphicsObj.addBox(coords); + } else if (shape instanceof Ellipse2D) { + double[] dstPts = new double[6]; + Ellipse2D elip = (Ellipse2D) shape; + double scale = trans.getScaleX(); + double radiusWidth = elip.getWidth() / 2; + double radiusHeight = elip.getHeight() / 2; + graphicsObj.setArcParams( + (int)Math.round(radiusWidth * scale), + (int)Math.round(radiusHeight * scale), + 0, + 0 + ); + double[] srcPts = new double[] {elip.getCenterX(), elip.getCenterY()}; + trans.transform(srcPts, 0, dstPts, 0, 1); + final int mh = 1; + final int mhr = 0; + graphicsObj.addFullArc( + (int)Math.round(dstPts[X]), + (int)Math.round(dstPts[Y]), + mh, + mhr + ); + } else { + processPathIterator(iter); + } + + if (fill) { + graphicsObj.endArea(); + } + } + + /** + * Processes a path iterator generating the necessary painting operations. + * + * @param iter PathIterator to process + */ + private void processPathIterator(PathIterator iter) { + double[] dstPts = new double[6]; + for (int[] openingCoords = new int[2]; !iter.isDone(); iter.next()) { + switch (iter.currentSegment(dstPts)) { + case PathIterator.SEG_LINETO: + graphicsObj.addLine(new int[] { + (int)Math.round(dstPts[X]), + (int)Math.round(dstPts[Y]) + }, true); + break; + case PathIterator.SEG_QUADTO: + graphicsObj.addFillet(new int[] { + (int)Math.round(dstPts[X1]), + (int)Math.round(dstPts[Y1]), + (int)Math.round(dstPts[X2]), + (int)Math.round(dstPts[Y2]) + }, true); + break; + case PathIterator.SEG_CUBICTO: + graphicsObj.addFillet(new int[] { + (int)Math.round(dstPts[X1]), + (int)Math.round(dstPts[Y1]), + (int)Math.round(dstPts[X2]), + (int)Math.round(dstPts[Y2]), + (int)Math.round(dstPts[X3]), + (int)Math.round(dstPts[Y3]) + }, true); + break; + case PathIterator.SEG_MOVETO: + openingCoords = new int[] { + (int)Math.round(dstPts[X]), + (int)Math.round(dstPts[Y]) + }; + graphicsObj.setCurrentPosition(openingCoords); + break; + case PathIterator.SEG_CLOSE: + graphicsObj.addLine(openingCoords, true); + break; + default: + log.debug("Unrecognised path iterator type"); + break; + } + } + } + + /** {@inheritDoc} */ + public void draw(Shape shape) { + log.debug("draw() shape=" + shape); + doDrawing(shape, false); + } + + /** {@inheritDoc} */ + public void fill(Shape shape) { + log.debug("fill() shape=" + shape); + doDrawing(shape, true); + } + + /** + * Central handler for IOExceptions for this class. + * + * @param ioe + * IOException to handle + */ + public void handleIOException(IOException ioe) { + // TODO Surely, there's a better way to do this. + log.error(ioe.getMessage()); + ioe.printStackTrace(); + } + + /** {@inheritDoc} */ + public void drawString(String str, float x, float y) { + try { + if (customTextHandler != null && !textAsShapes) { + customTextHandler.drawString(this, str, x, y); + } else { + fallbackTextHandler.drawString(this, str, x, y); + } + } catch (IOException ioe) { + handleIOException(ioe); + } + } + + /** {@inheritDoc} */ + public GraphicsConfiguration getDeviceConfiguration() { + return graphicsConfig; + } + + /** {@inheritDoc} */ + public Graphics create() { + return new AFPGraphics2D(this); + } + + /** {@inheritDoc} */ + public void dispose() { + this.graphicsObj = null; + } + + /** {@inheritDoc} */ + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer); + } + + private BufferedImage buildBufferedImage(Dimension size) { + return new BufferedImage(size.width, size.height, + BufferedImage.TYPE_INT_ARGB); + } + + private AFPImageObjectInfo createImageObjectInfo( + RenderedImage img, int x, int y, int width, int height) throws IOException { + ImageInfo imageInfo = new ImageInfo(null, "image/unknown"); + ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72); + imageInfo.setSize(size); + + ImageRendered imageRendered = new ImageRendered(imageInfo, img, null); + RenderedImage renderedImage = imageRendered.getRenderedImage(); + + // create image object info + AFPImageObjectInfo imageObjectInfo = new AFPImageObjectInfo(); + + imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45); + + int bitsPerPixel = paintingState.getBitsPerPixel(); + imageObjectInfo.setBitsPerPixel(bitsPerPixel); + + imageObjectInfo.setResourceInfo(resourceInfo); + + int dataHeight = renderedImage.getHeight(); + imageObjectInfo.setDataHeight(dataHeight); + + int dataWidth = renderedImage.getWidth(); + imageObjectInfo.setDataWidth(dataWidth); + + boolean colorImages = paintingState.isColorImages(); + imageObjectInfo.setColor(colorImages); + + ByteArrayOutputStream boas = new ByteArrayOutputStream(); + ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, boas); + byte[] imageData = boas.toByteArray(); + + // convert to grayscale + if (!colorImages) { + boas.reset(); + imageObjectInfo.setBitsPerPixel(bitsPerPixel); + ImageEncodingHelper.encodeRGBAsGrayScale( + imageData, dataWidth, dataHeight, bitsPerPixel, boas); + imageData = boas.toByteArray(); + } + imageObjectInfo.setData(imageData); + + if (imageInfo != null) { + imageObjectInfo.setUri(imageInfo.getOriginalURI()); + } + + // create object area info + AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); + objectAreaInfo.setX(x); + objectAreaInfo.setY(y); + objectAreaInfo.setWidth(width); + objectAreaInfo.setHeight(height); + + int resolution = paintingState.getResolution(); + objectAreaInfo.setWidthRes(resolution); + objectAreaInfo.setHeightRes(resolution); + + imageObjectInfo.setObjectAreaInfo(objectAreaInfo); + + return imageObjectInfo; + } + + /** + * Draws an AWT image into a BufferedImage using an AWT Graphics2D implementation + * + * @param img the AWT image + * @param bufferedImage the AWT buffered image + * @param width the image width + * @param height the image height + * @param observer the image observer + * @return true if the image was drawn + */ + private boolean drawBufferedImage(Image img, BufferedImage bufferedImage, + int width, int height, ImageObserver observer) { + + java.awt.Graphics2D g2d = bufferedImage.createGraphics(); + try { + g2d.setComposite(AlphaComposite.SrcOver); + + Color color = new Color(1, 1, 1, 0); + g2d.setBackground(color); + g2d.setPaint(color); + + g2d.fillRect(0, 0, width, height); + + int imageWidth = bufferedImage.getWidth(); + int imageHeight = bufferedImage.getHeight(); + Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight); + g2d.clip(clipRect); + + g2d.setComposite(gc.getComposite()); + + return g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer); + } finally { + g2d.dispose(); //drawn so dispose immediately to free system resource + } + } + + /** {@inheritDoc} */ + public boolean drawImage(Image img, int x, int y, int width, int height, + ImageObserver observer) { + + // draw with AWT Graphics2D + Dimension imageSize = new Dimension(width, height); + BufferedImage bufferedImage = buildBufferedImage(imageSize); + + boolean drawn = drawBufferedImage(img, bufferedImage, width, height, observer); + if (drawn) { + AffineTransform at = gc.getTransform(); + float[] srcPts = new float[] {x, y}; + float[] dstPts = new float[srcPts.length]; + at.transform(srcPts, 0, dstPts, 0, 1); + x = Math.round(dstPts[X]); + y = Math.round(dstPts[Y]); + try { + // get image object info + AFPImageObjectInfo imageObjectInfo + = createImageObjectInfo(bufferedImage, x, y, width, height); + + // create image resource + resourceManager.createObject(imageObjectInfo); + return true; + } catch (IOException ioe) { + handleIOException(ioe); + } + } + return false; + } + + /** {@inheritDoc} */ + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + int imgWidth = img.getWidth(); + int imgHeight = img.getHeight(); + + AffineTransform at = paintingState.getData().getTransform(); + AffineTransform gat = gc.getTransform(); + int graphicsObjectHeight + = graphicsObj.getObjectEnvironmentGroup().getObjectAreaDescriptor().getHeight(); + int x = (int)Math.round(at.getTranslateX() + gat.getTranslateX()); + int y = (int)Math.round(at.getTranslateY() - (gat.getTranslateY() - graphicsObjectHeight)); + int width = (int)Math.round(imgWidth * gat.getScaleX()); + int height = (int)Math.round(imgHeight * -gat.getScaleY()); + try { + // get image object info + AFPImageObjectInfo imageObjectInfo + = createImageObjectInfo(img, x, y, width, height); + // create image resource + resourceManager.createObject(imageObjectInfo); + } catch (IOException ioe) { + handleIOException(ioe); + } + } + + /** + * Sets a custom TextHandler implementation that is responsible for painting + * text. The default TextHandler paints all text as shapes. A custom + * implementation can implement text painting using text painting operators. + * + * @param handler + * the custom TextHandler implementation + */ + public void setCustomTextHandler(TextHandler handler) { + this.customTextHandler = handler; + } + + /** + * Returns the GOCA graphics object + * + * @return the GOCA graphics object + */ + public GraphicsObject getGraphicsObject() { + return this.graphicsObj; + } + + /** + * Sets the GOCA graphics object + * + * @param obj the GOCA graphics object + */ + public void setGraphicsObject(GraphicsObject obj) { + this.graphicsObj = obj; + } + + /** + * Sets the AFP painting state + * + * @param paintingState the AFP painting state + */ + public void setPaintingState(AFPPaintingState paintingState) { + this.paintingState = paintingState; + } + + /** + * Returns the AFP painting state + * + * @return the AFP painting state + */ + public AFPPaintingState getPaintingState() { + return this.paintingState; + } + + /** + * Sets the FontInfo + * + * @param the FontInfo + */ + public void setFontInfo(FontInfo fontInfo) { + this.fontInfo = fontInfo; + } + + /** + * Returns the FontInfo + * + * @return the FontInfo + */ + public FontInfo getFontInfo() { + return this.fontInfo; + } + + /** {@inheritDoc} */ + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform); + } + + /** {@inheritDoc} */ + public FontMetrics getFontMetrics(Font f) { + log.debug("getFontMetrics() NYI: f=" + f); + return null; + } + + /** {@inheritDoc} */ + public void setXORMode(Color col) { + log.debug("setXORMode() NYI: col=" + col); + } + + /** {@inheritDoc} */ + public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, + float x, float y, float width, float height) { + log.debug("NYI: addNativeImage() "+ "image=" + image + + ",x=" + x + ",y=" + y + ",width=" + width + ",height=" + height); + } + + /** {@inheritDoc} */ + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + log.debug("copyArea() NYI: "); + } +} diff --git a/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java b/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java new file mode 100644 index 000000000..cd8c7c303 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java @@ -0,0 +1,109 @@ +/* + * 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.afp; + +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; + +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * A graphics object info which contains necessary painting objects + */ +public class AFPGraphicsObjectInfo extends AFPDataObjectInfo { + + /** the graphics object painter implementation */ + private Graphics2DImagePainter painter; + + /** the graphics object area */ + private Rectangle2D area; + + /** the AFP graphics 2d implementation */ + private AFPGraphics2D g2d; + + /** + * Returns the graphics painter + * + * @return the graphics painter + */ + public Graphics2DImagePainter getPainter() { + return this.painter; + } + + /** + * Sets the graphics painter + * + * @param graphicsPainter the graphics painter + */ + public void setPainter(Graphics2DImagePainter graphicsPainter) { + this.painter = graphicsPainter; + } + + /** + * Returns the graphics area + * + * @return the graphics area + */ + public Rectangle2D getArea() { + AFPObjectAreaInfo objectAreaInfo = getObjectAreaInfo(); + int width = objectAreaInfo.getWidth(); + int height = objectAreaInfo.getHeight(); + return new Rectangle(width, height); + } + + /** + * Sets the graphics area area + * + * @param area the graphics object area + */ + public void setArea(Rectangle2D area) { + this.area = area; + } + + /** + * Sets the AFP graphics 2D implementation + * + * @param g2d the AFP graphics 2D implementation + */ + public void setGraphics2D(AFPGraphics2D g2d) { + this.g2d = g2d; + } + + /** + * Returns the AFP graphics 2D implementation + * + * @return the AFP graphics 2D implementation + */ + public AFPGraphics2D getGraphics2D() { + return this.g2d; + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsObjectInfo{" + super.toString() + "}"; + } + + /** {@inheritDoc} */ + public String getMimeType() { + return MimeConstants.MIME_SVG; + } + +} diff --git a/src/java/org/apache/fop/afp/AFPImageObjectInfo.java b/src/java/org/apache/fop/afp/AFPImageObjectInfo.java new file mode 100644 index 000000000..f3677534f --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPImageObjectInfo.java @@ -0,0 +1,115 @@ +/* + * 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.afp; + + +/** + * A list of parameters associated with an image + */ +public class AFPImageObjectInfo extends AFPDataObjectInfo { + + /** number of bits per pixel used */ + private int bitsPerPixel; + + /** is this a color image? */ + private boolean color; + + /** compression type if any */ + private int compression = -1; + + /** + * Default constructor + */ + public AFPImageObjectInfo() { + super(); + } + + /** + * Sets the number of bits per pixel + * + * @param bitsPerPixel the number of bits per pixel + */ + public void setBitsPerPixel(int bitsPerPixel) { + this.bitsPerPixel = bitsPerPixel; + } + + /** + * Sets if this image is color + * + * @param color true if this is a color image + */ + public void setColor(boolean color) { + this.color = color; + } + + /** + * Returns the number of bits used per pixel + * + * @return the number of bits used per pixel + */ + public int getBitsPerPixel() { + return bitsPerPixel; + } + + /** + * Returns true if this is a color image + * + * @return true if this is a color image + */ + public boolean isColor() { + return color; + } + + /** + * Returns true if this image uses compression + * + * @return true if this image uses compression + */ + public boolean hasCompression() { + return compression > -1; + } + + /** + * Returns the compression type + * + * @return the compression type + */ + public int getCompression() { + return compression; + } + + /** + * Sets the compression used with this image + * + * @param compression the type of compression used with this image + */ + public void setCompression(int compression) { + this.compression = compression; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPImageObjectInfo{" + super.toString() + + ", compression=" + compression + + ", color=" + color + + ", bitsPerPixel=" + bitsPerPixel + + "}"; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPLineDataInfo.java b/src/java/org/apache/fop/afp/AFPLineDataInfo.java new file mode 100644 index 000000000..f3acf4f71 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPLineDataInfo.java @@ -0,0 +1,192 @@ +/* + * 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.afp; + +import java.awt.Color; + +/** Line data information */ +public class AFPLineDataInfo { + + /** the x1 coordinate */ + int x1; + + /** the y1 coordinate */ + int y1; + + /** the x2 coordinate */ + int x2; + + /** the y2 coordinate */ + int y2; + + /** the thickness */ + int thickness; + + /** the painting color */ + Color color; + + /** the rotation */ + int rotation = 0; + + /** + * Default constructor + */ + public AFPLineDataInfo() { + } + + /** + * Returns the X1 coordinate + * + * @return the X1 coordinate + */ + public int getX1() { + return x1; + } + + /** + * Sets the X1 coordinate + * + * @param x1 the X1 coordinate + */ + public void setX1(int x1) { + this.x1 = x1; + } + + /** + * Returns the Y1 coordinate + * + * @return the Y1 coordinate + */ + public int getY1() { + return y1; + } + + /** + * Sets the Y1 coordinate + * + * @param y1 the Y1 coordinate + */ + public void setY1(int y1) { + this.y1 = y1; + } + + /** + * Returns the X2 coordinate + * + * @return the X2 coordinate + */ + public int getX2() { + return x2; + } + + /** + * Sets the X2 coordinate + * + * @param x2 the X2 coordinate + */ + public void setX2(int x2) { + this.x2 = x2; + } + + /** + * Returns the Y2 coordinate + * + * @return the Y2 coordinate + */ + public int getY2() { + return y2; + } + + /** + * Sets the Y2 coordinate + * + * @param y2 the Y2 coordinate + */ + public void setY2(int y2) { + this.y2 = y2; + } + + /** + * Returns the line thickness + * + * @return the line thickness + */ + public int getThickness() { + return thickness; + } + + /** + * Sets the line thickness + * + * @param thickness the line thickness + */ + public void setThickness(int thickness) { + this.thickness = thickness; + } + + /** + * Returns line color + * + * @return the line color + */ + public Color getColor() { + return color; + } + + /** + * Sets the line color + * + * @param color the line color + */ + public void setColor(Color color) { + this.color = color; + } + + /** + * Returns line rotation + * + * @return the line rotation + */ + public int getRotation() { + return rotation; + } + + /** + * Sets the line rotation + * + * @param rotation the line rotation + */ + public void setRotation(int rotation) { + this.rotation = rotation; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPLineDataInfo{x1=" + x1 + + ", y1=" + y1 + + ", x2=" + x2 + + ", y2=" + y2 + + ", thickness=" + thickness + + ", color=" + color + + ", rotation=" + rotation + + "}"; + } + +} diff --git a/src/java/org/apache/fop/afp/AFPObjectAreaInfo.java b/src/java/org/apache/fop/afp/AFPObjectAreaInfo.java new file mode 100644 index 000000000..963424470 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPObjectAreaInfo.java @@ -0,0 +1,172 @@ +/* + * 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.afp; + +/** + * A common class used to convey locations, + * dimensions and resolutions of data objects. + */ +public class AFPObjectAreaInfo { + private int x; + private int y; + private int width; + private int height; + private int widthRes; + private int heightRes; + private int rotation = 0; + + /** + * Sets the x position of the data object + * + * @param x the x position of the data object + */ + public void setX(int x) { + this.x = x; + } + + /** + * Sets the y position of the data object + * + * @param y the y position of the data object + */ + public void setY(int y) { + this.y = y; + } + + /** + * Sets the data object width + * + * @param width the width of the data object + */ + public void setWidth(int width) { + this.width = width; + } + + /** + * Sets the data object height + * + * @param height the height of the data object + */ + public void setHeight(int height) { + this.height = height; + } + + /** + * Sets the width resolution + * + * @param widthRes the width resolution + */ + public void setWidthRes(int widthRes) { + this.widthRes = widthRes; + } + + /** + * Sets the height resolution + * + * @param heightRes the height resolution + */ + public void setHeightRes(int heightRes) { + this.heightRes = heightRes; + } + + /** + * Returns the x coordinate of this data object + * + * @return the x coordinate of this data object + */ + public int getX() { + return x; + } + + /** + * Returns the y coordinate of this data object + * + * @return the y coordinate of this data object + */ + public int getY() { + return y; + } + + /** + * Returns the width of this data object + * + * @return the width of this data object + */ + public int getWidth() { + return width; + } + + /** + * Returns the height of this data object + * + * @return the height of this data object + */ + public int getHeight() { + return height; + } + + /** + * Returns the width resolution of this data object + * + * @return the width resolution of this data object + */ + public int getWidthRes() { + return widthRes; + } + + /** + * Returns the height resolution of this data object + * + * @return the height resolution of this data object + */ + public int getHeightRes() { + return heightRes; + } + + /** + * Returns the rotation of this data object + * + * @return the rotation of this data object + */ + public int getRotation() { + return rotation; + } + + /** + * Sets the data object rotation + * + * @param rotation the data object rotation + */ + public void setRotation(int rotation) { + this.rotation = rotation; + } + + /** {@inheritDoc} */ + public String toString() { + return "x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + ", widthRes=" + widthRes + + ", heightRes=" + heightRes + + ", rotation=" + rotation; + } + +} diff --git a/src/java/org/apache/fop/afp/AFPPaintingState.java b/src/java/org/apache/fop/afp/AFPPaintingState.java new file mode 100644 index 000000000..95a310bcb --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPPaintingState.java @@ -0,0 +1,495 @@ +/* + * 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.afp; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.fonts.AFPPageFonts; +import org.apache.fop.util.AbstractPaintingState; + +/** + * This keeps information about the current painting state when writing to an AFP datastream. + */ +public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState +implements Cloneable { + + private static final long serialVersionUID = 8206711712452344473L; + + private static Log log = LogFactory.getLog("org.apache.xmlgraphics.afp"); + + /** the portrait rotation */ + private int portraitRotation = 0; + + /** the landscape rotation */ + private int landscapeRotation = 270; + + /** color image support */ + private boolean colorImages = false; + + /** images are supported in this AFP environment */ + private boolean nativeImagesSupported = false; + + /** default value for image depth */ + private int bitsPerPixel = 8; + + /** the output resolution */ + private int resolution = 240; // 240 dpi + + /** the current page */ + private AFPPagePaintingState pagePaintingState = new AFPPagePaintingState(); + +// /** reference orientation */ +// private int orientation = 0; + + /** a unit converter */ + private final transient AFPUnitConverter unitConv = new AFPUnitConverter(this); + + /** + * Sets the rotation to be used for portrait pages, valid values are 0 + * (default), 90, 180, 270. + * + * @param rotation + * The rotation in degrees. + */ + public void setPortraitRotation(int rotation) { + if (rotation == 0 || rotation == 90 || rotation == 180 + || rotation == 270) { + portraitRotation = rotation; + } else { + throw new IllegalArgumentException( + "The portrait rotation must be one" + + " of the values 0, 90, 180, 270"); + + } + } + + /** + * Returns the rotation to be used for portrait pages + * + * @return the rotation to be used for portrait pages + */ + protected int getPortraitRotation() { + return this.portraitRotation; + } + + /** + * Sets the rotation to be used for landscape pages, valid values are 0, 90, + * 180, 270 (default). + * + * @param rotation + * The rotation in degrees. + */ + public void setLandscapeRotation(int rotation) { + if (rotation == 0 || rotation == 90 || rotation == 180 + || rotation == 270) { + landscapeRotation = rotation; + } else { + throw new IllegalArgumentException( + "The landscape rotation must be one" + + " of the values 0, 90, 180, 270"); + } + } + + /** + * Returns the landscape rotation + * + * @return the landscape rotation + */ + protected int getLandscapeRotation() { + return this.landscapeRotation; + } + + /** + * Sets the number of bits used per pixel + * + * @param bitsPerPixel + * number of bits per pixel + */ + public void setBitsPerPixel(int bitsPerPixel) { + switch (bitsPerPixel) { + case 1: + case 4: + case 8: + this.bitsPerPixel = bitsPerPixel; + break; + default: + log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8."); + this.bitsPerPixel = 8; + break; + } + } + + /** + * Returns the number of bits per pixel + * + * @return the number of bits per pixel + */ + public int getBitsPerPixel() { + return this.bitsPerPixel; + } + + /** + * Sets whether images are color or not + * + * @param colorImages + * color image output + */ + public void setColorImages(boolean colorImages) { + this.colorImages = colorImages; + } + + /** + * Returns true if color images are to be used + * + * @return true if color images are to be used + */ + public boolean isColorImages() { + return this.colorImages; + } + + /** + * Sets whether images are natively supported or not in the AFP environment + * + * @param nativeImagesSupported true if images are natively supported in this AFP environment + */ + public void setNativeImagesSupported(boolean nativeImagesSupported) { + this.nativeImagesSupported = nativeImagesSupported; + } + + /** + * Returns true if images are supported natively in this AFP environment + * + * @return true if images are supported natively in this AFP environment + */ + public boolean isNativeImagesSupported() { + return this.nativeImagesSupported; + } + + /** + * Sets the output/device resolution + * + * @param resolution + * the output resolution (dpi) + */ + public void setResolution(int resolution) { + if (log.isDebugEnabled()) { + log.debug("renderer-resolution set to: " + resolution + "dpi"); + } + this.resolution = resolution; + } + + /** + * Returns the output/device resolution. + * + * @return the resolution in dpi + */ + public int getResolution() { + return this.resolution; + } + + /** {@inheritDoc} */ + protected AbstractData instantiateData() { + return new AFPData(); + } + + /** {@inheritDoc} */ + protected AbstractPaintingState instantiate() { + return new AFPPaintingState(); + } + + /** + * Returns the painting state of the current page + * + * @return the painting state of the current page + */ + protected AFPPagePaintingState getPagePaintingState() { + return this.pagePaintingState; + } + + /** + * Gets the current page fonts + * + * @return the current page fonts + */ + public AFPPageFonts getPageFonts() { + return pagePaintingState.getFonts(); + } + + /** + * Sets the page width + * + * @param pageWidth the page width + */ + public void setPageWidth(int pageWidth) { + pagePaintingState.setWidth(pageWidth); + } + + /** + * Returns the page width + * + * @return the page width + */ + public int getPageWidth() { + return pagePaintingState.getWidth(); + } + + /** + * Sets the page height + * + * @param pageHeight the page height + */ + public void setPageHeight(int pageHeight) { + pagePaintingState.setHeight(pageHeight); + } + + /** + * Returns the page height + * + * @return the page height + */ + public int getPageHeight() { + return pagePaintingState.getHeight(); + } + + /** + * Returns the page rotation + * + * @return the page rotation + */ + public int getPageRotation() { + return pagePaintingState.getOrientation(); + } + + /** + * Sets the uri of the current image + * + * @param uri the uri of the current image + */ + public void setImageUri(String uri) { + ((AFPData)getData()).imageUri = uri; + } + + /** + * Gets the uri of the current image + * + * @return the uri of the current image + */ + public String getImageUri() { + return ((AFPData)getData()).imageUri; + } + + /** + * Returns the currently derived rotation + * + * @return the currently derived rotation + */ + public int getRotation() { + return getData().getDerivedRotation(); + } + + /** + * Returns the unit converter + * + * @return the unit converter + */ + public AFPUnitConverter getUnitConverter() { + return this.unitConv; + } + + /** {@inheritDoc} */ + public Object clone() { + AFPPaintingState paintingState = (AFPPaintingState)super.clone(); + paintingState.pagePaintingState = (AFPPagePaintingState)this.pagePaintingState.clone(); + paintingState.portraitRotation = this.portraitRotation; + paintingState.landscapeRotation = this.landscapeRotation; + paintingState.bitsPerPixel = this.bitsPerPixel; + paintingState.colorImages = this.colorImages; + paintingState.resolution = this.resolution; + return paintingState; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPPaintingState{" + "portraitRotation=" + portraitRotation + + ", landscapeRotation=" + landscapeRotation + + ", colorImages=" + colorImages + + ", bitsPerPixel=" + bitsPerPixel + + ", resolution=" + resolution + + ", pageState=" + pagePaintingState + + super.toString() + + "}"; + } + + /** + * Page level state data + */ + private class AFPPagePaintingState implements Cloneable { + /** page width */ + private int width = 0; + + /** page height */ + private int height = 0; + + /** page fonts */ + private AFPPageFonts fonts = new AFPPageFonts(); + + /** page font count */ + private int fontCount = 0; + + /** page orientation */ + private int orientation = 0; + + /** + * Returns the page width + * + * @return the page width + */ + protected int getWidth() { + return width; + } + + /** + * Sets the page width + * + * @param width the page width + */ + protected void setWidth(int width) { + this.width = width; + } + + /** + * Returns the page height + * + * @return the page height + */ + protected int getHeight() { + return height; + } + + /** + * Sets the page height + * + * @param height the page height + */ + protected void setHeight(int height) { + this.height = height; + } + + /** + * Returns the page fonts + * + * @return the page fonts + */ + protected AFPPageFonts getFonts() { + return fonts; + } + + /** + * Sets the current page fonts + * + * @param fonts the current page fonts + */ + protected void setFonts(AFPPageFonts fonts) { + this.fonts = fonts; + } + + /** + * Increments and returns the current page font count + * + * @return increment and return the current page font count + */ + protected int incrementFontCount() { + return ++fontCount; + } + + /** + * Returns the current page orientation + * + * @return the current page orientation + */ + protected int getOrientation() { + return orientation; + } + + /** + * Sets the current page orientation + * + * @param orientation the current page orientation + */ + protected void setOrientation(int orientation) { + this.orientation = orientation; + } + + /** {@inheritDoc} */ + public Object clone() { + AFPPagePaintingState state = new AFPPagePaintingState(); + state.width = this.width; + state.height = this.height; + state.orientation = this.orientation; + state.fonts = new AFPPageFonts(this.fonts); + state.fontCount = this.fontCount; + return state; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPPagePaintingState{width=" + width + + ", height=" + height + + ", orientation=" + orientation + + ", fonts=" + fonts + + ", fontCount=" + fontCount + + "}"; + } + } + + /** + * Block level state data + */ + private class AFPData extends org.apache.fop.util.AbstractPaintingState.AbstractData { + private static final long serialVersionUID = -1789481244175275686L; + + /** The current fill status */ + private boolean filled = false; + + private String imageUri = null; + + /** {@inheritDoc} */ + public Object clone() { + AFPData obj = (AFPData)super.clone(); + obj.filled = this.filled; + obj.imageUri = this.imageUri; + return obj; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPData{" + super.toString() + + ", filled=" + filled + + ", imageUri=" + imageUri + + "}"; + } + + /** {@inheritDoc} */ + protected AbstractData instantiate() { + return new AFPData(); + } + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPRectanglePainter.java b/src/java/org/apache/fop/afp/AFPRectanglePainter.java new file mode 100644 index 000000000..e2bad6159 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPRectanglePainter.java @@ -0,0 +1,84 @@ +/* + * 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.afp; + +import java.awt.geom.AffineTransform; + + +/** + * A painter of rectangles in AFP + */ +public class AFPRectanglePainter extends AbstractAFPPainter { + + /** + * Main constructor + * + * @param paintingState the AFP painting state + * @param dataStream the AFP datastream + */ + public AFPRectanglePainter(AFPPaintingState paintingState, DataStream dataStream) { + super(paintingState, dataStream); + } + + /** {@inheritDoc} */ + public void paint(PaintingInfo paintInfo) { + RectanglePaintingInfo rectanglePaintInfo = (RectanglePaintingInfo)paintInfo; + int pageWidth = dataStream.getCurrentPage().getWidth(); + int pageHeight = dataStream.getCurrentPage().getHeight(); + + AFPUnitConverter unitConv = paintingState.getUnitConverter(); + float width = unitConv.pt2units(rectanglePaintInfo.getWidth()); + float height = unitConv.pt2units(rectanglePaintInfo.getHeight()); + float x = unitConv.pt2units(rectanglePaintInfo.getX()); + float y = unitConv.pt2units(rectanglePaintInfo.getY()); + + AffineTransform at = paintingState.getData().getTransform(); + + AFPLineDataInfo lineDataInfo = new AFPLineDataInfo(); + lineDataInfo.color = paintingState.getColor(); + lineDataInfo.rotation = paintingState.getRotation(); + lineDataInfo.thickness = Math.round(height); + + switch (lineDataInfo.rotation) { + case 0: + lineDataInfo.x1 = Math.round((float)at.getTranslateX() + x); + lineDataInfo.y1 = lineDataInfo.y2 = Math.round((float)at.getTranslateY() + y); + lineDataInfo.x2 = Math.round((float)at.getTranslateX() + x + width); + break; + case 90: + lineDataInfo.x1 = Math.round((float)at.getTranslateY() + x); + lineDataInfo.y1 = lineDataInfo.y2 + = pageWidth - Math.round((float)at.getTranslateX()) + Math.round(y); + lineDataInfo.x2 = Math.round(width + (float)at.getTranslateY() + x); + break; + case 180: + lineDataInfo.x1 = pageWidth - Math.round((float)at.getTranslateX() - x); + lineDataInfo.y1 = lineDataInfo.y2 = pageHeight - Math.round((float)at.getTranslateY() - y); + lineDataInfo.x2 = pageWidth - Math.round((float)at.getTranslateX() - x - width); + break; + case 270: + lineDataInfo.x1 = pageHeight - Math.round((float)at.getTranslateY() - x); + lineDataInfo.y1 = lineDataInfo.y2 = Math.round((float)at.getTranslateX() + y); + lineDataInfo.x2 = lineDataInfo.x1 + Math.round(width - x); + break; + } + dataStream.createLine(lineDataInfo); + } +} diff --git a/src/java/org/apache/fop/afp/AFPResourceInfo.java b/src/java/org/apache/fop/afp/AFPResourceInfo.java new file mode 100644 index 000000000..729339fa4 --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPResourceInfo.java @@ -0,0 +1,141 @@ +/* + * 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.afp; + + +/** + * The level at which a resource is to reside in the AFP output + */ +public class AFPResourceInfo { + private static final AFPResourceLevel DEFAULT_LEVEL + = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE); + + /** the uri of this resource */ + private String uri = null; + + /** the reference name of this resource */ + private String name = null; + + /** the resource level of this resource */ + private AFPResourceLevel level = DEFAULT_LEVEL; + + /** true when the resource level was changed */ + private boolean levelChanged = false; + + /** + * Sets the data object uri + * + * @param uri the data object uri + */ + public void setUri(String uri) { + this.uri = uri; + } + + /** + * Returns the uri of this data object + * + * @return the uri of this data object + */ + public String getUri() { + return uri; + } + + /** + * Sets the resource reference name + * + * @param resourceName the resource reference name + */ + public void setName(String resourceName) { + this.name = resourceName; + } + + /** + * Returns the resource reference name + * + * @return the resource reference name + */ + public String getName() { + return this.name; + } + + /** + * Returns the resource level + * + * @return the resource level + */ + public AFPResourceLevel getLevel() { + if (level == null) { + return DEFAULT_LEVEL; + } + return this.level; + } + + /** + * Sets the resource level + * + * @param resourceLevel the resource level + */ + public void setLevel(AFPResourceLevel resourceLevel) { + this.level = resourceLevel; + levelChanged = true; + } + + /** + * Returns true when the resource level was set + * + * @return true when the resource level was set + */ + public boolean levelChanged() { + return levelChanged; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPResourceInfo{uri=" + uri + + (name != null ? ", name=" + name : "") + + (level != null ? ", level=" + level : "") + + "}"; + + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if ((obj == null) || !(obj instanceof AFPResourceInfo)) { + return false; + } + + AFPResourceInfo ri = (AFPResourceInfo)obj; + return (uri == ri.uri || uri != null && uri.equals(ri.uri)) + && (name == ri.name || name != null && name.equals(ri.name)) + && (level == ri.level || level != null && level.equals(ri.level)); + } + + /** {@inheritDoc} */ + public int hashCode() { + int hash = 7; + hash = 31 * hash + (null == uri ? 0 : uri.hashCode()); + hash = 31 * hash + (null == name ? 0 : name.hashCode()); + hash = 31 * hash + (null == level ? 0 : level.hashCode()); + return hash; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPResourceLevel.java b/src/java/org/apache/fop/afp/AFPResourceLevel.java new file mode 100644 index 000000000..5e8d54aae --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPResourceLevel.java @@ -0,0 +1,201 @@ +/* + * 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.afp; + +/** + * A resource level + */ +public class AFPResourceLevel { + + /** directly in page **/ + public static final int INLINE = 0; + + /** page level **/ + public static final int PAGE = 1; + + /** page group level **/ + public static final int PAGE_GROUP = 2; + + /** document level **/ + public static final int DOCUMENT = 3; + + /** print file level **/ + public static final int PRINT_FILE = 4; + + /** external level **/ + public static final int EXTERNAL = 5; + + private static final String NAME_INLINE = "inline"; + private static final String NAME_PAGE = "page"; + private static final String NAME_PAGE_GROUP = "page-group"; + private static final String NAME_DOCUMENT = "document"; + private static final String NAME_PRINT_FILE = "print-file"; + private static final String NAME_EXTERNAL = "external"; + + private static final String[] NAMES = new String[] { + NAME_INLINE, NAME_PAGE, NAME_PAGE_GROUP, NAME_DOCUMENT, NAME_PRINT_FILE, NAME_EXTERNAL + }; + + + /** where the resource will reside in the AFP output */ + private int level = PRINT_FILE; // default is print-file level (images) + + /** the external resource group file path */ + private String extFilePath = null; + + /** + * Sets the resource placement level within the AFP output + * + * @param levelString the resource level (page, page-group, document, print-file or external) + * @return true if the resource level was successfully set + */ + public static AFPResourceLevel valueOf(String levelString) { + if (levelString != null) { + levelString = levelString.toLowerCase(); + AFPResourceLevel resourceLevel = null; + for (int i = 0; i < NAMES.length; i++) { + if (NAMES[i].equals(levelString)) { + resourceLevel = new AFPResourceLevel(i); + break; + } + } + return resourceLevel; + } + return null; + } + + /** + * Main constructor + * + * @param level the resource level + */ + public AFPResourceLevel(int level) { + setLevel(level); + } + + /** + * Sets the resource level + * + * @param level the resource level + */ + public void setLevel(int level) { + this.level = level; + } + + /** + * Returns true if this is at page level + * + * @return true if this is at page level + */ + public boolean isPage() { + return level == PAGE; + } + + /** + * Returns true if this is at page group level + * + * @return true if this is at page group level + */ + public boolean isPageGroup() { + return level == PAGE_GROUP; + } + + /** + * Returns true if this is at document level + * + * @return true if this is at document level + */ + public boolean isDocument() { + return level == DOCUMENT; + } + + /** + * Returns true if this is at external level + * + * @return true if this is at external level + */ + public boolean isExternal() { + return level == EXTERNAL; + } + + /** + * Returns true if this is at print-file level + * + * @return true if this is at print-file level + */ + public boolean isPrintFile() { + return level == PRINT_FILE; + } + + /** + * Returns true if this resource level is inline + * + * @return true if this resource level is inline + */ + public boolean isInline() { + return level == INLINE; + } + + /** + * Returns the destination file path of the external resource group file + * + * @return the destination file path of the external resource group file + */ + public String getExternalFilePath() { + return this.extFilePath; + } + + /** + * Sets the external destination of the resource + * + * @param filePath the external resource group file + */ + public void setExternalFilePath(String filePath) { + this.extFilePath = filePath; + } + + /** {@inheritDoc} */ + public String toString() { + return NAMES[level] + (isExternal() ? ", file=" + extFilePath : ""); + } + + /** {@inheritDoc} */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if ((obj == null) || !(obj instanceof AFPResourceLevel)) { + return false; + } + + AFPResourceLevel rl = (AFPResourceLevel)obj; + return (level == level) + && (extFilePath == rl.extFilePath + || extFilePath != null && extFilePath.equals(rl.extFilePath)); + } + + /** {@inheritDoc} */ + public int hashCode() { + int hash = 7; + hash = 31 * hash + level; + hash = 31 * hash + (null == extFilePath ? 0 : extFilePath.hashCode()); + return hash; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java new file mode 100644 index 000000000..164ebfd2d --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPResourceManager.java @@ -0,0 +1,179 @@ +/* + * 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.afp; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +import org.apache.fop.afp.modca.AbstractNamedAFPObject; +import org.apache.fop.afp.modca.IncludeObject; +import org.apache.fop.afp.modca.Registry; +import org.apache.fop.afp.modca.ResourceGroup; + +/** + * Manages the creation and storage of document resources + */ +public class AFPResourceManager { + /** The AFP datastream (document tree) */ + private DataStream dataStream; + + /** Resource creation factory */ + private final Factory factory; + + private final AFPStreamer streamer; + + private final AFPDataObjectFactory dataObjectFactory; + + /** Maintain a reference count of instream objects for referencing purposes */ + private int instreamObjectCount = 0; + + /** a mapping of resourceInfo --> include name */ + private final Map/*<AFPResourceInfo,String>*/ includeNameMap + = new java.util.HashMap()/*<AFPResourceInfo,String>*/; + + /** + * Main constructor + */ + public AFPResourceManager() { + this.factory = new Factory(); + this.streamer = new AFPStreamer(factory); + this.dataObjectFactory = new AFPDataObjectFactory(factory); + } + + /** + * Sets the outputstream + * + * @param paintingState the AFP painting state + * @param outputStream the outputstream + * @return a new AFP DataStream + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public DataStream createDataStream(AFPPaintingState paintingState, OutputStream outputStream) + throws IOException { + this.dataStream = streamer.createDataStream(paintingState); + streamer.setOutputStream(outputStream); + return this.dataStream; + } + + /** + * Returns the AFP DataStream + * + * @return the AFP DataStream + */ + public DataStream getDataStream() { + return this.dataStream; + } + + /** + * Tells the streamer to write + * + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + public void writeToStream() throws IOException { + streamer.close(); + } + + /** + * Sets the default resource group file path + * + * @param filePath the default resource group file path + */ + + public void setDefaultResourceGroupFilePath(String filePath) { + streamer.setDefaultResourceGroupFilePath(filePath); + } + + /** + * Creates a new data object in the AFP datastream + * + * @param dataObjectInfo the data object info + * + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + public void createObject(AFPDataObjectInfo dataObjectInfo) throws IOException { + AbstractNamedAFPObject namedObj = null; + + AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + String uri = resourceInfo.getUri(); + if (uri == null) { + uri = "/"; + } + // if this is an instream data object adjust the uri to ensure that its unique + if (uri.endsWith("/")) { + uri += "#" + (++instreamObjectCount); + resourceInfo.setUri(uri); + } + + String objectName = (String)includeNameMap.get(resourceInfo); + if (objectName == null) { + boolean useInclude = true; + Registry.ObjectType objectType = null; + + // new resource so create + if (dataObjectInfo instanceof AFPImageObjectInfo) { + AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo; + namedObj = dataObjectFactory.createImage(imageObjectInfo); + } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) { + AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo)dataObjectInfo; + namedObj = dataObjectFactory.createGraphic(graphicsObjectInfo); + } else { + // natively embedded data object + namedObj = dataObjectFactory.createObjectContainer(dataObjectInfo); + objectType = dataObjectInfo.getObjectType(); + useInclude = objectType != null && objectType.isIncludable(); + } + + AFPResourceLevel resourceLevel = resourceInfo.getLevel(); + ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel); + useInclude &= resourceGroup != null; + if (useInclude) { + // if it is to reside within a resource group at print-file or external level + if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) { + // wrap newly created data object in a resource object + namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType); + } + + // add data object into its resource group destination + resourceGroup.addObject(namedObj); + + // create the include object + objectName = namedObj.getName(); + IncludeObject includeObject + = dataObjectFactory.createInclude(objectName, dataObjectInfo); + + // add an include to the current page + dataStream.getCurrentPage().addObject(includeObject); + + // record mapping of resource info to data object resource name + includeNameMap.put(resourceInfo, objectName); + } else { + // not to be included so inline data object directly into the current page + dataStream.getCurrentPage().addObject(namedObj); + } + } else { + // an existing data resource so reference it by adding an include to the current page + IncludeObject includeObject + = dataObjectFactory.createInclude(objectName, dataObjectInfo); + dataStream.getCurrentPage().addObject(includeObject); + } + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPStreamer.java b/src/java/org/apache/fop/afp/AFPStreamer.java new file mode 100644 index 000000000..7e208bb6e --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPStreamer.java @@ -0,0 +1,215 @@ +/* + * 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.afp; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.modca.ResourceGroup; +import org.apache.fop.afp.modca.StreamedResourceGroup; + +/** + * Manages the streaming of the AFP output + */ +public class AFPStreamer implements Streamable { + /** Static logging instance */ + private static final Log log = LogFactory.getLog(AFPStreamer.class); + + private static final String AFPDATASTREAM_TEMP_FILE_PREFIX = "AFPDataStream_"; + + private static final int BUFFER_SIZE = 4096; // 4k writing buffer + + private static final String DEFAULT_EXTERNAL_RESOURCE_FILENAME = "resources.afp"; + + + private final Factory factory; + + /** A mapping of external resource destinations to resource groups */ + private final Map/*<String,AFPExternalResourceGroup>*/pathResourceGroupMap + = new java.util.HashMap/*<String,AFPExternalResourceGroup>*/(); + + private StreamedResourceGroup printFileResourceGroup; + + /** Sets the default resource group file path */ + private String defaultResourceGroupFilePath = DEFAULT_EXTERNAL_RESOURCE_FILENAME; + + private File tempFile; + + /** temporary document outputstream */ + private OutputStream documentOutputStream; + + /** the final outputstream */ + private OutputStream outputStream; + + private RandomAccessFile documentFile; + + private DataStream dataStream; + + /** + * Main constructor + * + * @param factory a factory + */ + public AFPStreamer(Factory factory) { + this.factory = factory; + } + + /** + * Creates a new DataStream + * + * @param paintingState the AFP painting state + * @return a new {@link DataStream} + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public DataStream createDataStream(AFPPaintingState paintingState) throws IOException { + this.tempFile = File.createTempFile(AFPDATASTREAM_TEMP_FILE_PREFIX, null); + this.documentFile = new RandomAccessFile(tempFile, "rw"); + this.documentOutputStream = new BufferedOutputStream( + new FileOutputStream(documentFile.getFD())); + this.dataStream = factory.createDataStream(paintingState, documentOutputStream); + return dataStream; + } + + /** + * Sets the default resource group file path + * + * @param filePath the default resource group file path + */ + public void setDefaultResourceGroupFilePath(String filePath) { + this.defaultResourceGroupFilePath = filePath; + } + + /** + * Returns the resource group for a given resource info + * + * @param level a resource level + * @return a resource group for the given resource info + */ + public ResourceGroup getResourceGroup(AFPResourceLevel level) { + ResourceGroup resourceGroup = null; + if (level.isInline()) { // no resource group for inline level + return null; + } + if (level.isExternal()) { + String filePath = level.getExternalFilePath(); + if (filePath == null) { + log.warn("No file path provided for external resource, using default."); + filePath = defaultResourceGroupFilePath; + } + resourceGroup = (ResourceGroup)pathResourceGroupMap.get(filePath); + if (resourceGroup == null) { + OutputStream os = null; + try { + os = new BufferedOutputStream(new FileOutputStream(filePath)); + } catch (FileNotFoundException fnfe) { + log.error("Failed to create/open external resource group file '" + + filePath + "'"); + } finally { + if (os != null) { + resourceGroup = factory.createStreamedResourceGroup(os); + pathResourceGroupMap.put(filePath, resourceGroup); + } + } + } + } else if (level.isPrintFile()) { + if (printFileResourceGroup == null) { + // use final outputstream for print-file resource group + printFileResourceGroup = factory.createStreamedResourceGroup(outputStream); + } + resourceGroup = printFileResourceGroup; + } else { + // resource group in afp document datastream + resourceGroup = dataStream.getResourceGroup(level); + } + return resourceGroup; + } + + /** + * Closes off the AFP stream writing the document stream + * + * @throws IOException if an an I/O exception of some sort has occurred + */ + // write out any external resource groups + public void close() throws IOException { + Iterator it = pathResourceGroupMap.entrySet().iterator(); + while (it.hasNext()) { + StreamedResourceGroup resourceGroup = (StreamedResourceGroup)it.next(); + resourceGroup.close(); + } + + // close any open print-file resource group + if (printFileResourceGroup != null) { + printFileResourceGroup.close(); + } + + // write out document + writeToStream(outputStream); + + outputStream.close(); + + // delete temporary file + tempFile.delete(); + } + + /** + * Sets the final outputstream + * + * @param outputStream an outputstream + */ + public void setOutputStream(OutputStream outputStream) { + this.outputStream = outputStream; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { +// long start = System.currentTimeMillis(); + int len = (int)documentFile.length(); + int numChunks = len / BUFFER_SIZE; + int remainingChunkSize = len % BUFFER_SIZE; + byte[] buffer; + + documentFile.seek(0); + if (numChunks > 0) { + buffer = new byte[BUFFER_SIZE]; + for (int i = 0; i < numChunks; i++) { + documentFile.read(buffer, 0, BUFFER_SIZE); + os.write(buffer, 0, BUFFER_SIZE); + } + } else { + buffer = new byte[remainingChunkSize]; + } + if (remainingChunkSize > 0) { + documentFile.read(buffer, 0, remainingChunkSize); + os.write(buffer, 0, remainingChunkSize); + } + os.flush(); +// long end = System.currentTimeMillis(); +// log.debug("writing time " + (end - start) + "ms"); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPTextDataInfo.java b/src/java/org/apache/fop/afp/AFPTextDataInfo.java new file mode 100644 index 000000000..8047c927c --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPTextDataInfo.java @@ -0,0 +1,232 @@ +/* + * 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.afp; + +import java.awt.Color; + +/** + * Text data information + */ +public class AFPTextDataInfo { + + /** the text font reference */ + private int fontReference; + + /** the text x coordinate position */ + private int x; + + /** the text y coordinate position */ + private int y; + + /** the text color */ + private Color color; + + /** the text variable space adjustment */ + private int variableSpaceCharacterIncrement; + + /** the text inter character adjustment */ + private int interCharacterAdjustment; + + /** the text orientation */ + private int rotation; + + /** the text encoding */ + private String textEncoding; + + /** the text string */ + private String textString; + + /** + * Returns the font reference + * + * @return the font reference + */ + public int getFontReference() { + return fontReference; + } + + /** + * Sets the font reference + * + * @param fontReference the font reference + */ + public void setFontReference(int fontReference) { + this.fontReference = fontReference; + } + + /** + * Returns the x coordinate + * + * @return the x coordinate + */ + public int getX() { + return x; + } + + /** + * Sets the X coordinate + * + * @param x the X coordinate + */ + public void setX(int x) { + this.x = x; + } + + /** + * Returns the y coordinate + * + * @return the y coordinate + */ + public int getY() { + return y; + } + + /** + * Sets the Y coordinate + * + * @param y the Y coordinate + */ + public void setY(int y) { + this.y = y; + } + + /** + * Returns the color + * + * @return the color + */ + public Color getColor() { + return color; + } + + /** + * Sets the color + * + * @param color the color + */ + public void setColor(Color color) { + this.color = color; + } + + /** + * Return the variable space character increment + * + * @return the variable space character increment + */ + public int getVariableSpaceCharacterIncrement() { + return variableSpaceCharacterIncrement; + } + + /** + * Sets the variable space character increment + * + * @param variableSpaceCharacterIncrement the variable space character increment + */ + public void setVariableSpaceCharacterIncrement( + int variableSpaceCharacterIncrement) { + this.variableSpaceCharacterIncrement = variableSpaceCharacterIncrement; + } + + /** + * Return the inter character adjustment + * + * @return the inter character adjustment + */ + public int getInterCharacterAdjustment() { + return interCharacterAdjustment; + } + + /** + * Sets the inter character adjustment + * + * @param interCharacterAdjustment the inter character adjustment + */ + public void setInterCharacterAdjustment(int interCharacterAdjustment) { + this.interCharacterAdjustment = interCharacterAdjustment; + } + + /** + * Sets the text orientation + * + * @param rotation the text rotation + */ + public void setRotation(int rotation) { + this.rotation = rotation; + } + + /** + * Returns the text rotation + * + * @return the text rotation + */ + public int getRotation() { + return this.rotation; + } + + /** + * Sets the text encoding + * + * @param textEncoding the text encoding + */ + public void setEncoding(String textEncoding) { + this.textEncoding = textEncoding; + } + + /** + * Returns the text encoding + * + * @return the text encoding + */ + public String getEncoding() { + return this.textEncoding; + } + + /** + * Sets the text string + * + * @param textString the text string + */ + public void setString(String textString) { + this.textString = textString; + } + + /** + * Returns the text string + * + * @return the text string + */ + public String getString() { + return this.textString; + } + + /** {@inheritDoc} */ + public String toString() { + return "TextDataInfo{fontReference=" + fontReference + + ", x=" + x + + ", y=" + y + + ", color=" + color + + ", vsci=" + variableSpaceCharacterIncrement + + ", ica=" + interCharacterAdjustment + + ", orientation=" + rotation + + ", textString=" + textString + + ", textEncoding=" + textEncoding + + "}"; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/AFPUnitConverter.java b/src/java/org/apache/fop/afp/AFPUnitConverter.java new file mode 100644 index 000000000..3195ba70f --- /dev/null +++ b/src/java/org/apache/fop/afp/AFPUnitConverter.java @@ -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.afp; + +import java.awt.geom.AffineTransform; + + + +/** + * AFP Unit converter + */ +public class AFPUnitConverter { + + /** the AFP state */ + private final AFPPaintingState paintingState; + + /** + * Unit converter + * + * @param paintingState the AFP painting state + */ + public AFPUnitConverter(AFPPaintingState paintingState) { + this.paintingState = paintingState; + } + + /** + * Converts millipoints to units + * + * @param srcPts source points + * @param dstPts destination points + * @return transformed points + */ + public int[] mpts2units(float[] srcPts, float[] dstPts) { + return transformPoints(srcPts, dstPts, true); + } + + /** + * Converts points to units + * + * @param srcPts source points + * @param dstPts destination points + * @return transformed points + */ + public int[] pts2units(float[] srcPts, float[] dstPts) { + return transformPoints(srcPts, dstPts, false); + } + + /** + * Converts millipoints to units + * + * @param srcPts source points + * @return transformed points + */ + public int[] mpts2units(float[] srcPts) { + return transformPoints(srcPts, null, true); + } + + /** + * Converts points to units + * + * @param srcPts source points + * @return transformed points + */ + public int[] pts2units(float[] srcPts) { + return transformPoints(srcPts, null, false); + } + + /** + * Converts point to unit + * + * @param pt point + * @return transformed point + */ + public float pt2units(float pt) { + return pt / ((float)AFPConstants.DPI_72 / paintingState.getResolution()); + } + + /** + * Converts millipoint to unit + * + * @param mpt millipoint + * @return transformed point + */ + public float mpt2units(float mpt) { + return mpt / ((float)AFPConstants.DPI_72_MPTS / paintingState.getResolution()); + } + + private int[] transformPoints(float[] srcPts, float[] dstPts, boolean milli) { + if (dstPts == null) { + dstPts = new float[srcPts.length]; + } + AffineTransform at = paintingState.getData().getTransform(); + at.transform(srcPts, 0, dstPts, 0, srcPts.length / 2); + int[] coords = new int[srcPts.length]; + for (int i = 0; i < srcPts.length; i++) { + if (!milli) { + dstPts[i] *= 1000; + } + coords[i] = Math.round(dstPts[i]); + } + return coords; + } + +} diff --git a/src/java/org/apache/fop/afp/AbstractAFPPainter.java b/src/java/org/apache/fop/afp/AbstractAFPPainter.java new file mode 100644 index 000000000..576b8bb11 --- /dev/null +++ b/src/java/org/apache/fop/afp/AbstractAFPPainter.java @@ -0,0 +1,53 @@ +/* + * 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.afp; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A base AFP painter + */ +public abstract class AbstractAFPPainter { + + /** Static logging instance */ + protected static Log log = LogFactory.getLog("org.apache.xmlgraphics.afp"); + + protected final DataStream dataStream; + protected final AFPPaintingState paintingState; + + /** + * Main constructor + * + * @param paintingState the AFP painting state + * @param dataStream the AFP Datastream + */ + public AbstractAFPPainter(AFPPaintingState paintingState, DataStream dataStream) { + this.paintingState = paintingState; + this.dataStream = dataStream; + } + + /** + * Paints the painting item + * + * @param paintInfo the painting information + */ + public abstract void paint(PaintingInfo paintInfo); +} diff --git a/src/java/org/apache/fop/afp/BorderPaintingInfo.java b/src/java/org/apache/fop/afp/BorderPaintingInfo.java new file mode 100644 index 000000000..4917c7bc0 --- /dev/null +++ b/src/java/org/apache/fop/afp/BorderPaintingInfo.java @@ -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.afp; + +import java.awt.Color; + +/** + * Border painting information + */ +public class BorderPaintingInfo implements PaintingInfo { + + private final float x1; + private final float y1; + private final float x2; + private final float y2; + private final boolean isHorizontal; + private final int style; + private final Color color; + + /** + * Main constructor + * + * @param x1 the x1 coordinate + * @param y1 the y1 coordinate + * @param x2 the x2 coordinate + * @param y2 the y2 coordinate + * @param isHorizontal true when the border line is horizontal + * @param style the border style + * @param color the border color + */ + public BorderPaintingInfo(float x1, float y1, float x2, float y2, + boolean isHorizontal, int style, Color color) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + this.isHorizontal = isHorizontal; + this.style = style; + this.color = color; + } + + /** + * Returns the x1 coordinate + * + * @return the x1 coordinate + */ + public float getX1() { + return x1; + } + + /** + * Returns the y1 coordinate + * + * @return the y1 coordinate + */ + public float getY1() { + return y1; + } + + /** + * Returns the x2 coordinate + * + * @return the x2 coordinate + */ + public float getX2() { + return x2; + } + + /** + * Returns the y2 coordinate + * + * @return the y2 coordinate + */ + public float getY2() { + return y2; + } + + /** + * Returns true when this is a horizontal line + * + * @return true when this is a horizontal line + */ + public boolean isHorizontal() { + return isHorizontal; + } + + /** + * Returns the style + * + * @return the style + */ + public int getStyle() { + return style; + } + + /** + * Returns the color + * + * @return the color + */ + public Color getColor() { + return color; + } +} diff --git a/src/java/org/apache/fop/afp/Completable.java b/src/java/org/apache/fop/afp/Completable.java new file mode 100644 index 000000000..e1fc764dd --- /dev/null +++ b/src/java/org/apache/fop/afp/Completable.java @@ -0,0 +1,40 @@ +/* + * 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.afp; + +/** + * Set and expose the internal completeness of an object. + */ +public interface Completable { + + /** + * Sets whether or not this object is complete or not + * + * @param complete true if this object is complete + */ + void setComplete(boolean complete); + + /** + * Returns true if this object is complete + * + * @return true if this object is complete + */ + boolean isComplete(); +} diff --git a/src/java/org/apache/fop/afp/DataStream.java b/src/java/org/apache/fop/afp/DataStream.java new file mode 100644 index 000000000..783c698ea --- /dev/null +++ b/src/java/org/apache/fop/afp/DataStream.java @@ -0,0 +1,602 @@ +/* + * 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.afp; + +import java.awt.Color; +import java.awt.Point; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.fonts.AFPFont; +import org.apache.fop.afp.fonts.AFPFontAttributes; +import org.apache.fop.afp.modca.AbstractPageObject; +import org.apache.fop.afp.modca.Document; +import org.apache.fop.afp.modca.InterchangeSet; +import org.apache.fop.afp.modca.Overlay; +import org.apache.fop.afp.modca.PageGroup; +import org.apache.fop.afp.modca.PageObject; +import org.apache.fop.afp.modca.ResourceGroup; +import org.apache.fop.afp.modca.TagLogicalElementBean; +import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; + +/** + * A data stream is a continuous ordered stream of data elements and objects + * conforming to a given format. Application programs can generate data streams + * destined for a presentation service, archive library, presentation device or + * another application program. The strategic presentation data stream + * architectures used is Mixed Object Document Content Architecture (MO:DCA). + * + * The MO:DCA architecture defines the data stream used by applications to + * describe documents and object envelopes for interchange with other + * applications and application services. Documents defined in the MO:DCA format + * may be archived in a database, then later retrieved, viewed, annotated and + * printed in local or distributed systems environments. Presentation fidelity + * is accommodated by including resource objects in the documents that reference + * them. + */ +public class DataStream { + + /** Static logging instance */ + protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp"); + + /** Boolean completion indicator */ + private boolean complete = false; + + /** The AFP document object */ + private Document document = null; + + /** The current page group object */ + private PageGroup currentPageGroup = null; + + /** The current page object */ + private PageObject currentPageObject = null; + + /** The current overlay object */ + private Overlay currentOverlay = null; + + /** The current page */ + private AbstractPageObject currentPage = null; + + /** The MO:DCA interchange set in use (default to MO:DCA-P IS/2 set) */ + private InterchangeSet interchangeSet + = InterchangeSet.valueOf(InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2); + + private final Factory factory; + + private OutputStream outputStream; + + /** the afp painting state */ + private final AFPPaintingState paintingState; + + /** + * Default constructor for the AFPDocumentStream. + * + * @param factory the resource factory + * @param paintingState the AFP painting state + * @param outputStream the outputstream to write to + */ + public DataStream(Factory factory, AFPPaintingState paintingState, OutputStream outputStream) { + this.paintingState = paintingState; + this.factory = factory; + this.outputStream = outputStream; + } + + /** + * Returns the outputstream + * + * @return the outputstream + */ + public OutputStream getOutputStream() { + return this.outputStream; + } + + /** + * Returns the document object + * + * @return the document object + */ + private Document getDocument() { + return this.document; + } + + /** + * Returns the current page + * + * @return the current page + */ + public AbstractPageObject getCurrentPage() { + return this.currentPage; + } + + /** + * The document is started by invoking this method which creates an instance + * of the AFP Document object. + * + * @param name + * the name of this document. + */ + public void setDocumentName(String name) { + if (name != null) { + getDocument().setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_DOCUMENT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, name); + } + } + + /** + * Helper method to mark the end of the current document. + * + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public void endDocument() throws IOException { + if (complete) { + String msg = "Invalid state - document already ended."; + log.warn("endDocument():: " + msg); + throw new IllegalStateException(msg); + } + + if (currentPageObject != null) { + // End the current page if necessary + endPage(); + } + + if (currentPageGroup != null) { + // End the current page group if necessary + endPageGroup(); + } + + // Write out document + if (document != null) { + document.endDocument(); + document.writeToStream(this.outputStream); + } + + this.outputStream.flush(); + + this.complete = true; + + this.document = null; + + this.outputStream = null; + } + + /** + * Start a new page. When processing has finished on the current page, the + * {@link #endPage()}method must be invoked to mark the page ending. + * + * @param pageWidth + * the width of the page + * @param pageHeight + * the height of the page + * @param pageRotation + * the rotation of the page + * @param pageWidthRes + * the width resolution of the page + * @param pageHeightRes + * the height resolution of the page + */ + public void startPage(int pageWidth, int pageHeight, int pageRotation, + int pageWidthRes, int pageHeightRes) { + currentPageObject = factory.createPage(pageWidth, pageHeight, + pageRotation, pageWidthRes, pageHeightRes); + currentPage = currentPageObject; + currentOverlay = null; + } + + /** + * Start a new overlay. When processing has finished on the current overlay, + * the {@link #endOverlay()}method must be invoked to mark the overlay + * ending. + * + * @param x + * the x position of the overlay on the page + * @param y + * the y position of the overlay on the page + * @param width + * the width of the overlay + * @param height + * the height of the overlay + * @param widthRes + * the width resolution of the overlay + * @param heightRes + * the height resolution of the overlay + * @param overlayRotation + * the rotation of the overlay + */ + public void startOverlay(int x, int y, int width, int height, int widthRes, + int heightRes, int overlayRotation) { + this.currentOverlay = factory.createOverlay( + width, height, widthRes, heightRes, overlayRotation); + + String overlayName = currentOverlay.getName(); + currentPageObject.createIncludePageOverlay(overlayName, x, y, 0); + currentPage = currentOverlay; + } + + /** + * Helper method to mark the end of the current overlay. + * + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public void endOverlay() throws IOException { + if (currentOverlay != null) { + currentOverlay.endPage(); + currentOverlay = null; + currentPage = currentPageObject; + } + } + + /** + * Helper method to save the current page. + * + * @return current page object that was saved + */ + public PageObject savePage() { + PageObject pageObject = currentPageObject; + if (currentPageGroup != null) { + currentPageGroup.addPage(currentPageObject); + } else { + document.addPage(currentPageObject); + } + currentPageObject = null; + currentPage = null; + return pageObject; + } + + /** + * Helper method to restore the current page. + * + * @param pageObject + * page object + */ + public void restorePage(PageObject pageObject) { + currentPageObject = pageObject; + currentPage = pageObject; + } + + /** + * Helper method to mark the end of the current page. + * + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public void endPage() throws IOException { + if (currentPageObject != null) { + currentPageObject.endPage(); + if (currentPageGroup != null) { + currentPageGroup.addPage(currentPageObject); + currentPageGroup.writeToStream(this.outputStream); + } else { + document.addPage(currentPageObject); + document.writeToStream(this.outputStream); + } + currentPageObject = null; + currentPage = null; + } + } + + /** + * Creates the given page fonts in the current page + * + * @param pageFonts + * a collection of AFP font attributes + */ + public void addFontsToCurrentPage(Map pageFonts) { + Iterator iter = pageFonts.values().iterator(); + while (iter.hasNext()) { + AFPFontAttributes afpFontAttributes = (AFPFontAttributes) iter + .next(); + createFont(afpFontAttributes.getFontReference(), afpFontAttributes + .getFont(), afpFontAttributes.getPointSize()); + } + } + + /** + * Helper method to create a map coded font object on the current page, this + * method delegates the construction of the map coded font object to the + * active environment group on the current page. + * + * @param fontReference + * the font number used as the resource identifier + * @param font + * the font + * @param size + * the point size of the font + */ + public void createFont(int fontReference, AFPFont font, int size) { + currentPage.createFont(fontReference, font, size); + } + + /** + * Returns a point on the current page + * + * @param x the X-coordinate + * @param y the Y-coordinate + * @return a point on the current page + */ + private Point getPoint(int x, int y) { + Point p = new Point(); + int rotation = paintingState.getRotation(); + switch (rotation) { + case 90: + p.x = y; + p.y = currentPage.getWidth() - x; + break; + case 180: + p.x = currentPage.getWidth() - x; + p.y = currentPage.getHeight() - y; + break; + case 270: + p.x = currentPage.getHeight() - y; + p.y = x; + break; + default: + p.x = x; + p.y = y; + break; + } + return p; + } + + /** + * Helper method to create text on the current page, this method delegates + * to the current presentation text object in order to construct the text. + * + * @param textDataInfo + * the afp text data + * @throws UnsupportedEncodingException thrown if character encoding is not supported + */ + public void createText(AFPTextDataInfo textDataInfo) throws UnsupportedEncodingException { + int rotation = paintingState.getRotation(); + if (rotation != 0) { + textDataInfo.setRotation(rotation); + Point p = getPoint(textDataInfo.getX(), textDataInfo.getY()); + textDataInfo.setX(p.x); + textDataInfo.setY(p.y); + } + currentPage.createText(textDataInfo); + } + + /** + * Method to create a line on the current page. + * + * @param lineDataInfo the line data information. + */ + public void createLine(AFPLineDataInfo lineDataInfo) { + currentPage.createLine(lineDataInfo); + } + + /** + * This method will create shading on the page using the specified + * coordinates (the shading contrast is controlled via the red, green, blue + * parameters, by converting this to grey scale). + * + * @param x + * the x coordinate of the shading + * @param y + * the y coordinate of the shading + * @param w + * the width of the shaded area + * @param h + * the height of the shaded area + * @param col + * the shading color + */ + public void createShading(int x, int y, int w, int h, Color col) { + currentPageObject.createShading(x, y, w, h, col.getRed(), col.getGreen(), col.getBlue()); + } + + /** + * Helper method which allows creation of the MPO object, via the AEG. And + * the IPO via the Page. (See actual object for descriptions.) + * + * @param name + * the name of the static overlay + */ + public void createIncludePageOverlay(String name) { + currentPageObject.createIncludePageOverlay(name, 0, 0, paintingState.getRotation()); + currentPageObject.getActiveEnvironmentGroup().createOverlay(name); + } + + /** + * Helper method which allows creation of the IMM object. + * + * @param name + * the name of the medium map + */ + public void createInvokeMediumMap(String name) { + currentPageGroup.createInvokeMediumMap(name); + } + + /** + * Creates an IncludePageSegment on the current page. + * + * @param name + * the name of the include page segment + * @param x + * the x coordinate for the overlay + * @param y + * the y coordinate for the overlay + */ + public void createIncludePageSegment(String name, int x, int y) { + int xOrigin; + int yOrigin; + int orientation = paintingState.getRotation(); + switch (orientation) { + case 90: + xOrigin = currentPage.getWidth() - y; + yOrigin = x; + break; + case 180: + xOrigin = currentPage.getWidth() - x; + yOrigin = currentPage.getHeight() - y; + break; + case 270: + xOrigin = y; + yOrigin = currentPage.getHeight() - x; + break; + default: + xOrigin = x; + yOrigin = y; + break; + } + currentPage.createIncludePageSegment(name, xOrigin, yOrigin); + } + + /** + * Creates a TagLogicalElement on the current page. + * + * @param attributes + * the array of key value pairs. + */ + public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) { + for (int i = 0; i < attributes.length; i++) { + String name = attributes[i].getKey(); + String value = attributes[i].getValue(); + currentPage.createTagLogicalElement(name, value); + } + } + + /** + * Creates a TagLogicalElement on the current page group. + * + * @param attributes + * the array of key value pairs. + */ + public void createPageGroupTagLogicalElement(TagLogicalElementBean[] attributes) { + for (int i = 0; i < attributes.length; i++) { + String name = attributes[i].getKey(); + String value = attributes[i].getValue(); + currentPageGroup.createTagLogicalElement(name, value); + } + } + + /** + * Creates a TagLogicalElement on the current page or page group + * + * @param name + * The tag name + * @param value + * The tag value + */ + public void createTagLogicalElement(String name, String value) { + if (currentPageGroup != null) { + currentPageGroup.createTagLogicalElement(name, value); + } else { + currentPage.createTagLogicalElement(name, value); + } + } + + /** + * Creates a NoOperation item + * + * @param content + * byte data + */ + public void createNoOperation(String content) { + currentPage.createNoOperation(content); + } + + /** + * Returns the current page group + * + * @return the current page group + */ + public PageGroup getCurrentPageGroup() { + return this.currentPageGroup; + } + + /** + * Start a new document. + * + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public void startDocument() throws IOException { + this.document = factory.createDocument(); + document.writeToStream(this.outputStream); + } + + /** + * Start a new page group. When processing has finished on the current page + * group the {@link #endPageGroup()}method must be invoked to mark the page + * group ending. + * + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public void startPageGroup() throws IOException { + endPageGroup(); + this.currentPageGroup = factory.createPageGroup(); + } + + /** + * Helper method to mark the end of the page group. + * + * @throws IOException thrown if an I/O exception of some sort has occurred + */ + public void endPageGroup() throws IOException { + if (currentPageGroup != null) { + currentPageGroup.endPageGroup(); + document.addPageGroup(currentPageGroup); + document.writeToStream(outputStream); + currentPageGroup = null; + } + } + + /** + * Sets the MO:DCA interchange set to use + * + * @param interchangeSet the MO:DCA interchange set + */ + public void setInterchangeSet(InterchangeSet interchangeSet) { + this.interchangeSet = interchangeSet; + } + + /** + * Returns the MO:DCA interchange set in use + * + * @return the MO:DCA interchange set in use + */ + public InterchangeSet getInterchangeSet() { + return this.interchangeSet; + } + + /** + * Returns the resource group for a given resource info + * + * @param level a resource level + * @return a resource group for the given resource info + */ + public ResourceGroup getResourceGroup(AFPResourceLevel level) { + ResourceGroup resourceGroup = null; + if (level.isDocument()) { + resourceGroup = document.getResourceGroup(); + } else if (level.isPageGroup()) { + resourceGroup = currentPageGroup.getResourceGroup(); + } else if (level.isPage()) { + resourceGroup = currentPageObject.getResourceGroup(); + } + return resourceGroup; + } + +} diff --git a/src/java/org/apache/fop/afp/Factory.java b/src/java/org/apache/fop/afp/Factory.java new file mode 100644 index 000000000..a278a5761 --- /dev/null +++ b/src/java/org/apache/fop/afp/Factory.java @@ -0,0 +1,635 @@ +/* + * 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.afp; + +import java.io.OutputStream; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.goca.GraphicsData; +import org.apache.fop.afp.ioca.ImageContent; +import org.apache.fop.afp.ioca.ImageRasterData; +import org.apache.fop.afp.ioca.ImageSegment; +import org.apache.fop.afp.ioca.ImageSizeParameter; +import org.apache.fop.afp.modca.ActiveEnvironmentGroup; +import org.apache.fop.afp.modca.ContainerDataDescriptor; +import org.apache.fop.afp.modca.Document; +import org.apache.fop.afp.modca.GraphicsDataDescriptor; +import org.apache.fop.afp.modca.GraphicsObject; +import org.apache.fop.afp.modca.IMImageObject; +import org.apache.fop.afp.modca.ImageDataDescriptor; +import org.apache.fop.afp.modca.ImageObject; +import org.apache.fop.afp.modca.IncludeObject; +import org.apache.fop.afp.modca.IncludePageSegment; +import org.apache.fop.afp.modca.InvokeMediumMap; +import org.apache.fop.afp.modca.MapCodedFont; +import org.apache.fop.afp.modca.MapContainerData; +import org.apache.fop.afp.modca.MapDataResource; +import org.apache.fop.afp.modca.ObjectAreaDescriptor; +import org.apache.fop.afp.modca.ObjectAreaPosition; +import org.apache.fop.afp.modca.ObjectContainer; +import org.apache.fop.afp.modca.ObjectEnvironmentGroup; +import org.apache.fop.afp.modca.Overlay; +import org.apache.fop.afp.modca.PageDescriptor; +import org.apache.fop.afp.modca.PageGroup; +import org.apache.fop.afp.modca.PageObject; +import org.apache.fop.afp.modca.PresentationEnvironmentControl; +import org.apache.fop.afp.modca.PresentationTextDescriptor; +import org.apache.fop.afp.modca.PresentationTextObject; +import org.apache.fop.afp.modca.ResourceEnvironmentGroup; +import org.apache.fop.afp.modca.ResourceGroup; +import org.apache.fop.afp.modca.ResourceObject; +import org.apache.fop.afp.modca.StreamedResourceGroup; +import org.apache.fop.afp.modca.TagLogicalElement; +import org.apache.fop.afp.util.StringUtils; + +/** + * Creator of MO:DCA structured field objects + */ +public class Factory { + + /** Static logging instance */ + private static final Log log = LogFactory.getLog(Factory.class); + + private static final String OBJECT_ENVIRONMENT_GROUP_NAME_PREFIX = "OEG"; + + private static final String ACTIVE_ENVIRONMENT_GROUP_NAME_PREFIX = "AEG"; + + private static final String IMAGE_NAME_PREFIX = "IMG"; + + private static final String GRAPHIC_NAME_PREFIX = "GRA"; + + private static final String BARCODE_NAME_PREFIX = "BAR"; + +// private static final String OTHER_NAME_PREFIX = "OTH"; + + private static final String OBJECT_CONTAINER_NAME_PREFIX = "OC"; + + private static final String RESOURCE_NAME_PREFIX = "RES"; + + private static final String RESOURCE_GROUP_NAME_PREFIX = "RG"; + + private static final String PAGE_GROUP_NAME_PREFIX = "PGP"; + + private static final String PAGE_NAME_PREFIX = "PGN"; + + private static final String OVERLAY_NAME_PREFIX = "OVL"; + + private static final String PRESENTATION_TEXT_NAME_PREFIX = "PT"; + + private static final String DOCUMENT_NAME_PREFIX = "DOC"; + + private static final String IM_IMAGE_NAME_PREFIX = "IMIMG"; + + private static final String IMAGE_SEGMENT_NAME_PREFIX = "IS"; + + + /** the page group count */ + private int pageGroupCount = 0; + + /** the page count */ + private int pageCount = 0; + + /** the image count */ + private int imageCount = 0; + + /** the im image count */ + private int imImageCount = 0; + + /** the image segment count */ + private int imageSegmentCount = 0; + + /** the graphic count */ + private int graphicCount = 0; + + /** the object container count */ + private int objectContainerCount = 0; + + /** the resource count */ + private int resourceCount = 0; + + /** the resource group count */ + private int resourceGroupCount = 0; + + /** the overlay count */ + private int overlayCount = 0; + + /** the presentation text object count */ + private int textObjectCount = 0; + + /** the active environment group count */ + private int activeEnvironmentGroupCount = 0; + + /** the document count */ + private int documentCount = 0; + + /** the object environment group count */ + private int objectEnvironmentGroupCount = 0; + + /** + * Main constructor + */ + public Factory() { + } + + /** + * Creates a new IOCA {@link ImageObject} + * + * @return a new {@link ImageObject} + */ + public ImageObject createImageObject() { + String name = IMAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++imageCount), '0', 5); + ImageObject imageObject = new ImageObject(this, name); + return imageObject; + } + + /** + * Creates an IOCA {@link IMImageObject} + * + * @return a new {@link IMImageObject} + */ + public IMImageObject createIMImageObject() { + String name = IM_IMAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++imImageCount), '0', 3); + IMImageObject imImageObject = new IMImageObject(name); + return imImageObject; + } + + /** + * Creates a new GOCA {@link GraphicsObject} + * + * @return a new {@link GraphicsObject} + */ + public GraphicsObject createGraphicsObject() { + String name = GRAPHIC_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++graphicCount), '0', 5); + GraphicsObject graphicsObj = new GraphicsObject(this, name); + return graphicsObj; + } + + /** + * Creates a new MO:DCA {@link ObjectContainer} + * + * @return a new {@link ObjectContainer} + */ + public ObjectContainer createObjectContainer() { + String name = OBJECT_CONTAINER_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++objectContainerCount), '0', 6); + return new ObjectContainer(this, name); + } + + /** + * Creates a new MO:DCA {@link ResourceObject} + * + * @param resourceName the resource object name + * @return a new {@link ResourceObject} + */ + public ResourceObject createResource(String resourceName) { + return new ResourceObject(resourceName); + } + + /** + * Creates a new MO:DCA {@link ResourceObject} + * + * @return a new {@link ResourceObject} + */ + public ResourceObject createResource() { + String name = RESOURCE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++resourceCount), '0', 5); + return createResource(name); + } + + /** + * Creates a new MO:DCA {@link PageGroup} + * + * @return a new {@link PageGroup} + */ + public PageGroup createPageGroup() { + String name = PAGE_GROUP_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++pageGroupCount), '0', 5); + return new PageGroup(this, name); + } + + /** + * Creates a new MO:DCA {@link ActiveEnvironmentGroup} + * + * @param width the page width + * @param height the page height + * @param widthRes the page width resolution + * @param heightRes the page height resolution + * @return a new {@link ActiveEnvironmentGroup} + */ + public ActiveEnvironmentGroup createActiveEnvironmentGroup( + int width, int height, int widthRes, int heightRes) { + String name = ACTIVE_ENVIRONMENT_GROUP_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++activeEnvironmentGroupCount ), '0', 5); + return new ActiveEnvironmentGroup(this, name, width, height, widthRes, heightRes); + } + + /** + * Creates a new MO:DCA {@link ResourceGroup} + * + * @return a new {@link ResourceGroup} + */ + public ResourceGroup createResourceGroup() { + String name = RESOURCE_GROUP_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++resourceGroupCount), '0', 6); + return new ResourceGroup(name); + } + + /** + * Creates a new MO:DCA {@link StreamedResourceGroup} + * + * @param os the outputstream of the streamed resource group + * @return a new {@link StreamedResourceGroup} + */ + public StreamedResourceGroup createStreamedResourceGroup(OutputStream os) { + String name = RESOURCE_GROUP_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++resourceGroupCount), '0', 6); + return new StreamedResourceGroup(name, os); + } + + /** + * Creates a new MO:DCA {@link PageObject}. + * + * @param pageWidth + * the width of the page + * @param pageHeight + * the height of the page + * @param pageRotation + * the rotation of the page + * @param pageWidthRes + * the width resolution of the page + * @param pageHeightRes + * the height resolution of the page + * + * @return a new {@link PageObject} + */ + public PageObject createPage(int pageWidth, int pageHeight, int pageRotation, + int pageWidthRes, int pageHeightRes) { + String pageName = PAGE_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++pageCount), '0', 5); + return new PageObject(this, pageName, pageWidth, pageHeight, + pageRotation, pageWidthRes, pageHeightRes); + } + + + /** + * Creates a new MO:DCA {@link PresentationTextObject}. + * + * @return a new {@link PresentationTextObject} + */ + public PresentationTextObject createPresentationTextObject() { + String textObjectName = PRESENTATION_TEXT_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++textObjectCount), '0', 6); + return new PresentationTextObject(textObjectName); + } + + + /** + * Creates a new MO:DCA {@link Overlay}. + * + * @param width + * the width of the overlay + * @param height + * the height of the overlay + * @param widthRes + * the width resolution of the overlay + * @param heightRes + * the height resolution of the overlay + * @param overlayRotation + * the rotation of the overlay + * + * @return a new {@link Overlay}. + */ + public Overlay createOverlay(int width, int height, + int widthRes, int heightRes, int overlayRotation) { + String overlayName = OVERLAY_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++overlayCount), '0', 5); + Overlay overlay = new Overlay(this, overlayName, width, height, + overlayRotation, widthRes, heightRes); + return overlay; + } + + /** + * Creates a MO:DCA {@link Document} + * + * @return a new {@link Document} + */ + public Document createDocument() { + String documentName = DOCUMENT_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++documentCount), '0', 5); + Document document = new Document(this, documentName); + return document; + } + + /** + * Creates a MO:DCA {@link MapCodedFont} + * + * @return a new {@link MapCodedFont} + */ + public MapCodedFont createMapCodedFont() { + MapCodedFont mapCodedFont = new MapCodedFont(); + return mapCodedFont; + } + + /** + * Creates a MO:DCA {@link IncludePageSegment} + * + * @param name the page segment name + * @param x the x coordinate + * @param y the y coordinate + * + * @return a new {@link IncludePageSegment} + */ + public IncludePageSegment createIncludePageSegment(String name, int x, int y) { + IncludePageSegment includePageSegment = new IncludePageSegment(name, x, y); + return includePageSegment; + } + + /** + * Creates a MO:DCA {@link IncludeObject} + * + * @param name the name of this include object + * @return a new {@link IncludeObject} + */ + public IncludeObject createInclude(String name) { + IncludeObject includeObject = new IncludeObject(name); + return includeObject; + } + + /** + * Creates a MO:DCA {@link TagLogicalElement} + * + * @param name name of the element + * @param value value of the element + * @return a new {@link TagLogicalElement} + */ + public TagLogicalElement createTagLogicalElement(String name, String value) { + TagLogicalElement tle = new TagLogicalElement(name, value); + return tle; + } + + /** + * Creates a new {@link DataStream} + * + * @param paintingState the AFP painting state + * @param outputStream an outputstream to write to + * @return a new {@link DataStream} + */ + public DataStream createDataStream(AFPPaintingState paintingState, OutputStream outputStream) { + DataStream dataStream = new DataStream(this, paintingState, outputStream); + return dataStream; + } + + /** + * Creates a new MO:DCA {@link PageDescriptor} + * + * @param width the page width. + * @param height the page height. + * @param widthRes the page width resolution. + * @param heightRes the page height resolution. + * @return a new {@link PageDescriptor} + */ + public PageDescriptor createPageDescriptor(int width, int height, int widthRes, int heightRes) { + PageDescriptor pageDescriptor = new PageDescriptor(width, height, widthRes, heightRes); + return pageDescriptor; + } + + /** + * Returns a new MO:DCA {@link ObjectEnvironmentGroup} + * + * @return a new {@link ObjectEnvironmentGroup} + */ + public ObjectEnvironmentGroup createObjectEnvironmentGroup() { + String oegName = OBJECT_ENVIRONMENT_GROUP_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++objectEnvironmentGroupCount), '0', 5); + ObjectEnvironmentGroup objectEnvironmentGroup = new ObjectEnvironmentGroup(oegName); + return objectEnvironmentGroup; + } + + /** + * Creates a new GOCA {@link GraphicsData} + * + * @return a new {@link GraphicsData} + */ + public GraphicsData createGraphicsData() { + GraphicsData graphicsData = new GraphicsData(); + return graphicsData; + } + + /** + * Creates a new {@link ObjectAreaDescriptor} + * + * @param width the object width. + * @param height the object height. + * @param widthRes the object width resolution. + * @param heightRes the object height resolution. + * @return a new {@link ObjectAreaDescriptor} + */ + public ObjectAreaDescriptor createObjectAreaDescriptor( + int width, int height, int widthRes, int heightRes) { + ObjectAreaDescriptor objectAreaDescriptor + = new ObjectAreaDescriptor(width, height, widthRes, heightRes); + return objectAreaDescriptor; + } + + /** + * Creates a new {@link ObjectAreaPosition} + * + * @param x the x coordinate. + * @param y the y coordinate. + * @param rotation the coordinate system rotation (must be 0, 90, 180, 270). + * @return a new {@link ObjectAreaPosition} + */ + public ObjectAreaPosition createObjectAreaPosition(int x, int y, + int rotation) { + ObjectAreaPosition objectAreaPosition = new ObjectAreaPosition( + x, y, rotation); + return objectAreaPosition; + } + + /** + * Creates a new {@link ImageDataDescriptor} + * + * @param width the image width + * @param height the image height + * @param widthRes the x resolution of the image + * @param heightRes the y resolution of the image + * @return a new {@link ImageDataDescriptor} + */ + public ImageDataDescriptor createImageDataDescriptor( + int width, int height, int widthRes, int heightRes) { + ImageDataDescriptor imageDataDescriptor = new ImageDataDescriptor( + width, height, widthRes, heightRes); + return imageDataDescriptor; + } + + /** + * Creates a new GOCA {@link GraphicsDataDescriptor} + * + * @param xlwind the left edge of the graphics window + * @param xrwind the right edge of the graphics window + * @param ybwind the top edge of the graphics window + * @param ytwind the bottom edge of the graphics window + * @param widthRes the x resolution of the graphics window + * @param heightRes the y resolution of the graphics window + * @return a new {@link GraphicsDataDescriptor} + */ + public GraphicsDataDescriptor createGraphicsDataDescriptor( + int xlwind, int xrwind, int ybwind, int ytwind, int widthRes, int heightRes) { + GraphicsDataDescriptor graphicsDataDescriptor = new GraphicsDataDescriptor( + xlwind, xrwind, ybwind, ytwind, widthRes, heightRes); + return graphicsDataDescriptor; + } + + /** + * Creates a new MO:DCA {@link ContainerDataDescriptor} + * + * @param dataWidth the container data width + * @param dataHeight the container data height + * @param widthRes the container data width resolution + * @param heightRes the container data height resolution + * @return a new {@link ContainerDataDescriptor} + */ + public ContainerDataDescriptor createContainerDataDescriptor( + int dataWidth, int dataHeight, int widthRes, int heightRes) { + ContainerDataDescriptor containerDataDescriptor + = new ContainerDataDescriptor(dataWidth, dataHeight, widthRes, heightRes); + return containerDataDescriptor; + } + + /** + * Creates a new MO:DCA {@link MapContainerData} + * + * @param optionValue the option value + * @return a new {@link MapContainerData} + */ + public MapContainerData createMapContainerData(byte optionValue) { + MapContainerData mapContainerData = new MapContainerData(optionValue); + return mapContainerData; + } + + /** + * Creates a new MO:DCA {@link MapDataResource} + * + * @return a new {@link MapDataResource} + */ + public MapDataResource createMapDataResource() { + MapDataResource mapDataResource = new MapDataResource(); + return mapDataResource; + } + + /** + * Creates a new PTOCA {@link PresentationTextDescriptor} + * + * @return a new {@link PresentationTextDescriptor} + */ + public PresentationTextDescriptor createPresentationTextDataDescriptor( + int width, int height, int widthRes, int heightRes) { + PresentationTextDescriptor presentationTextDescriptor + = new PresentationTextDescriptor(width, height, + widthRes, heightRes); + return presentationTextDescriptor; + } + + /** + * Creates a new MO:DCA {@link PresentationEnvironmentControl} + * + * @return a new {@link PresentationEnvironmentControl} + */ + public PresentationEnvironmentControl createPresentationEnvironmentControl() { + PresentationEnvironmentControl presentationEnvironmentControl + = new PresentationEnvironmentControl(); + return presentationEnvironmentControl; + } + + /** + * Creates a new MO:DCA {@link InvokeMediumMap} + * + * @param name the object name + * @return a new {@link InvokeMediumMap} + */ + public InvokeMediumMap createInvokeMediumMap(String name) { + InvokeMediumMap invokeMediumMap = new InvokeMediumMap(name); + return invokeMediumMap; + } + + /** + * Creates a new MO:DCA {@link ResourceEnvironmentGroup} + * + * @return a new {@link ResourceEnvironmentGroup} + */ + public ResourceEnvironmentGroup createResourceEnvironmentGroup() { + ResourceEnvironmentGroup resourceEnvironmentGroup = new ResourceEnvironmentGroup(); + return resourceEnvironmentGroup; + } + + /** + * Creates a new IOCA {@link ImageSegment} + * + * @return a new {@link ImageSegment} + */ + public ImageSegment createImageSegment() { + String name = IMAGE_SEGMENT_NAME_PREFIX + + StringUtils.lpad(String.valueOf(++imageSegmentCount), '0', 2); + ImageSegment imageSegment = new ImageSegment(this, name); + return imageSegment; + } + + /** + * Creates an new IOCA {@link ImageContent} + * + * @return an {@link ImageContent} + */ + public ImageContent createImageContent() { + ImageContent imageContent = new ImageContent(); + return imageContent; + } + + /** + * Creates a new IOCA {@link ImageRasterData} + * + * @param rasterData raster data + * @return a new {@link ImageRasterData} + */ + public ImageRasterData createImageRasterData(byte[] rasterData) { + ImageRasterData imageRasterData = new ImageRasterData(rasterData); + return imageRasterData; + } + + /** + * Creates an new IOCA {@link ImageSizeParameter}. + * + * @param hsize The horizontal size of the image. + * @param vsize The vertical size of the image. + * @param hresol The horizontal resolution of the image. + * @param vresol The vertical resolution of the image. + * @return a new {@link ImageSizeParameter} + */ + public ImageSizeParameter createImageSizeParameter(int hsize, int vsize, + int hresol, int vresol) { + ImageSizeParameter imageSizeParameter + = new ImageSizeParameter(hsize, vsize, hresol, vresol); + return imageSizeParameter; + } + +} diff --git a/src/java/org/apache/fop/afp/PaintingInfo.java b/src/java/org/apache/fop/afp/PaintingInfo.java new file mode 100644 index 000000000..e53f28306 --- /dev/null +++ b/src/java/org/apache/fop/afp/PaintingInfo.java @@ -0,0 +1,27 @@ +/* + * 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.afp; + +/** + * Generic painting information interface + */ +public interface PaintingInfo { + +} diff --git a/src/java/org/apache/fop/afp/RectanglePaintingInfo.java b/src/java/org/apache/fop/afp/RectanglePaintingInfo.java new file mode 100644 index 000000000..64503d0b8 --- /dev/null +++ b/src/java/org/apache/fop/afp/RectanglePaintingInfo.java @@ -0,0 +1,84 @@ +/* + * 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.afp; + + +/** + * Filled rectangle painting information + */ +public class RectanglePaintingInfo implements PaintingInfo { + + private final float x; + private final float y; + private final float width; + private final float height; + + /** + * Main constructor + * + * @param x the x coordinate + * @param y the y coordinate + * @param width the width + * @param height the height + */ + public RectanglePaintingInfo(float x, float y, float width, float height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + /** + * Returns the x coordinate + * + * @return the x coordinate + */ + protected float getX() { + return x; + } + + /** + * Returns the y coordinate + * + * @return the y coordinate + */ + protected float getY() { + return y; + } + + /** + * Returns the width + * + * @return the width + */ + protected float getWidth() { + return width; + } + + /** + * Returns the height + * + * @return the height + */ + protected float getHeight() { + return height; + } + +} diff --git a/src/java/org/apache/fop/afp/Startable.java b/src/java/org/apache/fop/afp/Startable.java new file mode 100644 index 000000000..fd05b8455 --- /dev/null +++ b/src/java/org/apache/fop/afp/Startable.java @@ -0,0 +1,40 @@ +/* + * 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.afp; + +/** + * Set and expose whether an object has started or not. + */ +public interface Startable { + + /** + * Sets whether or not this object has started or not + * + * @param complete true if this object has started + */ + void setStarted(boolean started); + + /** + * Returns true if this object has started + * + * @return true if this object has started + */ + boolean isStarted(); +} diff --git a/src/java/org/apache/fop/afp/Streamable.java b/src/java/org/apache/fop/afp/Streamable.java new file mode 100644 index 000000000..cd731ab47 --- /dev/null +++ b/src/java/org/apache/fop/afp/Streamable.java @@ -0,0 +1,38 @@ +/* + * 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.afp; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Implementing object is able to write to an OutputStream + */ +public interface Streamable { + + /** + * DataStream objects must implement the writeToStream() + * method to write its data to the given OutputStream + * + * @param os the outputsteam stream + * @throws java.io.IOException an I/O exception of some sort has occurred. + */ + void writeToStream(OutputStream os) throws IOException; +} diff --git a/src/java/org/apache/fop/afp/StructuredData.java b/src/java/org/apache/fop/afp/StructuredData.java new file mode 100644 index 000000000..99555b39b --- /dev/null +++ b/src/java/org/apache/fop/afp/StructuredData.java @@ -0,0 +1,33 @@ +/* + * 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.afp; + +/** + * An AFP object which is able to know its own data length prior to writeToStream() + */ +public interface StructuredData { + + /** + * Returns the data length of this structured field + * + * @return the data length of this structured field + */ + int getDataLength(); +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java new file mode 100644 index 000000000..c39bf5e1e --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java @@ -0,0 +1,157 @@ +/* + * 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.afp.fonts; + +import org.apache.fop.fonts.Base14Font; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.base14.Courier; +import org.apache.fop.fonts.base14.CourierBold; +import org.apache.fop.fonts.base14.CourierBoldOblique; +import org.apache.fop.fonts.base14.CourierOblique; +import org.apache.fop.fonts.base14.Helvetica; +import org.apache.fop.fonts.base14.HelveticaBold; +import org.apache.fop.fonts.base14.HelveticaOblique; +import org.apache.fop.fonts.base14.TimesBold; +import org.apache.fop.fonts.base14.TimesBoldItalic; +import org.apache.fop.fonts.base14.TimesItalic; +import org.apache.fop.fonts.base14.TimesRoman; + +/** + * Sets up a typical Base 12 font configuration for AFP + */ +public class AFPBase12FontCollection implements FontCollection { + + /** standard raster font sizes */ + private static final int[] RASTER_SIZES = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 30, 36}; + + /** standard raster font charset references */ + private static final String[] CHARSET_REF = { + "60", "70", "80", "90", "00", "A0", "B0", "D0", "F0", "H0", "J0", "N0", "T0", "Z0"}; + + private void addCharacterSet(RasterFont font, String charsetName, Base14Font base14) { + for (int i = 0; i < RASTER_SIZES.length; i++) { + int size = RASTER_SIZES[i]; + FopCharacterSet characterSet = new FopCharacterSet( + CharacterSet.DEFAULT_CODEPAGE, CharacterSet.DEFAULT_ENCODING, + charsetName + CHARSET_REF[i], size, base14); + font.addCharacterSet(size, characterSet); + } + } + + private int addFontProperties(FontInfo fontInfo, AFPFont font, + String[] names, String style, int weight, int num) { + String internalFontKey = "F" + num; + fontInfo.addMetrics(internalFontKey, font); + fontInfo.addFontProperties(internalFontKey, names, style, weight); + num++; + return num; + } + + /** {@inheritDoc} */ + public int setup(int start, FontInfo fontInfo) { + + /** + * Add the base 12 fonts (Helvetica, Times and Courier) + * + * Note: this default font configuration may not be available + * on your AFP environment. + */ + int num = start; + RasterFont font = null; + + /** standard font family reference names for Helvetica font */ + final String[] helveticaNames = {"Helvetica", "Arial", "sans-serif"}; + font = new RasterFont("Helvetica"); + addCharacterSet(font, "C0H200", new Helvetica()); + num = addFontProperties(fontInfo, font, helveticaNames, + Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num); + + font = new RasterFont("Helvetica Italic"); + addCharacterSet(font, "C0H300", new HelveticaOblique()); + num = addFontProperties(fontInfo, font, helveticaNames, + Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num); + + font = new RasterFont("Helvetica (Semi) Bold"); + addCharacterSet(font, "C0H400", new HelveticaBold()); + num = addFontProperties(fontInfo, font, helveticaNames, + Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num); + + font = new RasterFont("Helvetica Italic (Semi) Bold"); + addCharacterSet(font, "C0H500", new HelveticaOblique()); + num = addFontProperties(fontInfo, font, helveticaNames, + Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num); + + + /** standard font family reference names for Times font */ + + /** any is treated as serif */ + final String[] timesNames = {"Times", "TimesRoman", "Times Roman", "Times-Roman", + "Times New Roman", "TimesNewRoman", "serif", "any"}; + + font = new RasterFont("Times Roman"); + addCharacterSet(font, "CON200", new TimesRoman()); + num = addFontProperties(fontInfo, font, timesNames, + Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num); + + font = new RasterFont("Times Roman Italic"); + addCharacterSet(font, "CON300", new TimesItalic()); + num = addFontProperties(fontInfo, font, timesNames, + Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num); + + font = new RasterFont("Times Roman Bold"); + addCharacterSet(font, "CON400", new TimesBold()); + num = addFontProperties(fontInfo, font, timesNames, + Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num); + + font = new RasterFont("Times Roman Italic Bold"); + addCharacterSet(font, "CON500", new TimesBoldItalic()); + num = addFontProperties(fontInfo, font, timesNames, + Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num); + + + /** standard font family reference names for Courier font */ + final String[] courierNames = {"Courier", "monospace"}; + + font = new RasterFont("Courier"); + addCharacterSet(font, "C04200", new Courier()); + num = addFontProperties(fontInfo, font, courierNames, + Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num); + + font = new RasterFont("Courier Italic"); + addCharacterSet(font, "C04300", new CourierOblique()); + num = addFontProperties(fontInfo, font, courierNames, + Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num); + + font = new RasterFont("Courier Bold"); + addCharacterSet(font, "C04400", new CourierBold()); + num = addFontProperties(fontInfo, font, courierNames, + Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num); + + font = new RasterFont("Courier Italic Bold"); + addCharacterSet(font, "C04500", new CourierBoldOblique()); + num = addFontProperties(fontInfo, font, courierNames, + Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num); + + return num; + } + +} diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java b/src/java/org/apache/fop/afp/fonts/AFPFont.java index 2819cf12c..dc8f9c315 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFont.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFont.java @@ -17,7 +17,8 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; + import java.util.Map; import java.util.Set; @@ -41,7 +42,6 @@ public abstract class AFPFont extends Typeface { */ public AFPFont(String name) { this.name = name; - } /** {@inheritDoc} */ @@ -106,4 +106,8 @@ public abstract class AFPFont extends Typeface { return true; } + /** {@inheritDoc} */ + public String toString() { + return "name=" + name; + } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/AFPFontAttributes.java b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java index fb6f82463..de7f7f5be 100644 --- a/src/java/org/apache/fop/render/afp/AFPFontAttributes.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java @@ -17,40 +17,30 @@ /* $Id$ */ -package org.apache.fop.render.afp; - -import org.apache.fop.render.afp.fonts.AFPFont; +package org.apache.fop.afp.fonts; /** * This class encapsulates the font attributes that need to be included * in the AFP data stream. This class does not assist in converting the * font attributes to AFP code pages and character set values. - * */ public class AFPFontAttributes { - /** - * The font reference - */ + /** the font reference */ private int fontReference; - /** - * The font key - */ - private String fontKey; + /** the font key */ + private final String fontKey; - /** - * The font - */ - private AFPFont font; + /** the font */ + private final AFPFont font; - /** - * The point size - */ - private int pointSize; + /** the point size */ + private final int pointSize; /** * Constructor for the AFPFontAttributes + * * @param fontKey the font key * @param font the font * @param pointSize the point size @@ -62,6 +52,8 @@ public class AFPFontAttributes { } /** + * Return the font + * * @return the font */ public AFPFont getFont() { @@ -69,6 +61,8 @@ public class AFPFontAttributes { } /** + * Return the FontKey attribute + * * @return the FontKey attribute */ public String getFontKey() { @@ -76,6 +70,8 @@ public class AFPFontAttributes { } /** + * Return the point size attribute + * * @return the point size attribute */ public int getPointSize() { @@ -83,6 +79,8 @@ public class AFPFontAttributes { } /** + * Return the FontReference attribute + * * @return the FontReference attribute */ public int getFontReference() { @@ -91,10 +89,18 @@ public class AFPFontAttributes { /** * Sets the FontReference attribute + * * @param fontReference the FontReference to set */ public void setFontReference(int fontReference) { this.fontReference = fontReference; } + /** {@inheritDoc} */ + public String toString() { + return "fontReference=" + fontReference + + ", fontKey=" + fontKey + + ", font=" + font + + ", pointSize=" + pointSize; + } } diff --git a/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java new file mode 100644 index 000000000..bf136225b --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/AFPFontCollection.java @@ -0,0 +1,92 @@ +/* + * 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.afp.fonts; + +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.afp.AFPEventProducer; +import org.apache.fop.events.EventBroadcaster; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontCollection; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; + +/** + * A base collection of AFP fonts + */ +public class AFPFontCollection implements FontCollection { + + private final EventBroadcaster eventBroadcaster; + + private final List/*<AFPFontInfo>*/ fontInfoList; + + /** + * Main constructor + * + * @param eventBroadcaster the event broadcaster + * @param fontInfoList the font info list + */ + public AFPFontCollection(EventBroadcaster eventBroadcaster, + List/*<AFPFontInfo>*/ fontInfoList) { + this.eventBroadcaster = eventBroadcaster; + this.fontInfoList = fontInfoList; + } + + /** {@inheritDoc} */ + public int setup(int start, FontInfo fontInfo) { + int num = 1; + AFPEventProducer eventProducer = AFPEventProducer.Provider.get(eventBroadcaster); + if (fontInfoList != null && fontInfoList.size() > 0) { + for (Iterator it = fontInfoList.iterator(); it.hasNext();) { + AFPFontInfo afpFontInfo = (AFPFontInfo)it.next(); + AFPFont afpFont = afpFontInfo.getAFPFont(); + List/*<FontTriplet>*/ tripletList = afpFontInfo.getFontTriplets(); + for (Iterator it2 = tripletList.iterator(); it2.hasNext();) { + FontTriplet triplet = (FontTriplet)it2.next(); + fontInfo.addFontProperties("F" + num, + triplet.getName(), triplet.getStyle(), triplet.getWeight()); + fontInfo.addMetrics("F" + num, afpFont); + num++; + } + } + if (fontInfo.fontLookup("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) { + eventProducer.warnMissingDefaultFont(this, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); + } + if (fontInfo.fontLookup("any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL) == null) { + eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_NORMAL); + } + if (fontInfo.fontLookup("any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD) == null) { + eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + } + if (fontInfo.fontLookup("any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD) == null) { + eventProducer.warnMissingDefaultFont(this, Font.STYLE_ITALIC, Font.WEIGHT_BOLD); + } + } else { + eventProducer.warnDefaultFontSetup(this); + + // Go with a default base 12 configuration for AFP environments + FontCollection base12FontCollection = new AFPBase12FontCollection(); + num = base12FontCollection.setup(num, fontInfo); + } + return num; + } + +} diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java b/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java index 42f333a66..0259435c6 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFontInfo.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFontInfo.java @@ -17,30 +17,33 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; import java.util.List; + /** * FontInfo contains meta information on fonts */ public class AFPFontInfo { private AFPFont font; - private List fontTriplets; + private List/*<FontTriplet>*/ tripletList; /** * Main constructor + * * @param afpFont The AFP Font - * @param fontTriplets List of font triplets to associate with this font + * @param tripletList List of font triplets to associate with this font */ - public AFPFontInfo(AFPFont afpFont, List fontTriplets) { + public AFPFontInfo(AFPFont afpFont, List/*<FontTriplet>*/ tripletList) { this.font = afpFont; - this.fontTriplets = fontTriplets; + this.tripletList = tripletList; } /** * Returns the afp font + * * @return the afp font */ public AFPFont getAFPFont() { @@ -49,10 +52,11 @@ public class AFPFontInfo { /** * Returns the list of font triplets associated with this font. + * * @return List of font triplets */ - public List getFontTriplets() { - return fontTriplets; + public List/*<FontTriplet>*/ getFontTriplets() { + return tripletList; } } diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java index 0c190738c..16c341ac4 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java +++ b/src/java/org/apache/fop/afp/fonts/AFPFontReader.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; import java.io.File; import java.io.FileNotFoundException; @@ -31,8 +31,8 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.modca.AFPConstants; -import org.apache.fop.render.afp.tools.StructuredFieldReader; +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.util.StructuredFieldReader; /** * The AFPFontReader is responsible for reading the font attributes from binary @@ -56,7 +56,7 @@ public final class AFPFontReader { /** * Static logging instance */ - protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.fonts"); + protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.fonts"); /** * Template used to convert lists to arrays. diff --git a/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java new file mode 100644 index 000000000..ee7a3c0eb --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/AFPPageFonts.java @@ -0,0 +1,64 @@ +/* + * 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.afp.fonts; + +/** + * Holds the current page fonts + */ +public class AFPPageFonts extends java.util.HashMap { + private static final long serialVersionUID = -4991896259427109041L; + + /** + * Default constructor + */ + public AFPPageFonts() { + super(); + } + + /** + * Parameterized constructor + * + * @param fonts an existing set of afp page fonts + */ + public AFPPageFonts(AFPPageFonts fonts) { + super(fonts); + } + + /** + * Registers a font on the current page and returns font attributes + * + * @param fontName the internal font name + * @param font the AFPFont + * @param fontSize the font point size + * @return newly registered AFPFontAttributes + */ + public AFPFontAttributes registerFont(String fontName, AFPFont font, int fontSize) { + String pageFontKey = fontName + "_" + fontSize; + AFPFontAttributes afpFontAttributes = (AFPFontAttributes)super.get(pageFontKey); + // Add to page font mapping if not already present + if (afpFontAttributes == null) { + afpFontAttributes = new AFPFontAttributes(fontName, font, fontSize); + super.put(pageFontKey, afpFontAttributes); + int fontRef = super.size(); + afpFontAttributes.setFontReference(fontRef); + } + return afpFontAttributes; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index f7680b15c..31b53bf08 100644 --- a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -25,8 +25,8 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.modca.AFPConstants; -import org.apache.fop.render.afp.tools.StringUtils; +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.util.StringUtils; /** * The IBM Font Object Content Architecture (FOCA) supports presentation @@ -51,10 +51,10 @@ public class CharacterSet { protected static final Log log = LogFactory.getLog(CharacterSet.class.getName()); /** default codepage */ - protected static final String DEFAULT_CODEPAGE = "T1V10500"; + public static final String DEFAULT_CODEPAGE = "T1V10500"; /** default encoding */ - protected static final String DEFAULT_ENCODING = "Cp500"; + public static final String DEFAULT_ENCODING = "Cp500"; private static final int MAX_NAME_LEN = 8; diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java index e13029717..88e99eccf 100644 --- a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; /** * The IBM Font Object Content Architecture (FOCA) supports presentation diff --git a/src/java/org/apache/fop/render/afp/exceptions/FontRuntimeException.java b/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java index a54e4ad67..86e41707f 100644 --- a/src/java/org/apache/fop/render/afp/exceptions/FontRuntimeException.java +++ b/src/java/org/apache/fop/afp/fonts/FontRuntimeException.java @@ -17,13 +17,15 @@ /* $Id$ */ -package org.apache.fop.render.afp.exceptions; +package org.apache.fop.afp.fonts; /** * A runtime exception for handling fatal errors in processing fonts. * <p/> */ -public class FontRuntimeException extends NestedRuntimeException { +public class FontRuntimeException extends RuntimeException { + + private static final long serialVersionUID = -2217420523816384707L; /** * Constructs a FontRuntimeException with the specified message. diff --git a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java index d5beb5a33..49e536eab 100644 --- a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; import org.apache.fop.fonts.Typeface; diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/afp/fonts/OutlineFont.java index 71c5dfb6f..28f2df6c4 100644 --- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/afp/fonts/OutlineFont.java @@ -17,7 +17,8 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; + /** * A font defined as a set of lines and curves as opposed to a bitmap font. An diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/afp/fonts/RasterFont.java index 5c1696aa4..c36027913 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/afp/fonts/RasterFont.java @@ -17,18 +17,14 @@ /* $Id$ */ -package org.apache.fop.render.afp.fonts; +package org.apache.fop.afp.fonts; -import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.fo.properties.FixedLength; -import org.apache.fop.render.afp.exceptions.FontRuntimeException; - /** * A font where each character is stored as an array of pixels (a bitmap). Such * fonts are not easily scalable, in contrast to vectored fonts. With this type @@ -39,9 +35,10 @@ import org.apache.fop.render.afp.exceptions.FontRuntimeException; public class RasterFont extends AFPFont { /** Static logging instance */ - protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.fonts"); + protected static final Log log = LogFactory.getLog("org.apache.fop.afp.fonts"); - private Map charSets = new HashMap(); + private final Map/*<String,CharacterSet>*/ charSets + = new java.util.HashMap/*<String,CharacterSet>*/(); private CharacterSet charSet = null; @@ -66,6 +63,9 @@ public class RasterFont extends AFPFont { this.charSet = characterSet; } + /** Describes the unit millipoint. */ + public static final String MPT = "mpt"; + /** * Get the character set metrics for the specified point size. * @@ -77,7 +77,7 @@ public class RasterFont extends AFPFont { String pointsize = String.valueOf(size / 1000); CharacterSet csm = (CharacterSet) charSets.get(pointsize); if (csm == null) { - csm = (CharacterSet) charSets.get(size + FixedLength.MPT); + csm = (CharacterSet) charSets.get(size + MPT); } if (csm == null) { // Get char set with nearest font size @@ -85,7 +85,7 @@ public class RasterFont extends AFPFont { for (Iterator it = charSets.entrySet().iterator(); it.hasNext();) { Map.Entry me = (Map.Entry)it.next(); String key = (String)me.getKey(); - if (!key.endsWith(FixedLength.MPT)) { + if (!key.endsWith(MPT)) { int mpt = Integer.parseInt(key) * 1000; if (Math.abs(size - mpt) < distance) { distance = Math.abs(size - mpt); @@ -95,7 +95,7 @@ public class RasterFont extends AFPFont { } } if (csm != null) { - charSets.put(size + FixedLength.MPT, csm); + charSets.put(size + MPT, csm); String msg = "No " + (size / 1000) + "pt font " + getFontName() + " found, substituted with " + pointsize + "pt font"; log.warn(msg); diff --git a/src/java/org/apache/fop/afp/fonts/package.html b/src/java/org/apache/fop/afp/fonts/package.html new file mode 100644 index 000000000..74f8bf450 --- /dev/null +++ b/src/java/org/apache/fop/afp/fonts/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.goca Package</TITLE> +<BODY> +<P>Contains a collection of AFP Graphics Object Content Architecture (GOCA) structured objects.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java new file mode 100644 index 000000000..3d8495667 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java @@ -0,0 +1,149 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * A base class encapsulating the structure of coordinate based GOCA objects + */ +public abstract class AbstractGraphicsCoord extends AbstractGraphicsDrawingOrder { + + /** array of x/y coordinates */ + protected int[] coords = null; + + protected boolean relative = false; + + /** + * Constructor + * + * @param coords the x/y coordinates for this object + */ + public AbstractGraphicsCoord(int[] coords) { + if (coords == null) { + relative = true; + } else { + this.coords = coords; + } + } + + /** + * Constructor + * + * @param coords the x/y coordinates for this object + * @param relative + */ + public AbstractGraphicsCoord(int[] coords, boolean relative) { + this(coords); + this.relative = relative; + } + + /** + * Constructor + * + * @param x the x coordinate for this object + * @param y the y coordinate for this object + */ + public AbstractGraphicsCoord(int x, int y) { + this(new int[] {x, y}); + } + + /** + * Constructor + * + * @param x1 the x1 coordinate for this object + * @param y1 the y1 coordinate for this object + * @param x2 the x2 coordinate for this object + * @param y2 the y2 coordinate for this object + */ + public AbstractGraphicsCoord(int x1, int y1, int x2, int y2) { + this(new int[] {x1, y1, x2, y2}); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2 + (coords != null ? coords.length * 2 : 0); + } + + /** + * Returns the coordinate data start index + * + * @return the coordinate data start index + */ + int getCoordinateDataStartIndex() { + return 2; + } + + /** + * Returns the coordinate data + * + * @return the coordinate data + */ + byte[] getData() { + byte[] data = super.getData(); + if (coords != null) { + addCoords(data, getCoordinateDataStartIndex()); + } + return data; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + os.write(getData()); + } + + /** + * Adds the coordinates to the structured field data + * + * @param data the structured field data + * @param fromIndex the start index + */ + protected void addCoords(byte[] data, int fromIndex) { + // X/Y POS + for (int i = 0; i < coords.length; i++, fromIndex += 2) { + byte[] coord = BinaryUtils.convert(coords[i], 2); + data[fromIndex] = coord[0]; + data[fromIndex + 1] = coord[1]; + } + } + + /** {@inheritDoc} */ + public String toString() { + String coordsStr = ""; + for (int i = 0; i < coords.length; i++) { + coordsStr += (i % 2 == 0) ? "x" : "y"; + coordsStr += (i / 2) + "=" + coords[i] + ","; + } + coordsStr = coordsStr.substring(0, coordsStr.length() - 1); + return getName() + "{" + coordsStr + "}"; + } + + /** + * Returns true if this is a relative drawing order + * + * @return true if this is a relative drawing order + */ + protected boolean isRelative() { + return this.relative; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java new file mode 100644 index 000000000..0d8f793c0 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrder.java @@ -0,0 +1,60 @@ +/* + * 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.afp.goca; + +import org.apache.fop.afp.StructuredData; +import org.apache.fop.afp.modca.AbstractAFPObject; + +/** + * A base GOCA drawing order + */ +public abstract class AbstractGraphicsDrawingOrder extends AbstractAFPObject + implements StructuredData { + + /** + * Returns the order code of this structured field + * + * @return the order code of this structured field + */ + abstract byte getOrderCode(); + + /** + * Returns the coordinate data + * + * @return the coordinate data + */ + byte[] getData() { + int len = getDataLength(); + byte[] data = new byte[len]; + data[0] = getOrderCode(); + data[1] = (byte)(len - 2); + return data; + } + + /** + * Returns the short name of this GOCA object + * + * @return the short name of this GOCA object + */ + public String getName() { + String className = getClass().getName(); + return className.substring(className.lastIndexOf(".") + 1); + } +} diff --git a/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java new file mode 100644 index 000000000..34398b094 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/AbstractGraphicsDrawingOrderContainer.java @@ -0,0 +1,158 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.afp.Completable; +import org.apache.fop.afp.Startable; +import org.apache.fop.afp.StructuredData; +import org.apache.fop.afp.modca.AbstractNamedAFPObject; + +/** + * A base container of prepared structured AFP objects + */ +public abstract class AbstractGraphicsDrawingOrderContainer extends AbstractNamedAFPObject +implements StructuredData, Completable, Startable { + + /** list of objects contained within this container */ + protected List/*<StructuredDataObject>*/ objects + = new java.util.ArrayList/*<StructuredDataObject>*/(); + + /** object is complete */ + private boolean complete = false; + + /** object has started */ + private boolean started = false; + + /** + * Default constructor + */ + protected AbstractGraphicsDrawingOrderContainer() { + } + + /** + * Named constructor + * + * @param name the name of the container + */ + protected AbstractGraphicsDrawingOrderContainer(String name) { + super(name); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + setStarted(true); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + writeObjects(objects, os); + } + + /** + * Adds a given graphics object to this container + * + * @param object the structured data object + */ + public void addObject(StructuredData object) { + objects.add(object); + } + + /** + * Adds all the contents of a given graphics container to this container + * + * @param graphicsContainer a graphics container + */ + public void addAll(AbstractGraphicsDrawingOrderContainer graphicsContainer) { + Collection/*<StructuredDataObject>*/ objects = graphicsContainer.getObjects(); + objects.addAll(objects); + } + + /** + * Returns all the objects in this container + * + * @return all the objects in this container + */ + private Collection getObjects() { + return this.objects; + } + + /** + * Removes the last drawing order from this container and returns it + * + * @return the last drawing order from this container or null if empty + */ + public StructuredData removeLast() { + int lastIndex = objects.size() - 1; + StructuredData object = null; + if (lastIndex > -1) { + object = (StructuredData)objects.get(lastIndex); + objects.remove(lastIndex); + } + return object; + } + + /** + * Returns the current data length + * + * @return the current data length of this container including + * all enclosed objects (and their containers) + */ + public int getDataLength() { + int dataLen = 0; + Iterator it = objects.iterator(); + while (it.hasNext()) { + dataLen += ((StructuredData)it.next()).getDataLength(); + } + return dataLen; + } + + /** {@inheritDoc} */ + public void setComplete(boolean complete) { + Iterator it = objects.iterator(); + while (it.hasNext()) { + Object object = it.next(); + if (object instanceof Completable) { + ((Completable)object).setComplete(true); + } + } + this.complete = true; + } + + /** {@inheritDoc} */ + public boolean isComplete() { + return this.complete; + } + + /** {@inheritDoc} */ + public boolean isStarted() { + return this.started; + } + + /** {@inheritDoc} */ + public void setStarted(boolean started) { + this.started = started; + } +} diff --git a/src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java b/src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java new file mode 100644 index 000000000..fc66fa8cd --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsAreaBegin.java @@ -0,0 +1,69 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * The beginning of a filled region (graphics area). + */ +public class GraphicsAreaBegin extends AbstractGraphicsDrawingOrder { + + private static final int RES1 = 1; + private static final int BOUNDARY = 2; + private static final int NO_BOUNDARY = 0; + + /** draw boundary lines around this area */ + private boolean drawBoundary = false; + + /** + * Sets whether boundary lines are drawn + * + * @param drawBoundaryLines whether boundary lines are drawn + */ + public void setDrawBoundaryLines(boolean drawBoundaryLines) { + this.drawBoundary = drawBoundaryLines; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + getOrderCode(), // GBAR order code + (byte)(RES1 + (drawBoundary ? BOUNDARY : NO_BOUNDARY)) + }; + os.write(data); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsAreaBegin{drawBoundary=" + drawBoundary + "}"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x68; + } +} diff --git a/src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java b/src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java new file mode 100644 index 000000000..12f14bfa4 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsAreaEnd.java @@ -0,0 +1,53 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * The end of a filled region (graphics area). + */ +public class GraphicsAreaEnd extends AbstractGraphicsDrawingOrder { + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + getOrderCode(), // GEAR order code + 0x00, // LENGTH + }; + os.write(data); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsAreaEnd"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x60; + } +} diff --git a/src/java/org/apache/fop/afp/goca/GraphicsBox.java b/src/java/org/apache/fop/afp/goca/GraphicsBox.java new file mode 100644 index 000000000..945697ec2 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsBox.java @@ -0,0 +1,63 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * A GOCA graphics rectangular box + */ +public final class GraphicsBox extends AbstractGraphicsCoord { + + /** + * Constructor + * + * @param coords the x/y coordinates for this object + */ + public GraphicsBox(int[] coords) { + super(coords); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 12; + } + + /** {@inheritDoc} */ + int getCoordinateDataStartIndex() { + return 4; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return (byte)0xC0; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = (byte)0x20; // CONTROL draw control flags + data[3] = 0x00; // reserved + + os.write(data); + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java b/src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java new file mode 100644 index 000000000..8a92db296 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsChainedSegment.java @@ -0,0 +1,112 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * A GOCA graphics segment + */ +public final class GraphicsChainedSegment extends AbstractGraphicsDrawingOrderContainer { + + /** The maximum segment data length */ + protected static final int MAX_DATA_LEN = 8192; + + private byte[] predecessorNameBytes; + + /** + * Main constructor + * + * @param name + * the name of this graphics segment + */ + public GraphicsChainedSegment(String name) { + super(name); + } + + /** + * Constructor + * + * @param name + * the name of this graphics segment + * @param predecessorNameBytes + * the name of the predecessor in this chain + */ + public GraphicsChainedSegment(String name, byte[] predecessorNameBytes) { + super(name); + this.predecessorNameBytes = predecessorNameBytes; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 14 + super.getDataLength(); + } + + private static final byte APPEND_NEW_SEGMENT = 0; +// private static final byte PROLOG = 4; +// private static final byte APPEND_TO_EXISING = 48; + + private static final int NAME_LENGTH = 4; + + /** {@inheritDoc} */ + protected int getNameLength() { + return NAME_LENGTH; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x70; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[14]; + data[0] = getOrderCode(); // BEGIN_SEGMENT + data[1] = 0x0C; // Length of following parameters + + // segment name + byte[] nameBytes = getNameBytes(); + System.arraycopy(nameBytes, 0, data, 2, NAME_LENGTH); + + data[6] = 0x00; // FLAG1 (ignored) + data[7] = APPEND_NEW_SEGMENT; + + int dataLength = super.getDataLength(); + byte[] len = BinaryUtils.convert(dataLength, 2); + data[8] = len[0]; // SEGL + data[9] = len[1]; + + // P/S NAME (predecessor name) + if (predecessorNameBytes != null) { + System.arraycopy(predecessorNameBytes, 0, data, 10, NAME_LENGTH); + } + os.write(data); + + writeObjects(objects, os); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsChainedSegment(name=" + super.getName() + ")"; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java b/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java new file mode 100644 index 000000000..70039d167 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsCharacterString.java @@ -0,0 +1,114 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.fop.afp.AFPConstants; + +/** + * A GOCA graphics string + */ +public class GraphicsCharacterString extends AbstractGraphicsCoord { + + /** Up to 255 bytes of character data */ + protected static final int MAX_STR_LEN = 255; + + /** the string to draw */ + protected final String str; + + /** + * Constructor (absolute positioning) + * + * @param str the character string + * @param x the x coordinate + * @param y the y coordinate + */ + public GraphicsCharacterString(String str, int x, int y) { + super(x, y); + this.str = truncate(str); + } + + /** + * Constructor (relative positioning) + * + * @param str the character string + * @param x the x coordinate + * @param y the y coordinate + */ + public GraphicsCharacterString(String str) { + super(null); + this.str = truncate(str); + } + + /** {@inheritDoc} */ + byte getOrderCode() { + if (isRelative()) { + return (byte)0x83; + } else { + return (byte)0xC3; + } + } + + /** {@inheritDoc} */ + public int getDataLength() { + return super.getDataLength() + str.length(); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + byte[] strData = getStringAsBytes(); + System.arraycopy(strData, 0, data, 6, strData.length); + os.write(data); + } + + /** + * Truncates the string as necessary + * + * @param str a character string + * @return a possibly truncated string + */ + private String truncate(String str) { + if (str.length() > MAX_STR_LEN) { + str = str.substring(0, MAX_STR_LEN); + log.warn("truncated character string, longer than " + MAX_STR_LEN + " chars"); + } + return str; + } + + /** + * Returns the text string as an encoded byte array + * + * @return the text string as an encoded byte array + */ + private byte[] getStringAsBytes() throws UnsupportedEncodingException { + return str.getBytes(AFPConstants.EBCIDIC_ENCODING); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsCharacterString{" + + (coords != null ? "x=" + coords[0] + ", y=" + coords[1] : "") + + "str='" + str + "'" + "}"; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsData.java b/src/java/org/apache/fop/afp/goca/GraphicsData.java new file mode 100644 index 000000000..89be8dd94 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsData.java @@ -0,0 +1,126 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.StructuredData; +import org.apache.fop.afp.util.BinaryUtils; +import org.apache.fop.afp.util.StringUtils; + +/** + * A GOCA graphics data + */ +public final class GraphicsData extends AbstractGraphicsDrawingOrderContainer { + + /** the maximum graphics data length */ + public static final int MAX_DATA_LEN = 32767; + + /** the graphics segment */ + private GraphicsChainedSegment currentSegment = null; + + /** + * Main constructor + */ + public GraphicsData() { + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 8 + super.getDataLength(); + } + + /** + * Returns a new segment name + * + * @return a new segment name + */ + public String createSegmentName() { + return StringUtils.lpad(String.valueOf( + (super.objects != null ? super.objects.size() : 0) + 1), + '0', 4); + } + + /** + * Creates a new graphics segment + * + * @return a newly created graphics segment + */ + public GraphicsChainedSegment newSegment() { + String segmentName = createSegmentName(); + if (currentSegment == null) { + currentSegment = new GraphicsChainedSegment(segmentName); + } else { + currentSegment.setComplete(true); + currentSegment = new GraphicsChainedSegment(segmentName, currentSegment.getNameBytes()); + } + super.addObject(currentSegment); + return currentSegment; + } + + /** {@inheritDoc} */ + public void addObject(StructuredData object) { + if (currentSegment == null + || (currentSegment.getDataLength() + object.getDataLength()) + >= GraphicsChainedSegment.MAX_DATA_LEN) { + newSegment(); + } + currentSegment.addObject(object); + } + + /** + * Removes the current segment from this graphics data + * + * @return the current segment from this graphics data + */ + public StructuredData removeCurrentSegment() { + this.currentSegment = null; + return super.removeLast(); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[9]; + copySF(data, SF_CLASS, Type.DATA, Category.GRAPHICS); + int dataLength = getDataLength(); + byte[] len = BinaryUtils.convert(dataLength, 2); + data[1] = len[0]; // Length byte 1 + data[2] = len[1]; // Length byte 2 + os.write(data); + + writeObjects(objects, os); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsData"; + } + + /** + * Adds the given segment to this graphics data + * + * @param segment a graphics chained segment + */ + public void addSegment(GraphicsChainedSegment segment) { + currentSegment = segment; + super.addObject(currentSegment); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsFillet.java b/src/java/org/apache/fop/afp/goca/GraphicsFillet.java new file mode 100644 index 000000000..294be6d9b --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsFillet.java @@ -0,0 +1,46 @@ +/* + * 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.afp.goca; + +/** + * A GOCA graphics curved tangential line to a specified set of + * straight lines drawn from the given position or current position + */ +public final class GraphicsFillet extends AbstractGraphicsCoord { + + /** + * Constructor + * + * @param coords the x/y coordinates for this object + */ + public GraphicsFillet(int[] coords, boolean relative) { + super(coords, relative); + } + + /** {@inheritDoc} */ + byte getOrderCode() { + if (isRelative()) { + return (byte)0x85; + } else { + return (byte)0xC5; + } + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsFullArc.java b/src/java/org/apache/fop/afp/goca/GraphicsFullArc.java new file mode 100644 index 000000000..a4b6916ae --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsFullArc.java @@ -0,0 +1,85 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * A GOCA graphics arc (circle/ellipse) + */ +public class GraphicsFullArc extends AbstractGraphicsCoord { + + /** the integer portion of the multiplier */ + private final int mh; + + /** the fractional portion of the multiplier */ + private final int mhr; + + /** + * Constructor + * + * @param x the x coordinate of the center of the circle/ellipse + * @param y the y coordinate of the center of the circle/ellipse + * @param mh the integer portion of the multiplier + * @param mhr the fractional portion of the multiplier + */ + public GraphicsFullArc(int x, int y, int mh, int mhr) { + super(x, y); + this.mh = mh; + this.mhr = mhr; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 8; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return (byte)0xC7; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + + // integer portion of multiplier + data[6] = BinaryUtils.convert(mh, 1)[0]; + + // fractional portion of multiplier + data[7] = BinaryUtils.convert(mhr, 1)[0]; + + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsFullArc{" + + ", centerx=" + coords[0] + + ", centery=" + coords[1] + + ", mh=" + mh + + ", mhr=" + mhr + + "}"; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsImage.java b/src/java/org/apache/fop/afp/goca/GraphicsImage.java new file mode 100644 index 000000000..3b1dafeea --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsImage.java @@ -0,0 +1,120 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * A GOCA Image + */ +public class GraphicsImage extends AbstractGraphicsDrawingOrder { + + /** the maximum image data length */ + public static final short MAX_DATA_LEN = 255; + + /** x coordinate */ + private final int x; + + /** y coordinate */ + private final int y; + + /** width */ + private final int width; + + /** height */ + private final int height; + + /** image data */ + private final byte[] imageData; + + /** + * Main constructor + * + * @param x the x coordinate of the image + * @param y the y coordinate of the image + * @param width the image width + * @param height the image height + * @param imageData the image data + */ + public GraphicsImage(int x, int y, int width, int height, byte[] imageData) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.imageData = imageData; + } + + /** {@inheritDoc} */ + public int getDataLength() { + //TODO: + return 0; + } + + byte getOrderCode() { + return (byte)0xD1; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] xcoord = BinaryUtils.convert(x, 2); + byte[] ycoord = BinaryUtils.convert(y, 2); + byte[] w = BinaryUtils.convert(width, 2); + byte[] h = BinaryUtils.convert(height, 2); + byte[] startData = new byte[] { + getOrderCode(), // GBIMG order code + (byte) 0x0A, // LENGTH + xcoord[0], + xcoord[1], + ycoord[0], + ycoord[1], + 0x00, // FORMAT + 0x00, // RES + w[0], // WIDTH + w[1], // + h[0], // HEIGHT + h[1] // + }; + os.write(startData); + + byte[] dataHeader = new byte[] { + (byte) 0x92 // GIMD + }; + final int lengthOffset = 1; + writeChunksToStream(imageData, dataHeader, lengthOffset, MAX_DATA_LEN, os); + + byte[] endData = new byte[] { + (byte) 0x93, // GEIMG order code + 0x00 // LENGTH + }; + os.write(endData); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsImage{x=" + x + + ", y=" + y + + ", width=" + width + + ", height=" + height + + "}"; + } +} diff --git a/src/java/org/apache/fop/afp/goca/GraphicsLine.java b/src/java/org/apache/fop/afp/goca/GraphicsLine.java new file mode 100644 index 000000000..17bd43ce0 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsLine.java @@ -0,0 +1,56 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * A GOCA graphics straight line drawn from the + * given absolute position + */ +public class GraphicsLine extends AbstractGraphicsCoord { + + /** + * Constructor + * + * @param coords the x/y coordinates for this object + * + * @param relative is this a relative drawing order + */ + public GraphicsLine(int[] coords, boolean relative) { + super(coords, relative); + } + + /** {@inheritDoc} */ + byte getOrderCode() { + if (isRelative()) { + return (byte)0x81; + } else { + return (byte)0xC1; + } + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + os.write(data); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java b/src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java new file mode 100644 index 000000000..693cf21a9 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetArcParameters.java @@ -0,0 +1,51 @@ +/* + * 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.afp.goca; + +/** + * Sets the arc parameters for a GOCA graphics arc (circle/ellipse) + */ +public class GraphicsSetArcParameters extends AbstractGraphicsCoord { + + /** + * Constructor + * + * @param xmaj x coordinate of the major axis point + * @param ymin y coordinate of the minor axis point + * @param xmin x coordinate of the minor axis point + * @param ymaj y coordinate of the major axis point + */ + public GraphicsSetArcParameters(int xmaj, int ymin, int xmin, int ymaj) { + super(xmaj, ymin, xmin, ymaj); + } + + /** {@inheritDoc} */ + protected byte getOrderCode() { + return 0x22; + } + + /** {@inheritDoc} */ + public String toString() { + return getName() + "{xmaj=" + coords[0] + + ",ymin=" + coords[1] + + ",xmin=" + coords[2] + + ",ymaj=" + coords[3] + "}"; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java b/src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java new file mode 100644 index 000000000..b3d1158fe --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetCharacterSet.java @@ -0,0 +1,66 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * Sets the current character set (font) to be used for following graphics strings + */ +public class GraphicsSetCharacterSet extends AbstractGraphicsDrawingOrder { + + /** font character set reference */ + private final int fontReference; + + /** + * @param fontReference character set font reference + */ + public GraphicsSetCharacterSet(int fontReference) { + this.fontReference = fontReference; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + getOrderCode(), // GSCS order code + BinaryUtils.convert(fontReference)[0] + }; + os.write(data); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetCharacterSet(" + fontReference + ")"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x38; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java b/src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java new file mode 100644 index 000000000..675c2f034 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetCurrentPosition.java @@ -0,0 +1,40 @@ +/* + * 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.afp.goca; + +/** + * Sets the current painting position of the graphics object + */ +public class GraphicsSetCurrentPosition extends AbstractGraphicsCoord { + + /** + * Constructor + * + * @param coords the x/y coordinates for this object + */ + public GraphicsSetCurrentPosition(int[] coords) { + super(coords); + } + + /** {@inheritDoc} */ + protected byte getOrderCode() { + return (byte)0x21; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java b/src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java new file mode 100644 index 000000000..b6512f57c --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetLineType.java @@ -0,0 +1,97 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the value of the current line type attribute when stroking GOCA shapes (structured fields) + */ +public class GraphicsSetLineType extends AbstractGraphicsDrawingOrder { + + /** the default line type */ + public static final byte DEFAULT = 0x00; // normally SOLID + + /** the default line type */ + public static final byte DOTTED = 0x01; + + /** short dashed line type */ + public static final byte SHORT_DASHED = 0x02; + + /** dashed dotted line type */ + public static final byte DASH_DOT = 0x03; + + /** double dotted line type */ + public static final byte DOUBLE_DOTTED = 0x04; + + /** long dashed line type */ + public static final byte LONG_DASHED = 0x05; + + /** dash double dotted line type */ + public static final byte DASH_DOUBLE_DOTTED = 0x06; + + /** solid line type */ + public static final byte SOLID = 0x07; + + /** invisible line type */ + public static final byte INVISIBLE = 0x08; + + /** line type */ + private byte type = DEFAULT; + + /** + * Main constructor + * + * @param type line type + */ + public GraphicsSetLineType(byte type) { + this.type = type; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + getOrderCode(), // GSLW order code + type // line type + }; + os.write(data); + } + + private static final String[] TYPES = { + "default (solid)", "dotted", "short dashed", "dash dotted", "double dotted", + "long dashed", "dash double dotted", "solid", "invisible" + }; + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetLineType{type=" + TYPES[type] + "}"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x18; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java b/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java new file mode 100644 index 000000000..96eac0677 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetLineWidth.java @@ -0,0 +1,65 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the line width to use when stroking GOCA shapes (structured fields) + */ +public class GraphicsSetLineWidth extends AbstractGraphicsDrawingOrder { + + /** line width multiplier */ + private int multiplier = 1; + + /** + * Main constructor + * + * @param multiplier the line width multiplier + */ + public GraphicsSetLineWidth(int multiplier) { + this.multiplier = multiplier; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + getOrderCode(), // GSLW order code + (byte)multiplier // MH (line-width) + }; + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetLineWidth{multiplier=" + multiplier + "}"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x19; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetMix.java b/src/java/org/apache/fop/afp/goca/GraphicsSetMix.java new file mode 100644 index 000000000..dfb5ae0d2 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetMix.java @@ -0,0 +1,69 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the foreground mix mode. + */ +public class GraphicsSetMix extends AbstractGraphicsDrawingOrder { + + public static final byte MODE_DEFAULT = 0x00; + public static final byte MODE_OVERPAINT = 0x02; + + /** the mix mode value */ + private final byte mode; + + /** + * Main constructor + * + * @param mode the mix mode value + */ + public GraphicsSetMix(byte mode) { + this.mode = mode; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + 0x0C, // GSMX order code + mode // MODE (mix mode value) + }; + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetMix{mode=" + mode + "}"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x0C; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + +} diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java b/src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java new file mode 100644 index 000000000..3d6cf7cd6 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetPatternSymbol.java @@ -0,0 +1,117 @@ +/* + * 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.afp.goca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the pattern symbol to use when filling following GOCA structured fields + */ +public class GraphicsSetPatternSymbol extends AbstractGraphicsDrawingOrder { + + /** dotted density 1 */ + public static final byte DOTTED_DENSITY_1 = 0x01; + + /** dotted density 2 */ + public static final byte DOTTED_DENSITY_2 = 0x02; + + /** dotted density 3 */ + public static final byte DOTTED_DENSITY_3 = 0x03; + + /** dotted density 4 */ + public static final byte DOTTED_DENSITY_4 = 0x04; + + /** dotted density 5 */ + public static final byte DOTTED_DENSITY_5 = 0x05; + + /** dotted density 6 */ + public static final byte DOTTED_DENSITY_6 = 0x06; + + /** dotted density 7 */ + public static final byte DOTTED_DENSITY_7 = 0x07; + + /** dotted density 8 */ + public static final byte DOTTED_DENSITY_8 = 0x08; + + /** dotted density 9 */ + public static final byte VERTICAL_LINES = 0x09; + + /** horizontal lines */ + public static final byte HORIZONTAL_LINES = 0x0A; + + /** diagonal lines, bottom left to top right 1 */ + public static final byte DIAGONAL_LINES_BLTR_1 = 0x0B; + + /** diagonal lines, bottom left to top right 2 */ + public static final byte DIAGONAL_LINES_BLTR_2 = 0x0C; + + /** diagonal lines, top left to bottom right 1 */ + public static final byte DIAGONAL_LINES_TLBR_1 = 0x0D; + + /** diagonal lines, top left to bottom right 2 */ + public static final byte DIAGONAL_LINES_TLBR_2 = 0x0E; + + /** no fill */ + public static final byte NO_FILL = 0x0F; + + /** solid fill */ + public static final byte SOLID_FILL = 0x10; + + /** blank (same as no fill) */ + public static final byte BLANK = 0x40; // processed same as NO_FILL + + /** the graphics pattern symbol to use */ + private final byte pattern; + + /** + * Main constructor + * + * @param symb the pattern symbol to use + */ + public GraphicsSetPatternSymbol(byte pattern) { + this.pattern = pattern; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[] { + getOrderCode(), // GSPT order code + pattern + }; + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetPatternSymbol(fill=" + + (pattern == SOLID_FILL ? true : false) + ")"; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return 0x28; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java b/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java new file mode 100644 index 000000000..05a6ee5d1 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java @@ -0,0 +1,104 @@ +/* + * 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.afp.goca; + +import java.awt.Color; +import java.awt.color.ColorSpace; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Sets the current processing color for the following GOCA structured fields + */ +public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder { + + private final Color color; + + private final float[] colorComponents; + + /** + * Main constructor + * + * @param color the color to set + */ + public GraphicsSetProcessColor(Color color) { + this.color = color; + this.colorComponents = color.getColorComponents(null); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 12 + colorComponents.length; + } + + /** {@inheritDoc} */ + byte getOrderCode() { + return (byte)0xB2; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + + // COLSPCE + byte colspace; + int colSpaceType = color.getColorSpace().getType(); + if (colSpaceType == ColorSpace.TYPE_CMYK) { + colspace = 0x04; + } else if (colSpaceType == ColorSpace.TYPE_RGB) { + colspace = 0x01; + } else { + log.error("unsupported colorspace " + colSpaceType); + colspace = 0x01; + } + + // COLSIZE(S) + byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00}; + for (int i = 0; i < colorComponents.length; i++) { + colsizes[i] = (byte)8; + } + + int len = getDataLength(); + byte[] data = new byte[len]; + data[0] = getOrderCode(); // GSPCOL order code + data[1] = (byte)(len - 2); // LEN + data[2] = 0x00; // reserved; must be zero + data[3] = colspace; // COLSPCE + data[4] = 0x00; // reserved; must be zero + data[5] = 0x00; // reserved; must be zero + data[6] = 0x00; // reserved; must be zero + data[7] = 0x00; // reserved; must be zero + data[8] = colsizes[0]; // COLSIZE(S) + data[9] = colsizes[1]; + data[10] = colsizes[2]; + data[11] = colsizes[3]; + + // COLVALUE(S) + for (int i = 0; i < colorComponents.length; i++) { + data[i + 12] = (byte)(colorComponents[i] * 255); + } + + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsSetProcessColor(col=" + color + ")"; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/goca/package.html b/src/java/org/apache/fop/afp/goca/package.html new file mode 100644 index 000000000..539be8d13 --- /dev/null +++ b/src/java/org/apache/fop/afp/goca/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.fonts Package</TITLE> +<BODY> +<P>Contains a collection of AFP font related classes.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java b/src/java/org/apache/fop/afp/ioca/ImageCellPosition.java index c0b28904d..97489a9b1 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageCellPosition.java +++ b/src/java/org/apache/fop/afp/ioca/ImageCellPosition.java @@ -17,11 +17,13 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.ioca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.modca.AbstractAFPObject; +import org.apache.fop.afp.util.BinaryUtils; /** * The IM Image Cell Position structured field specifies the placement, @@ -29,38 +31,27 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ImageCellPosition extends AbstractAFPObject { - /** - * Offset of image cell in X direction - */ + /** offset of image cell in X direction */ private int xOffset = 0; - /** - * Offset of image cell in Y direction - */ + /** offset of image cell in Y direction */ private int yOffset = 0; - /** - * Size of image cell in X direction - */ - private byte[] xSize = new byte[] {(byte)0xFF, (byte)0xFF}; + /** size of image cell in X direction */ + private final byte[] xSize = new byte[] {(byte)0xFF, (byte)0xFF}; - /** - * Size of image cell in Y direction - */ - private byte[] ySize = new byte[] {(byte)0xFF, (byte)0xFF}; + /** size of image cell in Y direction */ + private final byte[] ySize = new byte[] {(byte)0xFF, (byte)0xFF}; - /** - * Size of fill rectangle in X direction - */ - private byte[] xFillSize = new byte[] {(byte)0xFF, (byte)0xFF}; + /** size of fill rectangle in X direction */ + private final byte[] xFillSize = new byte[] {(byte)0xFF, (byte)0xFF}; - /** - * Size of fill rectangle in Y direction - */ - private byte[] yFillSize = new byte[] {(byte)0xFF, (byte)0xFF}; + /** size of fill rectangle in Y direction */ + private final byte[] yFillSize = new byte[] {(byte)0xFF, (byte)0xFF}; /** - * Constructor for the ImageCellPosition + * Main Constructor + * * @param x The offset of image cell in X direction * @param y The offset of image cell in Y direction */ @@ -69,26 +60,14 @@ public class ImageCellPosition extends AbstractAFPObject { yOffset = y; } - /** - * Accessor method to write the AFP datastream for the Image Cell Position - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred - */ - public void writeDataStream(OutputStream os) throws IOException { + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[21]; + copySF(data, Type.POSITION, Category.IM_IMAGE); - data[0] = 0x5A; - - data[1] = 0x00; + data[1] = 0x00; // length data[2] = 0x14; - data[3] = (byte) 0xD3; - data[4] = (byte) 0xAC; - data[5] = (byte) 0x7B; - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - /** * Specifies the offset along the Xp direction, in image points, * of this image cell from the IM image object area origin. @@ -125,6 +104,7 @@ public class ImageCellPosition extends AbstractAFPObject { * of this image cell. A value of X'FFFF' indicates that the * default extent specified in bytes 28 and 29 of the Image * Input Descriptor (IID) is to be used. + * * @param xcSize The size to set. */ public void setXSize(int xcSize) { @@ -141,6 +121,7 @@ public class ImageCellPosition extends AbstractAFPObject { * be used as the fill rectangle X-extent. The fill rectangle is * filled in the X direction by repeating the image cell in the * X direction. The image cell can be truncated to fit the rectangle. + * * @param size The size to set. */ public void setXFillSize(int size) { @@ -154,6 +135,7 @@ public class ImageCellPosition extends AbstractAFPObject { * of this image cell. A value of X'FFFF' indicates that the * default extent specified in bytes 30 and 31 of the Image * Input Descriptor (IID) is to be used. + * * @param size The size to set. */ public void setYSize(int size) { @@ -170,6 +152,7 @@ public class ImageCellPosition extends AbstractAFPObject { * be used as the fill rectangle Y-extent. The fill rectangle is * filled in the Y direction by repeating the image cell in the * Y direction. The image cell can be truncated to fit the rectangle. + * * @param size The size to set. */ public void setYFillSize(int size) { diff --git a/src/java/org/apache/fop/afp/ioca/ImageContent.java b/src/java/org/apache/fop/afp/ioca/ImageContent.java new file mode 100644 index 000000000..40e51578b --- /dev/null +++ b/src/java/org/apache/fop/afp/ioca/ImageContent.java @@ -0,0 +1,267 @@ +/* + * 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.afp.ioca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.modca.AbstractStructuredObject; + +/** + * An IOCA Image Content + */ +public class ImageContent extends AbstractStructuredObject { + + /** + * The CCITT T.4 Group 3 Coding Standard (G3 MH-Modified Huffman) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * one-dimensional compression. + */ + public static final byte COMPID_G3_MH = (byte)0x80; + + /** + * The CCITT T.4 Group 3 Coding Option (G3 MR-Modified READ) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * two-dimensional compression. + */ + public static final byte COMPID_G3_MR = (byte)0x81; + + /** + * The CCITT T.6 Group 4 Coding Standard (G4 MMR-Modified Modified READ) is a + * compression method standardized by the International Telegraph and + * Telephone Consultative Committee (CCITT) for facsimile. It enables + * two-dimensional compression. + */ + public static final byte COMPID_G3_MMR = (byte)0x82; + + /** the image size parameter */ + private ImageSizeParameter imageSizeParameter = null; + + /** the image encoding */ + private byte encoding = (byte)0x03; + + /** the image ide size */ + private byte size = 1; + + /** the image compression */ + private byte compression = (byte)0xC0; + + /** the image color model */ + private byte colorModel = (byte)0x01; + + /** the image data */ + private byte[] data; + + /** + * Main Constructor + */ + public ImageContent() { + } + + /** + * Sets the image size parameter + * + * @param imageSizeParameter the image size parameter. + */ + public void setImageSizeParameter(ImageSizeParameter imageSizeParameter) { + this.imageSizeParameter = imageSizeParameter; + } + + /** + * Sets the image encoding. + * + * @param enc The image encoding. + */ + public void setImageEncoding(byte enc) { + this.encoding = enc; + } + + /** + * Sets the image compression. + * + * @param comp The image compression. + */ + public void setImageCompression(byte comp) { + this.compression = comp; + } + + /** + * Sets the image IDE size. + * + * @param s The IDE size. + */ + public void setImageIDESize(byte s) { + this.size = s; + } + + /** + * Sets the image IDE color model. + * + * @param color the IDE color model. + */ + public void setImageIDEColorModel(byte color) { + this.colorModel = color; + } + + /** + * Set the image data (can be byte array or inputstream) + * + * @param imageData the image data + */ + public void setImageData(byte[] imageData) { + this.data = imageData; + } + + private static final int MAX_DATA_LEN = 65535; + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + if (imageSizeParameter != null) { + imageSizeParameter.writeToStream(os); + } + + // TODO convert to triplet/parameter class + os.write(getImageEncodingParameter()); + + os.write(getImageIDESizeParameter()); + + os.write(getIDEStructureParameter()); + + os.write(getExternalAlgorithmParameter()); + + final byte[] dataHeader = new byte[] { + (byte)0xFE, // ID + (byte)0x92, // ID + 0x00, // length + 0x00 // length + }; + final int lengthOffset = 2; + + // Image Data + if (data != null) { + writeChunksToStream(data, dataHeader, lengthOffset, MAX_DATA_LEN, os); + } + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + final byte[] startData = new byte[] { + (byte)0x91, // ID + 0x01, // Length + (byte)0xff, // Object Type = IOCA Image Object + }; + os.write(startData); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + final byte[] endData = new byte[] { + (byte)0x93, // ID + 0x00, // Length + }; + os.write(endData); + } + + /** + * Helper method to return the image encoding parameter. + * + * @return byte[] The data stream. + */ + private byte[] getImageEncodingParameter() { + final byte[] encodingData = new byte[] { + (byte)0x95, // ID + 0x02, // Length + encoding, + 0x01, // RECID + }; + return encodingData; + } + + /** + * Helper method to return the external algorithm parameter. + * + * @return byte[] The data stream. + */ + private byte[] getExternalAlgorithmParameter() { + if (encoding == (byte)0x83 && compression != 0) { + final byte[] extAlgData = new byte[] { + (byte)0x95, // ID + 0x00, // Length + 0x10, // ALGTYPE = Compression Algorithm + 0x00, // Reserved + (byte)0x83, // COMPRID = JPEG + 0x00, // Reserved + 0x00, // Reserved + 0x00, // Reserved + compression, // MARKER + 0x00, // Reserved + 0x00, // Reserved + 0x00, // Reserved + }; + extAlgData[1] = (byte)(extAlgData.length - 2); + return extAlgData; + } + return new byte[0]; + } + + /** + * Helper method to return the image encoding parameter. + * + * @return byte[] The data stream. + */ + private byte[] getImageIDESizeParameter() { + final byte[] ideSizeData = new byte[] { + (byte)0x96, // ID + 0x01, // Length + size, + }; + return ideSizeData; + } + + /** + * Helper method to return the external algorithm parameter. + * + * @return byte[] The data stream. + */ + private byte[] getIDEStructureParameter() { + if (colorModel != 0 && size == 24) { + final byte bits = (byte)(size / 3); + final byte[] ideStructData = new byte[] { + (byte)0x9B, // ID + 0x00, // Length + 0x00, // FLAGS + 0x00, // Reserved + colorModel, // COLOR MODEL + 0x00, // Reserved + 0x00, // Reserved + 0x00, // Reserved + bits, + bits, + bits, + }; + ideStructData[1] = (byte)(ideStructData.length - 2); + return ideStructData; + } + return new byte[0]; + } + +} diff --git a/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java b/src/java/org/apache/fop/afp/ioca/ImageInputDescriptor.java index bba416c88..af237a467 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageInputDescriptor.java +++ b/src/java/org/apache/fop/afp/ioca/ImageInputDescriptor.java @@ -17,11 +17,13 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.ioca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.modca.AbstractAFPObject; +import org.apache.fop.afp.util.BinaryUtils; /** * The IM Image Input Descriptor structured field contains the @@ -30,30 +32,17 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ImageInputDescriptor extends AbstractAFPObject { - /** - * The resolution of the raster image (default 240) - */ + /** the resolution of the raster image (default 240) */ private int resolution = 240; - - /** - * Accessor method to write the AFP datastream for the Image Input Descriptor - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred - */ - public void writeDataStream(OutputStream os) throws IOException { + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[45]; + copySF(data, Type.DESCRIPTOR, Category.IM_IMAGE); - data[0] = 0x5A; - data[1] = 0x00; + data[1] = 0x00; // length data[2] = 0x2C; - data[3] = (byte) 0xD3; - data[4] = (byte) 0xA6; - data[5] = (byte) 0x7B; - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; // Constant data. data[9] = 0x00; @@ -131,12 +120,12 @@ public class ImageInputDescriptor extends AbstractAFPObject { data[44] = (byte)0xFF; os.write(data); - } /** * Sets the resolution information for the raster image * the default value is a resolution of 240 dpi. + * * @param resolution The resolution value */ public void setResolution(int resolution) { diff --git a/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java b/src/java/org/apache/fop/afp/ioca/ImageOutputControl.java index 558a600a5..3d500b3fd 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageOutputControl.java +++ b/src/java/org/apache/fop/afp/ioca/ImageOutputControl.java @@ -17,11 +17,13 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.ioca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.modca.AbstractAFPObject; +import org.apache.fop.afp.util.BinaryUtils; /** * The IM Image Output Control structured field specifies the position and @@ -31,9 +33,7 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ImageOutputControl extends AbstractAFPObject { - /** - * The orientation of the image - */ + /** the orientation of the image */ private int orientation = 0; /** @@ -48,9 +48,7 @@ public class ImageOutputControl extends AbstractAFPObject { */ private int yCoord = 0; - /** - * Map an image point to a single presentation device - */ + /** map an image point to a single presentation device */ private boolean singlePoint = true; /** @@ -67,18 +65,12 @@ public class ImageOutputControl extends AbstractAFPObject { * The Y-axis offset. */ public ImageOutputControl(int x, int y) { - xCoord = x; yCoord = y; - } - /** - * Accessor method to write the AFP datastream for the Image Output Control - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occured - */ - public void writeDataStream(OutputStream os) throws IOException { + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[33]; @@ -170,7 +162,6 @@ public class ImageOutputControl extends AbstractAFPObject { data[32] = (byte) 0xFF; os.write(data); - } /** diff --git a/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java b/src/java/org/apache/fop/afp/ioca/ImageRasterData.java index ca440a859..50f44d39d 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageRasterData.java +++ b/src/java/org/apache/fop/afp/ioca/ImageRasterData.java @@ -17,11 +17,13 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.ioca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.modca.AbstractAFPObject; +import org.apache.fop.afp.util.BinaryUtils; /** * Contains the image points that define the IM image raster pattern. @@ -45,43 +47,28 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class ImageRasterData extends AbstractAFPObject { - /** - * The image raster data - */ - private byte[] rasterData; + /** the image raster data */ + private final byte[] rasterData; /** * Constructor for the image raster data object + * * @param data The raster image data */ public ImageRasterData(byte[] data) { this.rasterData = data; } - /** - * Accessor method to write the AFP datastream for the Image Raster Data - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred - */ - public void writeDataStream(OutputStream os) throws IOException { - + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[9]; - - data[0] = 0x5A; - + copySF(data, Type.DATA, Category.IM_IMAGE); // The size of the structured field - byte[] x = BinaryUtils.convert(rasterData.length + 8, 2); - data[1] = x[0]; - data[2] = x[1]; - - data[3] = (byte) 0xD3; - data[4] = (byte) 0xEE; - data[5] = (byte) 0x7B; - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - + byte[] len = BinaryUtils.convert(rasterData.length + 8, 2); + data[1] = len[0]; + data[2] = len[1]; os.write(data); + os.write(rasterData); } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ImageRasterPattern.java b/src/java/org/apache/fop/afp/ioca/ImageRasterPattern.java index 373e50631..789eeb950 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageRasterPattern.java +++ b/src/java/org/apache/fop/afp/ioca/ImageRasterPattern.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.ioca; /** * Raster data is a grid of cells covering an area of interest. diff --git a/src/java/org/apache/fop/afp/ioca/ImageSegment.java b/src/java/org/apache/fop/afp/ioca/ImageSegment.java new file mode 100644 index 000000000..9fb544719 --- /dev/null +++ b/src/java/org/apache/fop/afp/ioca/ImageSegment.java @@ -0,0 +1,161 @@ +/* + * 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.afp.ioca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.modca.AbstractNamedAFPObject; + +/** + * An Image Segment is represented by a set of self-defining fields, fields + * that describe their own contents. It starts with a Begin Segment, and + * ends with an End Segment. + * + * Between the Begin Segment and End Segment is the image information to + * be processed, called the Image Content. + * + * Only one Image Content can exist within a single IOCA Image Segment. + */ +public class ImageSegment extends AbstractNamedAFPObject { + + /** + * The ImageContent for the image segment + */ + private ImageContent imageContent = null; + + private final Factory factory; + + /** + * Constructor for the image segment with the specified name, + * the name must be a fixed length of eight characters. + * @param factory the object factory + * + * @param name the name of the image. + */ + public ImageSegment(Factory factory, String name) { + super(name); + this.factory = factory; + } + + private ImageContent getImageContent() { + if (imageContent == null) { + this.imageContent = factory.createImageContent(); + } + return imageContent; + } + + /** + * Sets the image size parameters resolution, hsize and vsize. + * + * @param hsize The horizontal size of the image. + * @param vsize The vertical size of the image. + * @param hresol The horizontal resolution of the image. + * @param vresol The vertical resolution of the image. + */ + public void setImageSize(int hsize, int vsize, int hresol, int vresol) { + ImageSizeParameter imageSizeParameter + = factory.createImageSizeParameter(hsize, vsize, hresol, vresol); + getImageContent().setImageSizeParameter(imageSizeParameter); + } + + /** + * Sets the image encoding. + * + * @param encoding The image encoding. + */ + public void setEncoding(byte encoding) { + getImageContent().setImageEncoding(encoding); + } + + /** + * Sets the image compression. + * + * @param compression The image compression. + */ + public void setCompression(byte compression) { + getImageContent().setImageCompression(compression); + } + + /** + * Sets the image IDE size. + * + * @param size The IDE size. + */ + public void setIDESize(byte size) { + getImageContent().setImageIDESize(size); + } + + /** + * Sets the image IDE color model. + * + * @param colorModel the IDE color model. + */ + public void setIDEColorModel(byte colorModel) { + getImageContent().setImageIDEColorModel(colorModel); + } + + /** + * Set the data image data. + * + * @param data the image data + */ + public void setData(byte[] imageData) { + getImageContent().setImageData(imageData); + } + + /** {@inheritDoc} */ + public void writeContent(OutputStream os) throws IOException { + if (imageContent != null) { + imageContent.writeToStream(os); + } + } + + private static final int NAME_LENGTH = 4; + + /** {@inheritDoc} */ + protected int getNameLength() { + return NAME_LENGTH; + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] nameBytes = getNameBytes(); + byte[] data = new byte[] { + 0x70, // ID + 0x04, // Length + nameBytes[0], // Name byte 1 + nameBytes[1], // Name byte 2 + nameBytes[2], // Name byte 3 + nameBytes[3], // Name byte 4 + }; + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[] { + 0x71, // ID + 0x00, // Length + }; + os.write(data); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java b/src/java/org/apache/fop/afp/ioca/ImageSizeParameter.java index 7dd210a1e..38e7d9e56 100644 --- a/src/java/org/apache/fop/render/afp/modca/ImageSizeParameter.java +++ b/src/java/org/apache/fop/afp/ioca/ImageSizeParameter.java @@ -17,43 +17,42 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.ioca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.modca.AbstractAFPObject; +import org.apache.fop.afp.util.BinaryUtils; /** * Describes the measurement characteristics of the image when it is created. */ public class ImageSizeParameter extends AbstractAFPObject { - private int hRes = 0; - private int vRes = 0; private int hSize = 0; private int vSize = 0; + private int hRes = 0; + private int vRes = 0; /** * Constructor for a ImageSizeParameter for the specified * resolution, hsize and vsize. - * @param hresol The horizontal resolution of the image. - * @param vresol The vertical resolution of the image. + * * @param hsize The horizontal size of the image. * @param vsize The vertical size of the image. + * @param hresol The horizontal resolution of the image. + * @param vresol The vertical resolution of the image. */ - public ImageSizeParameter(int hresol, int vresol, int hsize, int vsize) { - this.hRes = hresol; - this.vRes = vresol; + public ImageSizeParameter(int hsize, int vsize, int hresol, int vresol) { this.hSize = hsize; this.vSize = vsize; + this.hRes = hresol; + this.vRes = vresol; } - /** - * Accessor method to write the AFP datastream for the Image Size Parameter - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occured - */ - public void writeDataStream(OutputStream os) throws IOException { + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[] { (byte)0x94, // ID = Image Size Parameter 0x09, // Length diff --git a/src/java/org/apache/fop/afp/ioca/package.html b/src/java/org/apache/fop/afp/ioca/package.html new file mode 100644 index 000000000..34e0bc19d --- /dev/null +++ b/src/java/org/apache/fop/afp/ioca/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.ioca Package</TITLE> +<BODY> +<P>Contains a collection of AFP Image Object Content Architecture (IOCA) structured objects.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java new file mode 100644 index 000000000..f1b76c447 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractAFPObject.java @@ -0,0 +1,321 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collection; +import java.util.Iterator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.Streamable; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * This is the base class for all data stream objects. Page objects are + * responsible for building and generating the binary datastream in an + * AFP format. + */ +public abstract class AbstractAFPObject implements Streamable { + + /** Static logging instance */ + protected static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp.modca"); + + /** the structured field class id */ + protected static final byte SF_CLASS = (byte)0xD3; + + private static final byte[] SF_HEADER = new byte[] { + 0x5A, // Structured field identifier + 0x00, // Length byte 1 + 0x10, // Length byte 2 + SF_CLASS, // Structured field id byte 1 + (byte) 0x00, // Structured field id byte 2 + (byte) 0x00, // Structured field id byte 3 + 0x00, // Flags + 0x00, // Reserved + 0x00, // Reserved + }; + + /** + * Copies the template structured field data array to the given byte array + * + * @param data the structured field data byte array + * @param type the type code + * @param category the category code + */ + protected void copySF(byte[] data, byte type, byte category) { + copySF(data, SF_CLASS, type, category); + } + + /** + * Copies the template structured field data array to the given byte array + * + * @param data the structured field data byte array + * @param clazz the class code + * @param type the type code + * @param category the category code + */ + protected static void copySF(byte[] data, byte clazz, byte type, byte category) { + System.arraycopy(SF_HEADER, 0, data, 0, SF_HEADER.length); + data[3] = clazz; + data[4] = type; + data[5] = category; + } + + /** + * Writes a collection of Streamable to the AFP Datastream. + * + * @param objects a list of AFPObjects + * @param os The stream to write to + * @throws java.io.IOException an I/O exception of some sort has occurred. + */ + protected void writeObjects(Collection/*<Streamable>*/ objects, OutputStream os) + throws IOException { + if (objects != null && objects.size() > 0) { + Iterator it = objects.iterator(); + while (it.hasNext()) { + Object object = it.next(); + if (object instanceof Streamable) { + ((Streamable)object).writeToStream(os); + it.remove(); // once written, immediately remove the object + } + } + } + } + + /** + * Reads data chunks from an InputStream + * and then formats them with a structured header to a given OutputStream + * + * @param dataHeader the header data + * @param lengthOffset offset of length field in data chunk + * @param maxChunkLength the maximum chunk length + * @param inputStream the InputStream to read from + * @param outputStream the OutputStream to write to + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + protected static void copyChunks(byte[] dataHeader, int lengthOffset, + int maxChunkLength, InputStream inputStream, OutputStream outputStream) + throws IOException { + int headerLen = dataHeader.length - lengthOffset; + // length field is just before data so do not include in data length + if (headerLen == 2) { + headerLen = 0; + } + byte[] data = new byte[maxChunkLength]; + int numBytesRead = 0; + while ((numBytesRead = inputStream.read(data, 0, maxChunkLength)) > 0) { + byte[] len = BinaryUtils.convert(headerLen + numBytesRead, 2); + dataHeader[lengthOffset] = len[0]; // Length byte 1 + dataHeader[lengthOffset + 1] = len[1]; // Length byte 2 + outputStream.write(dataHeader); + outputStream.write(data, 0, numBytesRead); + } + } + + /** + * Writes data chunks to a given outputstream + * + * @param data the data byte array + * @param dataHeader the header data + * @param lengthOffset offset of length field in data chunk + * @param maxChunkLength the maximum chunk length + * @param os the outputstream to write to + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + protected static void writeChunksToStream(byte[] data, byte[] dataHeader, + int lengthOffset, int maxChunkLength, OutputStream os) throws IOException { + int dataLength = data.length; + int numFullChunks = dataLength / maxChunkLength; + int lastChunkLength = dataLength % maxChunkLength; + + int headerLen = dataHeader.length - lengthOffset; + // length field is just before data so do not include in data length + if (headerLen == 2) { + headerLen = 0; + } + + byte[] len; + int off = 0; + if (numFullChunks > 0) { + // write out full data chunks + len = BinaryUtils.convert(headerLen + maxChunkLength, 2); + dataHeader[lengthOffset] = len[0]; // Length byte 1 + dataHeader[lengthOffset + 1] = len[1]; // Length byte 2 + for (int i = 0; i < numFullChunks; i++, off += maxChunkLength) { + os.write(dataHeader); + os.write(data, off, maxChunkLength); + } + } + + if (lastChunkLength > 0) { + // write last data chunk + len = BinaryUtils.convert(headerLen + lastChunkLength, 2); + dataHeader[lengthOffset] = len[0]; // Length byte 1 + dataHeader[lengthOffset + 1] = len[1]; // Length byte 2 + os.write(dataHeader); + os.write(data, off, lastChunkLength); + } + } + + /** structured field type codes */ + public interface Type { + + /** Attribute */ + byte ATTRIBUTE = (byte)0x0A; + + /** Copy Count */ + byte COPY_COUNT = (byte)0xA2; + + /** Descriptor */ + byte DESCRIPTOR = (byte)0xA6; + + /** Control */ + byte CONTROL = (byte)0xA7; + + /** Begin */ + byte BEGIN = (byte)0xA8; + + /** End */ + byte END = (byte)0xA9; + + /** Map */ + byte MAP = (byte)0xAB; + + /** Position */ + byte POSITION = (byte)0xAC; + + /** Process */ + byte PROCESS = (byte)0xAD; + + /** Include */ + byte INCLUDE = (byte)0xAF; + + /** Table */ + byte TABLE = (byte)0xB0; + + /** Migration */ + byte MIGRATION = (byte)0xB1; + + /** Variable */ + byte VARIABLE = (byte)0xB2; + + /** Link */ + byte LINK = (byte)0xB4; + + /** Data */ + byte DATA = (byte)0xEE; + } + + /** structured field category codes */ + public interface Category { + + /** Page Segment */ + byte PAGE_SEGMENT = (byte)0x5F; + + /** Object Area */ + byte OBJECT_AREA = (byte)0x6B; + + /** Color Attribute Table */ + byte COLOR_ATTRIBUTE_TABLE = (byte)0x77; + + /** IM Image */ + byte IM_IMAGE = (byte)0x7B; + + /** Medium */ + byte MEDIUM = (byte)0x88; + + /** Coded Font */ + byte CODED_FONT = (byte)0x8A; + + /** Process Element */ + byte PROCESS_ELEMENT = (byte)0x90; + + /** Object Container */ + byte OBJECT_CONTAINER = (byte)0x92; + + /** Presentation Text */ + byte PRESENTATION_TEXT = (byte)0x9B; + + /** Index */ + byte INDEX = (byte)0xA7; + + /** Document */ + byte DOCUMENT = (byte)0xA8; + + /** Page Group */ + byte PAGE_GROUP = (byte)0xAD; + + /** Page */ + byte PAGE = (byte)0xAF; + + /** Graphics */ + byte GRAPHICS = (byte)0xBB; + + /** Data Resource */ + byte DATA_RESOURCE = (byte)0xC3; + + /** Document Environment Group (DEG) */ + byte DOCUMENT_ENVIRONMENT_GROUP = (byte)0xC4; + + /** Resource Group */ + byte RESOURCE_GROUP = (byte)0xC6; + + /** Object Environment Group (OEG) */ + byte OBJECT_ENVIRONMENT_GROUP = (byte)0xC7; + + /** Active Environment Group (AEG) */ + byte ACTIVE_ENVIRONMENT_GROUP = (byte)0xC9; + + /** Medium Map */ + byte MEDIUM_MAP = (byte)0xCC; + + /** Form Map */ + byte FORM_MAP = (byte)0xCD; + + /** Name Resource */ + byte NAME_RESOURCE = (byte)0xCE; + + /** Page Overlay */ + byte PAGE_OVERLAY = (byte)0xD8; + + /** Resource Environment Group (REG) */ + byte RESOURCE_ENVIROMENT_GROUP = (byte)0xD9; + + /** Overlay */ + byte OVERLAY = (byte)0xDF; + + /** Data Suppression */ + byte DATA_SUPRESSION = (byte)0xEA; + + /** Bar Code */ + byte BARCODE = (byte)0xEB; + + /** No Operation */ + byte NO_OPERATION = (byte)0xEE; + + /** Image */ + byte IMAGE = (byte)0xFB; + } + +} + diff --git a/src/java/org/apache/fop/afp/modca/AbstractDataObject.java b/src/java/org/apache/fop/afp/modca/AbstractDataObject.java new file mode 100644 index 000000000..4a13b4a55 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractDataObject.java @@ -0,0 +1,140 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceLevel; +import org.apache.fop.afp.Completable; +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.Startable; + +/** + * Abstract base class used by the ImageObject and GraphicsObject which both + * have define an ObjectEnvironmentGroup + */ +public abstract class AbstractDataObject extends AbstractNamedAFPObject implements Startable, Completable { + + /** the object environment group */ + protected ObjectEnvironmentGroup objectEnvironmentGroup = null; + + /** the object factory */ + protected final Factory factory; + + /** the completion status of this object */ + private boolean complete; + + /** the starting status of this object */ + private boolean started; + + /** + * Named constructor + * + * @param factory the object factory + * @param name data object name + */ + public AbstractDataObject(Factory factory, String name) { + super(name); + this.factory = factory; + } + + /** + * Sets the object view port (area position and size). + * + * @param dataObjectInfo + * the object area info + */ + public void setViewport(AFPDataObjectInfo dataObjectInfo) { + AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); + + // object area descriptor + int width = objectAreaInfo.getWidth(); + int height = objectAreaInfo.getHeight(); + int widthRes = objectAreaInfo.getWidthRes(); + int heightRes = objectAreaInfo.getHeightRes(); + ObjectAreaDescriptor objectAreaDescriptor + = factory.createObjectAreaDescriptor(width, height, widthRes, heightRes); + getObjectEnvironmentGroup().setObjectAreaDescriptor(objectAreaDescriptor); + + // object area position + AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + AFPResourceLevel resourceLevel = resourceInfo.getLevel(); + ObjectAreaPosition objectAreaPosition = null; + if (resourceLevel.isInline()) { + int x = objectAreaInfo.getX(); + int y = objectAreaInfo.getY(); + int rotation = objectAreaInfo.getRotation(); + objectAreaPosition = factory.createObjectAreaPosition(x, y, rotation); + } else { + // positional values are specified in the oaOffset of the include object + objectAreaPosition = factory.createObjectAreaPosition(0, 0, 0); + } + getObjectEnvironmentGroup().setObjectAreaPosition(objectAreaPosition); + } + + /** + * Gets the ObjectEnvironmentGroup + * + * @return the object environment group + */ + public ObjectEnvironmentGroup getObjectEnvironmentGroup() { + if (objectEnvironmentGroup == null) { + this.objectEnvironmentGroup = factory.createObjectEnvironmentGroup(); + } + return objectEnvironmentGroup; + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + setStarted(true); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + writeTriplets(os); + if (objectEnvironmentGroup != null) { + objectEnvironmentGroup.writeToStream(os); + } + } + + /** {@inheritDoc} */ + public void setStarted(boolean started) { + this.started = started; + } + + /** {@inheritDoc} */ + public boolean isStarted() { + return this.started; + } + + /** {@inheritDoc} */ + public void setComplete(boolean complete) { + this.complete = complete; + } + + /** {@inheritDoc} */ + public boolean isComplete() { + return this.complete; + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java b/src/java/org/apache/fop/afp/modca/AbstractDescriptor.java index 83ed9b99a..8344bf0d1 100644 --- a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java +++ b/src/java/org/apache/fop/afp/modca/AbstractDescriptor.java @@ -17,33 +17,68 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; /** * Base class for AFP descriptor objects */ -public abstract class AbstractDescriptor extends AbstractAFPObject { +public abstract class AbstractDescriptor extends AbstractTripletStructuredObject { + /** width of this descriptor */ protected int width = 0; /** height of this descriptor */ protected int height = 0; /** width resolution of this descriptor */ - protected int widthResolution = 0; + protected int widthRes = 0; /** height resolution of this descriptor */ - protected int heightResolution = 0; + protected int heightRes = 0; + + /** + * Default constructor + */ + public AbstractDescriptor() { + } /** * Constructor a PresentationTextDescriptor for the specified * width and height. + * * @param width The width of the page. * @param height The height of the page. - * @param widthResolution The width resolution of the page. - * @param heightResolution The height resolution of the page. + * @param widthRes The width resolution of the page. + * @param heightRes The height resolution of the page. */ - public AbstractDescriptor(int width, int height, int widthResolution, int heightResolution) { + public AbstractDescriptor(int width, int height, int widthRes, int heightRes) { this.width = width; this.height = height; - this.widthResolution = widthResolution; - this.heightResolution = heightResolution; + this.widthRes = widthRes; + this.heightRes = heightRes; + } + + /** {@inheritDoc} */ + public String toString() { + return "width=" + width + + ", height=" + height + + ", widthRes=" + widthRes + + ", heightRes=" + heightRes; + } + + /** + * Returns the width + * + * @return the width + */ + public int getWidth() { + return this.width; + } + + /** + * Returns the height + * + * @return the height + */ + public int getHeight() { + return this.height; } + } diff --git a/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java new file mode 100644 index 000000000..a58bba1f0 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractEnvironmentGroup.java @@ -0,0 +1,101 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + * A base class that encapsulates common features of + * ActiveEnvironmentGroup and ResourceEnvironmentGroup + */ +public abstract class AbstractEnvironmentGroup extends AbstractNamedAFPObject { + + /** + * The collection of MapPageOverlay objects + */ + protected List mapPageOverlays = null; + + /** + * Main constructor + * + * @param name the object name + */ + public AbstractEnvironmentGroup(String name) { + super(name); + } + + private List getMapPageOverlays() { + if (mapPageOverlays == null) { + mapPageOverlays = new java.util.ArrayList(); + } + return mapPageOverlays; + } + + /** + * Actually creates the MPO object. + * Also creates the supporting object (an IPO) + * + * @param name the name of the overlay to be used + */ + public void createOverlay(String name) { + MapPageOverlay mpo = getCurrentMapPageOverlay(); + if (mpo == null) { + mpo = new MapPageOverlay(); + getMapPageOverlays().add(mpo); + } + + try { + mpo.addOverlay(name); + } catch (MaximumSizeExceededException msee) { + mpo = new MapPageOverlay(); + getMapPageOverlays().add(mpo); + try { + mpo.addOverlay(name); + } catch (MaximumSizeExceededException ex) { + // Should never happen (but log just in case) + log.error("createOverlay():: resulted in a MaximumSizeExceededException"); + } + } + } + + /** + * Getter method for the most recent MapPageOverlay added to the + * Active Environment Group (returns null if no MapPageOverlay exist) + * + * @return the most recent Map Coded Font + */ + private MapPageOverlay getCurrentMapPageOverlay() { + if (mapPageOverlays != null && mapPageOverlays.size() > 0) { + return (MapPageOverlay) mapPageOverlays.get(mapPageOverlays.size() - 1); + } else { + return null; + } + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (mapPageOverlays != null) { + writeObjects(mapPageOverlays, os); + } + } +} diff --git a/src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java new file mode 100644 index 000000000..4e0dbc349 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractNamedAFPObject.java @@ -0,0 +1,122 @@ +/* + * 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.afp.modca; + +import java.io.UnsupportedEncodingException; + +import org.apache.fop.afp.AFPConstants; + +/** + * This is the base class for all named data stream objects. + * A named data stream object has an 8 byte EBCIDIC name. + */ +public abstract class AbstractNamedAFPObject extends AbstractTripletStructuredObject { + + private static final int DEFAULT_NAME_LENGTH = 8; + + /** + * The actual name of the object + */ + protected String name = null; + + /** + * Default constructor + */ + protected AbstractNamedAFPObject() { + } + + /** + * Constructor for the ActiveEnvironmentGroup, this takes a + * name parameter which should be 8 characters long. + * + * @param name the object name + */ + protected AbstractNamedAFPObject(String name) { + this.name = name; + } + + /** + * Returns the name length + * + * @return the name length + */ + protected int getNameLength() { + return DEFAULT_NAME_LENGTH; + } + + /** + * Returns the name as a byte array in EBCIDIC encoding + * + * @return the name as a byte array in EBCIDIC encoding + */ + public byte[] getNameBytes() { + int afpNameLen = getNameLength(); + int nameLen = name.length(); + if (nameLen < afpNameLen) { + name = (name + " ").substring(0, afpNameLen); + } else if (name.length() > afpNameLen) { + String truncatedName = name.substring(nameLen - afpNameLen, nameLen); + log.warn("Constructor:: name '" + name + "'" + + " truncated to " + afpNameLen + " chars" + + " ('" + truncatedName + "')"); + name = truncatedName; + } + byte[] nameBytes = null; + try { + nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException usee) { + nameBytes = name.getBytes(); + log.warn( + "Constructor:: UnsupportedEncodingException translating the name " + + name); + } + return nameBytes; + } + + /** {@inheritDoc} */ + protected void copySF(byte[] data, byte type, byte category) { + super.copySF(data, type, category); + byte[] nameData = getNameBytes(); + System.arraycopy(nameData, 0, data, 9, nameData.length); + } + + /** + * Returns the name of this object + * + * @return the name of this object + */ + public String getName() { + return this.name; + } + + /** + * Sets the name of this object + * + * @param name the object name + */ + public void setName(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + public String toString() { + return getName(); + } +} diff --git a/src/java/org/apache/fop/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java new file mode 100644 index 000000000..249de1339 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractPageObject.java @@ -0,0 +1,350 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.List; + +import org.apache.fop.afp.AFPLineDataInfo; +import org.apache.fop.afp.AFPTextDataInfo; +import org.apache.fop.afp.Completable; +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.fonts.AFPFont; + +/** + * Pages contain the data objects that comprise a presentation document. Each + * page has a set of data objects associated with it. Each page within a + * document is independent from any other page, and each must establish its own + * environment parameters. + * + * The page is the level in the document component hierarchy that is used for + * printing or displaying a document's content. The data objects contained in + * the page envelope in the data stream are presented when the page is + * presented. Each data object has layout information associated with it that + * directs the placement and orientation of the data on the page. In addition, + * each page contains layout information that specifies the measurement units, + * page width, and page depth. + * + * A page is initiated by a begin page structured field and terminated by an end + * page structured field. Structured fields that define objects and active + * environment groups or that specify attributes of the page may be encountered + * in page state. + * + */ +public abstract class AbstractPageObject extends AbstractNamedAFPObject implements Completable { + + /** The active environment group for the page */ + protected ActiveEnvironmentGroup activeEnvironmentGroup = null; + + /** The current presentation text object */ + private PresentationTextObject currentPresentationTextObject = null; + + /** The list of tag logical elements */ + protected List/*<TagLogicalElement>*/ tagLogicalElements = null; + + /** The list of the include page segments */ + protected List/*<IncludePageSegment>*/ includePageSegments = null; + + /** The list of objects within this resource container */ + protected List/*<AbstractStructuredAFPObject>*/ objects = new java.util.ArrayList(); + + /** The page width */ + private int width; + + /** The page height */ + private int height; + + /** The page rotation */ + protected int rotation = 0; + + /** The page state */ + protected boolean complete = false; + + /** The width resolution */ + private int widthRes; + + /** The height resolution */ + private int heightRes; + + /** the object factory */ + protected final Factory factory; + + /** + * Default constructor + * + * @param factory the object factory + */ + public AbstractPageObject(Factory factory) { + this.factory = factory; + } + + /** + * Main constructor + * + * @param factory the object factory + * @param name the name of this page object + */ + public AbstractPageObject(Factory factory, String name) { + super(name); + this.factory = factory; + } + + /** + * Construct a new page object for the specified name argument, the page + * name should be an 8 character identifier. + * + * @param factory + * the object factory. + * @param name + * the name of the page. + * @param width + * the width of the page. + * @param height + * the height of the page. + * @param rotation + * the rotation of the page. + * @param widthRes + * the width resolution of the page. + * @param heightRes + * the height resolution of the page. + */ + public AbstractPageObject(Factory factory, + String name, int width, int height, int rotation, + int widthRes, int heightRes) { + super(name); + + this.factory = factory; + this.width = width; + this.height = height; + this.rotation = rotation; + this.widthRes = widthRes; + this.heightRes = heightRes; + } + + /** + * Helper method to create a map coded font object on the current page, this + * method delegates the construction of the map coded font object to the + * active environment group on the page. + * + * @param fontReference + * the font number used as the resource identifier + * @param font + * the font + * @param size + * the point size of the font + */ + public void createFont(int fontReference, AFPFont font, int size) { + getActiveEnvironmentGroup().createFont(fontReference, font, size, 0); + } + + /** + * Helper method to create a line on the current page, this method delegates + * to the presentation text object in order to construct the line. + * + * @param lineDataInfo the line data information. + */ + public void createLine(AFPLineDataInfo lineDataInfo) { + getPresentationTextObject().createLineData(lineDataInfo); + } + + /** + * Helper method to create text on the current page, this method delegates + * to the presentation text object in order to construct the text. + * + * @param textDataInfo + * the afp text data + * @throws UnsupportedEncodingException thrown if character encoding is not supported + */ + public void createText(AFPTextDataInfo textDataInfo) throws UnsupportedEncodingException { + getPresentationTextObject().createTextData(textDataInfo); + } + + /** + * Helper method to mark the end of the page. This should end the control + * sequence on the current presentation text object. + */ + public void endPage() { + if (currentPresentationTextObject != null) { + currentPresentationTextObject.endControlSequence(); + } + setComplete(true); + } + + /** + * Ends the presentation text object + */ + protected void endPresentationObject() { + if (currentPresentationTextObject != null) { + currentPresentationTextObject.endControlSequence(); + currentPresentationTextObject = null; + } + } + + /** + * Helper method to create a presentation text object + * on the current page and to return the object. + * + * @return the presentation text object + */ + private PresentationTextObject getPresentationTextObject() { + if (currentPresentationTextObject == null) { + PresentationTextObject presentationTextObject + = factory.createPresentationTextObject(); + addObject(presentationTextObject); + this.currentPresentationTextObject = presentationTextObject; + } + return currentPresentationTextObject; + } + + /** + * Creates a TagLogicalElement on the page. + * + * @param name + * the name of the tag + * @param value + * the value of the tag + */ + public void createTagLogicalElement(String name, String value) { + TagLogicalElement tle = new TagLogicalElement(name, value); + if (tagLogicalElements == null) { + tagLogicalElements = new java.util.ArrayList/*<TagLogicalElement>*/(); + } + tagLogicalElements.add(tle); + } + + /** + * Creates a NoOperation on the page. + * + * @param content the byte data + */ + public void createNoOperation(String content) { + addObject(new NoOperation(content)); + } + + /** + * Creates an IncludePageSegment on the current page. + * + * @param name + * the name of the page segment + * @param x + * the x coordinate of the page segment. + * @param y + * the y coordinate of the page segment. + */ + public void createIncludePageSegment(String name, int x, int y) { + IncludePageSegment ips = factory.createIncludePageSegment(name, x, y); + getIncludePageSegments().add(ips); + } + + /** + * Returns the include page segments list + * + * @return the include page segments list + */ + private List getIncludePageSegments() { + if (this.includePageSegments == null) { + this.includePageSegments = new java.util.ArrayList/*<IncludePageSegment>*/(); + } + return this.includePageSegments; + } + + /** + * Returns the ActiveEnvironmentGroup associated with this page. + * + * @return the ActiveEnvironmentGroup object + */ + public ActiveEnvironmentGroup getActiveEnvironmentGroup() { + if (activeEnvironmentGroup == null) { + // every page object must have an ActiveEnvironmentGroup + this.activeEnvironmentGroup + = factory.createActiveEnvironmentGroup(width, height, widthRes, heightRes); + + if (rotation != 0) { + switch (rotation) { + case 90: + activeEnvironmentGroup.setObjectAreaPosition(width, 0, rotation); + break; + case 180: + activeEnvironmentGroup.setObjectAreaPosition(width, height, rotation); + break; + case 270: + activeEnvironmentGroup.setObjectAreaPosition(0, height, rotation); + break; + default: + } + } + } + return activeEnvironmentGroup; + } + + /** + * Returns the height of the page + * + * @return the height of the page + */ + public int getHeight() { + return height; + } + + /** + * Returns the width of the page + * + * @return the width of the page + */ + public int getWidth() { + return width; + } + + /** + * Returns the rotation of the page + * + * @return the rotation of the page + */ + public int getRotation() { + return rotation; + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + writeObjects(this.objects, os); + } + + /** + * Adds an AFP object reference to this page + * + * @param obj an AFP object + */ + public void addObject(Object obj) { + objects.add(obj); + } + + /** {@inheritDoc} */ + public void setComplete(boolean complete) { + this.complete = complete; + } + + /** {@inheritDoc} */ + public boolean isComplete() { + return this.complete; + } +} diff --git a/src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java b/src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java new file mode 100644 index 000000000..baba170f7 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractResourceEnvironmentGroupContainer.java @@ -0,0 +1,99 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Factory; + + +/** + * An abstract class which encapsulates the common features of + * Document and PageGroup resource containers + */ +public abstract class AbstractResourceEnvironmentGroupContainer + extends AbstractResourceGroupContainer { + + /** + * The resource environment group used to store complex resources + */ + protected ResourceEnvironmentGroup resourceEnvironmentGroup = null; + + /** + * Main constructor + * + * @param factory the object factory + * @param name the name of this resource container + */ + public AbstractResourceEnvironmentGroupContainer( + Factory factory, String name) { + super(factory, name); + } + + /** + * Adds a page to the resource container. + * + * @param page - the Page object + */ + public void addPage(PageObject page) { + addObject(page); + } + + /** + * Adds a PageGroup to the resource container. + * + * @param pageGroup the PageGroup object + */ + public void addPageGroup(PageGroup pageGroup) { + addObject(pageGroup); + } + + /** + * Creates an InvokeMediaMap on the page. + * + * @param name + * the name of the media map + */ + public void createInvokeMediumMap(String name) { + InvokeMediumMap invokeMediumMap = factory.createInvokeMediumMap(name); + addObject(invokeMediumMap); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + if (resourceEnvironmentGroup != null) { + resourceEnvironmentGroup.writeToStream(os); + } + } + + /** + * Returns the resource environment group + * + * @return the resource environment group + */ + protected ResourceEnvironmentGroup getResourceEnvironmentGroup() { + if (resourceEnvironmentGroup == null) { + this.resourceEnvironmentGroup = factory.createResourceEnvironmentGroup(); + } + return this.resourceEnvironmentGroup; + } +} diff --git a/src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java b/src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java new file mode 100644 index 000000000..9dcd56277 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractResourceGroupContainer.java @@ -0,0 +1,168 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collection; +import java.util.Iterator; + +import org.apache.fop.afp.Completable; +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.Streamable; + + +/** + * An abstract container of resource objects + */ +public abstract class AbstractResourceGroupContainer extends AbstractPageObject +implements Streamable { + + /** The container started state */ + protected boolean started = false; + + /** the resource group object */ + protected ResourceGroup resourceGroup = null; + + /** + * Default constructor + * + * @param factory the object factory + */ + public AbstractResourceGroupContainer(Factory factory) { + super(factory); + } + + /** + * Named constructor + * + * @param factory the object factory + * @param name the name of this resource container + */ + public AbstractResourceGroupContainer(Factory factory, String name) { + super(factory, name); + } + + /** + * Construct a new page object for the specified name argument, the page + * name should be an 8 character identifier. + * + * @param factory + * the object factory + * @param name + * the name of the page. + * @param width + * the width of the page. + * @param height + * the height of the page. + * @param rotation + * the rotation of the page. + * @param widthRes + * the width resolution of the page. + * @param heightRes + * the height resolution of the page. + */ + public AbstractResourceGroupContainer(Factory factory, + String name, int width, int height, int rotation, int widthRes, int heightRes) { + super(factory, name, width, height, rotation, widthRes, heightRes); + } + + /** + * Return the number of resources in this container + * + * @return the number of resources in this container + */ + protected int getResourceCount() { + if (resourceGroup != null) { + return resourceGroup.getResourceCount(); + } + return 0; + } + + /** + * Returns true if this resource group container contains resources + * + * @return true if this resource group container contains resources + */ + protected boolean hasResources() { + return resourceGroup != null && resourceGroup.getResourceCount() > 0; + } + + /** + * Returns the resource group in this resource group container + * + * @return the resource group in this resource group container + */ + public ResourceGroup getResourceGroup() { + if (resourceGroup == null) { + resourceGroup = factory.createResourceGroup(); + } + return resourceGroup; + } + +// /** {@inheritDoc} */ +// protected void writeContent(OutputStream os) throws IOException { +// if (resourceGroup != null) { +// resourceGroup.writeToStream(os); +// } +// super.writeContent(os); +// } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + if (!started) { + writeStart(os); + started = true; + } + + writeContent(os); + + if (complete) { + writeEnd(os); + } + } + + /** {@inheritDoc} */ + protected void writeObjects(Collection/*<AbstractAFPObject>*/ objects, OutputStream os) + throws IOException { + if (objects != null && objects.size() > 0) { + Iterator it = objects.iterator(); + while (it.hasNext()) { + AbstractAFPObject ao = (AbstractAFPObject)it.next(); + if (canWrite(ao)) { + ao.writeToStream(os); + it.remove(); + } else { + break; + } + } + } + } + + /** + * Returns true if this object can be written + * + * @param obj an AFP object + * @return true if this object can be written + */ + protected boolean canWrite(AbstractAFPObject obj) { + return obj instanceof AbstractPageObject && ((Completable)obj).isComplete(); + } +} diff --git a/src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java b/src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java new file mode 100644 index 000000000..e848583b5 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractStructuredObject.java @@ -0,0 +1,69 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * An abstract class encapsulating an MODCA structured object + */ +public abstract class AbstractStructuredObject extends AbstractAFPObject { + + /** + * Default constructor + */ + protected AbstractStructuredObject() { + } + + /** + * Helper method to write the start of the Object. + * + * @param os The stream to write to + * @throws IOException throws an I/O exception if one occurred + */ + protected void writeStart(OutputStream os) throws IOException { + } + + /** + * Helper method to write the end of the Object. + * + * @param os The stream to write to + * @throws IOException an I/O exception if one occurred + */ + protected void writeEnd(OutputStream os) throws IOException { + } + + /** + * Helper method to write the contents of the Object. + * + * @param os The stream to write to + * @throws IOException throws an I/O exception if one occurred + */ + protected void writeContent(OutputStream os) throws IOException { + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + writeStart(os); + writeContent(os); + writeEnd(os); + } +} diff --git a/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java b/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java new file mode 100644 index 000000000..a14af2967 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java @@ -0,0 +1,181 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.afp.modca.Registry.ObjectType; +import org.apache.fop.afp.modca.triplets.AbstractTriplet; +import org.apache.fop.afp.modca.triplets.CommentTriplet; +import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet; + +/** + * A MODCA structured object base class providing support for Triplets + */ +public class AbstractTripletStructuredObject extends AbstractStructuredObject { + + /** list of object triplets */ + protected List/*<AbstractTriplet>*/ triplets = new java.util.ArrayList/*<AbstractTriplet>*/(); + + /** + * Returns the triplet data length + * + * @return the triplet data length + */ + protected int getTripletDataLength() { + int dataLength = 0; + if (hasTriplets()) { + Iterator it = triplets.iterator(); + while (it.hasNext()) { + AbstractTriplet triplet = (AbstractTriplet)it.next(); + dataLength += triplet.getDataLength(); + } + } + return dataLength; + } + + /** + * Returns true when this structured field contains triplets + * + * @return true when this structured field contains triplets + */ + public boolean hasTriplets() { + return triplets.size() > 0; + } + + /** + * Writes any triplet data + * + * @param os The stream to write to + * @throws IOException The stream to write to + */ + protected void writeTriplets(OutputStream os) throws IOException { + if (hasTriplets()) { + writeObjects(triplets, os); + triplets = null; // gc + } + } + + /** + * Returns the first matching triplet found in the structured field triplet list + * + * @param tripletId the triplet identifier + */ + private AbstractTriplet getTriplet(byte tripletId) { + Iterator it = getTriplets().iterator(); + while (it.hasNext()) { + AbstractTriplet triplet = (AbstractTriplet)it.next(); + if (triplet.getId() == tripletId) { + return triplet; + } + } + return null; + } + + /** + * Returns true of this structured field has the given triplet + * + * @param tripletId the triplet identifier + * @return true if the structured field has the given triplet + */ + public boolean hasTriplet(byte tripletId) { + return getTriplet(tripletId) != null; + } + + /** + * Adds a triplet to this structured object + * + * @param triplet the triplet to add + */ + protected void addTriplet(AbstractTriplet triplet) { + triplets.add(triplet); + } + + /** + * Adds a list of triplets to the triplets contained within this structured field + * + * @param tripletCollection a collection of triplets + */ + public void addTriplets(Collection/*<Triplet>*/ tripletCollection) { + if (tripletCollection != null) { + triplets.addAll(tripletCollection); + } + } + + /** @return the triplet list pertaining to this resource */ + protected List/*<Triplet>*/ getTriplets() { + return triplets; + } + + /** + * Sets the fully qualified name of this resource + * + * @param fqnType the fully qualified name type of this resource + * @param fqnFormat the fully qualified name format of this resource + * @param fqName the fully qualified name of this resource + */ + public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) { + addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqName)); + } + + /** @return the fully qualified name of this triplet or null if it does not exist */ + public String getFullyQualifiedName() { + FullyQualifiedNameTriplet fqNameTriplet + = (FullyQualifiedNameTriplet)getTriplet(AbstractTriplet.FULLY_QUALIFIED_NAME); + if (fqNameTriplet != null) { + return fqNameTriplet.getFullyQualifiedName(); + } + log.warn(this + " has no fully qualified name"); + return null; + } + + /** + * Sets the objects classification + * + * @param objectClass the classification of the object + * @param objectType the MOD:CA registry object type entry for the given + * object/component type of the object + * @param dataInContainer whether the data resides in the container + * @param containerHasOEG whether the container has an object environment group + * @param dataInOCD whether the data resides in a object container data structured field + */ + public void setObjectClassification( + byte objectClass, ObjectType objectType, + boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD) { + addTriplet( + new ObjectClassificationTriplet( + objectClass, objectType, dataInContainer, containerHasOEG, dataInOCD)); + } + + /** + * Sets a comment on this resource + * + * @param commentString a comment string + */ + public void setComment(String commentString) { + addTriplet(new CommentTriplet(AbstractTriplet.COMMENT, commentString)); + } + +} diff --git a/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java new file mode 100644 index 000000000..ddc986be3 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java @@ -0,0 +1,221 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.fonts.AFPFont; + +/** + * An Active Environment Group (AEG) is associated with each page, + * and is contained in the page's begin-end envelope in the data stream. + * The active environment group contains layout and formatting information + * that defines the measurement units and size of the page, and may contain + * resource information. + * + * Any objects that are required for page presentation and that are to be + * treated as resource objects must be mapped with a map structured field + * in the AEG. The scope of an active environment group is the scope of its + * containing page or overlay. + * + */ +public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { + + /** The collection of MapCodedFont objects */ + private final List/*<MapCodedFonts>*/ mapCodedFonts + = new java.util.ArrayList/*<MapCodedFonts>*/(); + + /** the collection of MapDataResource objects */ + private final List mapDataResources = null; + + /** the Object Area Descriptor for the active environment group */ + private ObjectAreaDescriptor objectAreaDescriptor = null; + + /** the Object Area Position for the active environment group */ + private ObjectAreaPosition objectAreaPosition = null; + + /** the PresentationTextDescriptor for the active environment group */ + private PresentationTextDescriptor presentationTextDataDescriptor = null; + + /** the PageDescriptor for the active environment group */ + private PageDescriptor pageDescriptor = null; + + /** the resource manager */ + private final Factory factory; + + /** + * Constructor for the ActiveEnvironmentGroup, this takes a + * name parameter which must be 8 characters long. + * + * @param factory the object factory + * @param name the active environment group name + * @param width the page width + * @param height the page height + * @param widthRes the page width resolution + * @param heightRes the page height resolution + */ + public ActiveEnvironmentGroup(Factory factory, + String name, int width, int height, int widthRes, int heightRes) { + super(name); + + this.factory = factory; + + // Create PageDescriptor + this.pageDescriptor + = factory.createPageDescriptor(width, height, widthRes, heightRes); + + // Create ObjectAreaDescriptor + this.objectAreaDescriptor + = factory.createObjectAreaDescriptor(width, height, widthRes, heightRes); + + // Create PresentationTextDataDescriptor + this.presentationTextDataDescriptor + = factory.createPresentationTextDataDescriptor(width, height, + widthRes, heightRes); + } + + /** + * Set the position of the object area + * + * @param x the x offset + * @param y the y offset + * @param rotation the rotation + */ + public void setObjectAreaPosition(int x, int y, int rotation) { + this.objectAreaPosition = factory.createObjectAreaPosition(x, y, rotation); + } + + /** + * Accessor method to obtain the PageDescriptor object of the + * active environment group. + * + * @return the page descriptor object + */ + public PageDescriptor getPageDescriptor() { + return pageDescriptor; + } + + /** + * Accessor method to obtain the PresentationTextDataDescriptor object of + * the active environment group. + * + * @return the presentation text descriptor + */ + public PresentationTextDescriptor getPresentationTextDataDescriptor() { + return presentationTextDataDescriptor; + } + + /** {@inheritDoc} */ + public void writeContent(OutputStream os) throws IOException { + super.writeTriplets(os); + + writeObjects(mapCodedFonts, os); + writeObjects(mapDataResources, os); + writeObjects(mapPageOverlays, os); + + if (pageDescriptor != null) { + pageDescriptor.writeToStream(os); + } + if (objectAreaDescriptor != null && objectAreaPosition != null) { + objectAreaDescriptor.writeToStream(os); + objectAreaPosition.writeToStream(os); + } + if (presentationTextDataDescriptor != null) { + presentationTextDataDescriptor.writeToStream(os); + } + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.ACTIVE_ENVIRONMENT_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.ACTIVE_ENVIRONMENT_GROUP); + os.write(data); + } + + /** + * Method to create a map coded font object + * + * @param fontRef the font number used as the resource identifier + * @param font the font + * @param size the point size of the font + * @param orientation the orientation of the font (e.g. 0, 90, 180, 270) + */ + public void createFont(int fontRef, AFPFont font, int size, int orientation) { + MapCodedFont mapCodedFont = getCurrentMapCodedFont(); + if (mapCodedFont == null) { + mapCodedFont = factory.createMapCodedFont(); + mapCodedFonts.add(mapCodedFont); + } + + try { + mapCodedFont.addFont(fontRef, font, size, orientation); + } catch (MaximumSizeExceededException msee) { + mapCodedFont = factory.createMapCodedFont(); + mapCodedFonts.add(mapCodedFont); + + try { + mapCodedFont.addFont(fontRef, font, size, orientation); + } catch (MaximumSizeExceededException ex) { + // Should never happen (but log just in case) + log.error("createFont():: resulted in a MaximumSizeExceededException"); + } + } + } + + /** + * Getter method for the most recent MapCodedFont added to the + * Active Environment Group (returns null if no MapCodedFonts exist) + * + * @return the most recent Map Coded Font. + */ + private MapCodedFont getCurrentMapCodedFont() { + int size = mapCodedFonts.size(); + if (size > 0) { + return (MapCodedFont)mapCodedFonts.get(size - 1); + } else { + return null; + } + } + +// private List getMapDataResources() { +// if (mapDataResources == null) { +// mapDataResources = new java.util.ArrayList(); +// } +// return mapDataResources; +//} + +// /** +// * Method to create a map data resource object +// * @param dataObjectAccessor a data object accessor +// */ +// protected void createMapDataResource(DataObjectAccessor dataObjectAccessor) { +// getMapDataResources().add(new MapDataResource(dataObjectAccessor)); +// } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java new file mode 100644 index 000000000..0f99d6624 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ContainerDataDescriptor.java @@ -0,0 +1,84 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * Container data descriptor (to maintain compatibility with pre-year 2000 applications) + */ +public class ContainerDataDescriptor extends AbstractDescriptor { + + /** + * Main constructor + * + * @param width the container data width + * @param height the container data height + * @param widthRes the container width resolution + * @param heightRes the container height resolution + */ + public ContainerDataDescriptor(int width, int height, int widthRes, + int heightRes) { + super(width, height, widthRes, heightRes); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[21]; + copySF(data, Type.DESCRIPTOR, Category.OBJECT_CONTAINER); + + // SF length + byte[] len = BinaryUtils.convert(data.length - 1, 2); + data[1] = len[0]; + data[2] = len[1]; + + // XocBase = 10 inches + data[9] = 0x00; + + // YocBase = 10 inches + data[10] = 0x00; + + // XocUnits + byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); + data[11] = xdpi[0]; + data[12] = xdpi[1]; + + // YocUnits + byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); + data[13] = ydpi[0]; + data[14] = ydpi[1]; + + // XocSize + byte[] xsize = BinaryUtils.convert(width, 3); + data[15] = xsize[0]; + data[16] = xsize[1]; + data[17] = xsize[2]; + + // YocSize + byte[] ysize = BinaryUtils.convert(height, 3); + data[18] = ysize[0]; + data[19] = ysize[1]; + data[20] = ysize[2]; + } + +} diff --git a/src/java/org/apache/fop/afp/modca/Document.java b/src/java/org/apache/fop/afp/modca/Document.java new file mode 100644 index 000000000..02a7b64e1 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/Document.java @@ -0,0 +1,96 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Factory; + +/** + * The document is the highest level of the MO:DCA data-stream document + * component hierarchy. Documents can be made up of pages, and the pages, which + * are at the intermediate level, can be made up of objects. Objects are at the + * lowest level, and can be bar codes, graphics, images, and presentation text. + * + * At each level of the hierarchy certain sets of MO:DCA data structures, called + * structured fields, are permissible. The document, pages and objects are + * bounded by structured fields that define their beginnings and their ends. + * These structured fields, called begin-end pairs, provide an envelope for the + * data-stream components. This feature enables a processor of the data stream + * that is not fully compliant with the architecture to bypass those objects + * that are beyond its scope, and to process the data stream to the best of its + * abilities. + * + * A presentation document is one that has been formatted and is intended for + * presentation, usually on a printer or display device. A data stream + * containing a presentation document should produce the same document content + * in the same format on different printers or display devices dependent, + * however, on the capabilities of each of the printers or display devices. A + * presentation document can reference resources that are to be included as part + * of the document to be presented. + * + */ +public final class Document extends AbstractResourceEnvironmentGroupContainer { + + /** + * Constructor for the document object. + * + * @param factory + * the object factory + * @param name + * the name of the document + */ + public Document(Factory factory, String name) { + super(factory, name); + } + + /** + * Method to mark the end of the page group. + */ + public void endDocument() { + complete = true; + } + + /** {@inheritDoc} */ + public boolean isComplete() { + return complete; + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.DOCUMENT); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.DOCUMENT); + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return this.name; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java b/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java new file mode 100644 index 000000000..5495e2e9c --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/GraphicsDataDescriptor.java @@ -0,0 +1,152 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * GOCA Graphics Data Descriptor + */ +public class GraphicsDataDescriptor extends AbstractDescriptor { + + private final int xlwind; + + private final int xrwind; + + private final int ybwind; + + private final int ytwind; + + /** + * Main constructor + * + * @param xlwind + * the left edge of the graphics window + * @param xrwind + * the right edge of the graphics window + * @param ybwind + * the top edge of the graphics window + * @param ytwind + * the bottom edge of the graphics window + * @param widthRes + * the width resolution of the graphics window + * @param heightRes + * the height resolution of the graphics window + */ + public GraphicsDataDescriptor(int xlwind, int xrwind, int ybwind, + int ytwind, int widthRes, int heightRes) { + this.xlwind = xlwind; + this.xrwind = xrwind; + this.ybwind = ybwind; + this.ytwind = ytwind; + super.widthRes = widthRes; + super.heightRes = heightRes; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] headerData = new byte[9]; + copySF(headerData, Type.DESCRIPTOR, Category.GRAPHICS); + + byte[] drawingOrderSubsetData = getDrawingOrderSubset(); + + byte[] windowSpecificationData = getWindowSpecification(); + + byte[] len = BinaryUtils.convert(headerData.length + + drawingOrderSubsetData.length + + windowSpecificationData.length - 1, 2); + headerData[1] = len[0]; + headerData[2] = len[1]; + + os.write(headerData); + os.write(drawingOrderSubsetData); + os.write(windowSpecificationData); + } + + /** + * Returns the drawing order subset data + * + * @return the drawing order subset data + */ + private byte[] getDrawingOrderSubset() { + final byte[] data = new byte[] { + // Drawing order subset + (byte) 0xF7, + 7, // LENGTH + (byte) 0xB0, // drawing order subset + 0x00, // reserved (must be zero) + 0x00, // reserved (must be zero) + 0x02, // SUBLEV + 0x00, // VERSION 0 + 0x01, // LENGTH (of following field) + 0x00 // GEOM + }; + return data; + } + + private static final int ABS = 2; + private static final int IMGRES = 8; + + /** + * Returns the window specification data + * + * @return the window specification data + */ + private byte[] getWindowSpecification() { + byte[] xlcoord = BinaryUtils.convert(xlwind, 2); + byte[] xrcoord = BinaryUtils.convert(xrwind, 2); + byte[] xbcoord = BinaryUtils.convert(ybwind, 2); + byte[] ytcoord = BinaryUtils.convert(ytwind, 2); + byte[] xResol = BinaryUtils.convert(widthRes * 10, 2); + byte[] yResol = BinaryUtils.convert(heightRes * 10, 2); + byte[] imxyres = xResol; + + // Window specification + final byte[] data = new byte[] { + (byte) 0xF6, + 18, // LENGTH + (ABS + IMGRES), // FLAGS (ABS) + 0x00, // reserved (must be zero) + 0x00, // CFORMAT (coordinate format - 16bit high byte first signed) + 0x00, // UBASE (unit base - ten inches) + + xResol[0], // XRESOL + xResol[1], + yResol[0], // YRESOL + yResol[1], + + imxyres[0], // IMXYRES (Number of image points per ten inches + imxyres[1], // in X and Y directions) + + xlcoord[0], // XLWIND + xlcoord[1], + xrcoord[0], // XRWIND + xrcoord[1], + xbcoord[0], // YBWIND + xbcoord[1], + ytcoord[0], // YTWIND + ytcoord[1] + }; + return data; + } +} diff --git a/src/java/org/apache/fop/afp/modca/GraphicsObject.java b/src/java/org/apache/fop/afp/modca/GraphicsObject.java new file mode 100644 index 000000000..24b3f949e --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/GraphicsObject.java @@ -0,0 +1,385 @@ +/* + * 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.afp.modca; + +import java.awt.Color; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.List; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.Completable; +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.StructuredData; +import org.apache.fop.afp.goca.GraphicsAreaBegin; +import org.apache.fop.afp.goca.GraphicsAreaEnd; +import org.apache.fop.afp.goca.GraphicsBox; +import org.apache.fop.afp.goca.GraphicsChainedSegment; +import org.apache.fop.afp.goca.GraphicsCharacterString; +import org.apache.fop.afp.goca.GraphicsData; +import org.apache.fop.afp.goca.GraphicsFillet; +import org.apache.fop.afp.goca.GraphicsFullArc; +import org.apache.fop.afp.goca.GraphicsImage; +import org.apache.fop.afp.goca.GraphicsLine; +import org.apache.fop.afp.goca.GraphicsSetArcParameters; +import org.apache.fop.afp.goca.GraphicsSetCharacterSet; +import org.apache.fop.afp.goca.GraphicsSetCurrentPosition; +import org.apache.fop.afp.goca.GraphicsSetLineType; +import org.apache.fop.afp.goca.GraphicsSetLineWidth; +import org.apache.fop.afp.goca.GraphicsSetPatternSymbol; +import org.apache.fop.afp.goca.GraphicsSetProcessColor; + +/** + * Top-level GOCA graphics object. + * + * Acts as container and factory of all other graphic objects + */ +public class GraphicsObject extends AbstractDataObject { + + /** the graphics data */ + private GraphicsData currentData = null; + + /** list of objects contained within this container */ + protected List/*<GraphicsData>*/ objects + = new java.util.ArrayList/*<GraphicsData>*/(); + + /** the graphics state */ + private final GraphicsState graphicsState = new GraphicsState(); + + /** + * Default constructor + * + * @param factory the object factory + * @param name the name of graphics object + */ + public GraphicsObject(Factory factory, String name) { + super(factory, name); + } + + /** {@inheritDoc} */ + public void setViewport(AFPDataObjectInfo dataObjectInfo) { + super.setViewport(dataObjectInfo); + + AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); + int width = objectAreaInfo.getWidth(); + int height = objectAreaInfo.getHeight(); + int widthRes = objectAreaInfo.getWidthRes(); + int heightRes = objectAreaInfo.getHeightRes(); + final int leftEdge = 0; + final int topEdge = 0; + GraphicsDataDescriptor graphicsDataDescriptor = factory.createGraphicsDataDescriptor( + leftEdge, width, topEdge, height, widthRes, heightRes); + + getObjectEnvironmentGroup().setDataDescriptor(graphicsDataDescriptor); + } + + /** {@inheritDoc} */ + public void addObject(StructuredData object) { + if (currentData == null) { + newData(); + } else if (currentData.getDataLength() + object.getDataLength() + >= GraphicsData.MAX_DATA_LEN) { + // graphics data full so transfer current incomplete segment to new data + GraphicsChainedSegment currentSegment + = (GraphicsChainedSegment)currentData.removeCurrentSegment(); + currentSegment.setName(newData().createSegmentName()); + currentData.addSegment(currentSegment); + } + currentData.addObject(object); + } + + /** + * Gets the current graphics data, creating a new one if necessary + * + * @return the current graphics data + */ + private GraphicsData getData() { + if (this.currentData == null) { + return newData(); + } + return this.currentData; + } + + /** + * Creates a new graphics data + * + * @return a newly created graphics data + */ + private GraphicsData newData() { + if (currentData != null) { + currentData.setComplete(true); + } + this.currentData = factory.createGraphicsData(); + objects.add(currentData); + return currentData; + } + + /** + * Sets the current color + * + * @param color the active color to use + */ + public void setColor(Color color) { + if (!color.equals(graphicsState.color)) { + addObject(new GraphicsSetProcessColor(color)); + graphicsState.color = color; + } + } + + /** + * Sets the current position + * + * @param coords the x and y coordinates of the current position + */ + public void setCurrentPosition(int[] coords) { + addObject(new GraphicsSetCurrentPosition(coords)); + } + + /** + * Sets the line width + * + * @param lineWidth the line width multiplier + */ + public void setLineWidth(int lineWidth) { + if (lineWidth != graphicsState.lineWidth) { + addObject(new GraphicsSetLineWidth(lineWidth)); + graphicsState.lineWidth = lineWidth; + } + } + + /** + * Sets the line type + * + * @param lineType the line type + */ + public void setLineType(byte lineType) { + if (lineType != graphicsState.lineType) { + addObject(new GraphicsSetLineType(lineType)); + graphicsState.lineType = lineType; + } + } + + /** + * Sets whether the following shape is to be filled + * + * @param fill true if the following shape is to be filled + */ + public void setFill(boolean fill) { + setPatternSymbol(fill ? + GraphicsSetPatternSymbol.SOLID_FILL : + GraphicsSetPatternSymbol.NO_FILL); + } + + /** + * Sets the fill pattern of the next shape + * + * @param the fill pattern of the next shape + */ + public void setPatternSymbol(byte patternSymbol) { + if (patternSymbol != graphicsState.patternSymbol) { + addObject(new GraphicsSetPatternSymbol(patternSymbol)); + graphicsState.patternSymbol = patternSymbol; + } + } + + /** + * Sets the character set to use + * + * @param characterSet the character set (font) reference + */ + public void setCharacterSet(int characterSet) { + if (characterSet != graphicsState.characterSet) { + addObject(new GraphicsSetCharacterSet(characterSet)); + graphicsState.characterSet = characterSet; + } + } + + /** + * Adds a line at the given x/y coordinates + * + * @param coords the x/y coordinates (can be a series) + */ + public void addLine(int[] coords) { + addLine(coords, false); + } + + /** + * Adds a line at the given x/y coordinates + * + * @param coords the x/y coordinates (can be a series) + * @param relative relative true for a line at current position (relative to) + */ + public void addLine(int[] coords, boolean relative) { + addObject(new GraphicsLine(coords, relative)); + } + + /** + * Adds a box at the given coordinates + * + * @param coords the x/y coordinates + */ + public void addBox(int[] coords) { + addObject(new GraphicsBox(coords)); + } + + /** + * Adds a fillet (curve) at the given coordinates + * + * @param coords the x/y coordinates + */ + public void addFillet(int[] coords) { + addFillet(coords, false); + } + + /** + * Adds a fillet (curve) at the given coordinates + * + * @param coords the x/y coordinates + * @param relative relative true for a fillet (curve) at current position (relative to) + */ + public void addFillet(int[] coords, boolean relative) { + addObject(new GraphicsFillet(coords, relative)); + } + + /** + * Sets the arc parameters + * + * @param xmaj the maximum value of the x coordinate + * @param ymin the minimum value of the y coordinate + * @param xmin the minimum value of the x coordinate + * @param ymaj the maximum value of the y coordinate + */ + public void setArcParams(int xmaj, int ymin, int xmin, int ymaj) { + addObject(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj)); + } + + /** + * Adds a full arc + * + * @param x the x coordinate + * @param y the y coordinate + * @param mh the integer portion of the multiplier + * @param mhr the fractional portion of the multiplier + */ + public void addFullArc(int x, int y, int mh, int mhr) { + addObject(new GraphicsFullArc(x, y, mh, mhr)); + } + + /** + * Adds an image + * + * @param x the x coordinate + * @param y the y coordinate + * @param width the image width + * @param height the image height + * @param imgData the image data + */ + public void addImage(int x, int y, int width, int height, byte[] imgData) { + addObject(new GraphicsImage(x, y, width, height, imgData)); + } + + /** + * Adds a string + * + * @param str the string + * @param x the x coordinate + * @param y the y coordinate + */ + public void addString(String str, int x, int y) { + addObject(new GraphicsCharacterString(str, x, y)); + } + + /** + * Begins a graphics area (start of fill) + */ + public void beginArea() { + addObject(new GraphicsAreaBegin()); + } + + /** + * Ends a graphics area (end of fill) + */ + public void endArea() { + addObject(new GraphicsAreaEnd()); + } + + /** {@inheritDoc} */ + public String toString() { + return "GraphicsObject: " + getName(); + } + + /** + * Creates a new graphics segment + */ + public void newSegment() { + getData().newSegment(); + } + + /** {@inheritDoc} */ + public void setComplete(boolean complete) { + Iterator it = objects.iterator(); + while (it.hasNext()) { + Completable completedObject = (Completable)it.next(); + completedObject.setComplete(true); + } + super.setComplete(complete); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.GRAPHICS); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + writeObjects(objects, os); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.GRAPHICS); + os.write(data); + } + + /** the internal graphics state */ + private class GraphicsState { + /** the current color */ + private Color color; + + /** the current line type */ + private byte lineType; + + /** the current line width */ + private int lineWidth; + + /** the current fill pattern */ + private byte patternSymbol; + + /** the current character set */ + private int characterSet; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java b/src/java/org/apache/fop/afp/modca/IMImageObject.java index bb43950dd..a09042441 100644 --- a/src/java/org/apache/fop/render/afp/modca/IMImageObject.java +++ b/src/java/org/apache/fop/afp/modca/IMImageObject.java @@ -17,11 +17,16 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; +import org.apache.fop.afp.ioca.ImageCellPosition; +import org.apache.fop.afp.ioca.ImageInputDescriptor; +import org.apache.fop.afp.ioca.ImageOutputControl; +import org.apache.fop.afp.ioca.ImageRasterData; + /** * An IM image data object specifies the contents of a raster image and * its placement on a page, overlay, or page segment. An IM image can be @@ -60,16 +65,16 @@ public class IMImageObject extends AbstractNamedAFPObject { /** * Constructor for the image object with the specified name, * the name must be a fixed length of eight characters. + * * @param name The name of the image. */ public IMImageObject(String name) { - super(name); - } /** * Sets the ImageOutputControl. + * * @param imageOutputControl The imageOutputControl to set */ public void setImageOutputControl(ImageOutputControl imageOutputControl) { @@ -78,6 +83,7 @@ public class IMImageObject extends AbstractNamedAFPObject { /** * Sets the ImageCellPosition. + * * @param imageCellPosition The imageCellPosition to set */ public void setImageCellPosition(ImageCellPosition imageCellPosition) { @@ -86,6 +92,7 @@ public class IMImageObject extends AbstractNamedAFPObject { /** * Sets the ImageInputDescriptor. + * * @param imageInputDescriptor The imageInputDescriptor to set */ public void setImageInputDescriptor(ImageInputDescriptor imageInputDescriptor) { @@ -94,98 +101,41 @@ public class IMImageObject extends AbstractNamedAFPObject { /** * Sets the ImageRastorData. + * * @param imageRasterData The imageRasterData to set */ public void setImageRasterData(ImageRasterData imageRasterData) { this.imageRasterData = imageRasterData; } - /** - * Accessor method to write the AFP datastream for the IM Image Objetc - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); if (imageOutputControl != null) { - imageOutputControl.writeDataStream(os); + imageOutputControl.writeToStream(os); } - if (imageInputDescriptor != null) { - imageInputDescriptor.writeDataStream(os); + imageInputDescriptor.writeToStream(os); } - if (imageCellPosition != null) { - imageCellPosition.writeDataStream(os); + imageCellPosition.writeToStream(os); } - if (imageRasterData != null) { - imageRasterData.writeDataStream(os); + imageRasterData.writeToStream(os); } - - writeEnd(os); - } - /** - * Helper method to write the start of the IM Image Object. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0x7B; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - + copySF(data, Type.BEGIN, Category.IM_IMAGE); os.write(data); - } - /** - * Helper method to write the end of the IM Image Object. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0x7B; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - + copySF(data, Type.END, Category.IM_IMAGE); os.write(data); - } - } diff --git a/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java new file mode 100644 index 000000000..07976e18a --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ImageDataDescriptor.java @@ -0,0 +1,78 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * ImageDataDescriptor + */ +public class ImageDataDescriptor extends AbstractDescriptor { + + /** + * Constructor for a ImageDataDescriptor for the specified + * resolution, width and height. + * + * @param width The width of the image. + * @param height The height of the height. + * @param widthRes The horizontal resolution of the image. + * @param heightRes The vertical resolution of the image. + */ + public ImageDataDescriptor(int width, int height, int widthRes, int heightRes) { + super(width, height, widthRes, heightRes); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[22]; + copySF(data, Type.DESCRIPTOR, Category.IMAGE); + + // SF length + byte[] len = BinaryUtils.convert(data.length - 1, 2); + data[1] = len[0]; + data[2] = len[1]; + + byte[] x = BinaryUtils.convert(widthRes, 2); + data[10] = x[0]; + data[11] = x[1]; + + byte[] y = BinaryUtils.convert(heightRes, 2); + data[12] = y[0]; + data[13] = y[1]; + + byte[] w = BinaryUtils.convert(width, 2); + data[14] = w[0]; + data[15] = w[1]; + + byte[] h = BinaryUtils.convert(height, 2); + data[16] = h[0]; + data[17] = h[1]; + + data[18] = (byte)0xF7; // ID = Set IOCA Function Set + data[19] = 0x02; // Length + data[20] = 0x01; // Category = Function set identifier + data[21] = 0x0B; // FCNSET = IOCA FS 11 + + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/ImageObject.java b/src/java/org/apache/fop/afp/modca/ImageObject.java new file mode 100644 index 000000000..24ac0cb22 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ImageObject.java @@ -0,0 +1,155 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPImageObjectInfo; +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.ioca.ImageSegment; + +/** + * An IOCA Image Data Object + */ +public class ImageObject extends AbstractDataObject { + + private static final int MAX_DATA_LEN = 32759; + + /** the image segment */ + private ImageSegment imageSegment = null; + + /** + * Constructor for the image object with the specified name, + * the name must be a fixed length of eight characters. + * + * @param name The name of the image. + * @param factory the resource manager + */ + public ImageObject(Factory factory, String name) { + super(factory, name); + } + + private ImageSegment getImageSegment() { + if (imageSegment == null) { + this.imageSegment = factory.createImageSegment(); + } + return imageSegment; + } + + /** {@inheritDoc} */ + public void setViewport(AFPDataObjectInfo dataObjectInfo) { + super.setViewport(dataObjectInfo); + + AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)dataObjectInfo; + int dataWidth = imageObjectInfo.getDataWidth(); + int dataHeight = imageObjectInfo.getDataHeight(); + +// AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); +// int widthRes = objectAreaInfo.getWidthRes(); +// int heightRes = objectAreaInfo.getHeightRes(); + + int dataWidthRes = imageObjectInfo.getDataWidthRes(); + int dataHeightRes = imageObjectInfo.getDataWidthRes(); + ImageDataDescriptor imageDataDescriptor + = factory.createImageDataDescriptor(dataWidth, dataHeight, dataWidthRes, dataHeightRes); + getObjectEnvironmentGroup().setDataDescriptor(imageDataDescriptor); + + getImageSegment().setImageSize(dataWidth, dataHeight, dataWidthRes, dataHeightRes); + } + + /** + * Sets the image encoding. + * + * @param encoding The image encoding. + */ + public void setEncoding(byte encoding) { + getImageSegment().setEncoding(encoding); + } + + /** + * Sets the image compression. + * + * @param compression The image compression. + */ + public void setCompression(byte compression) { + getImageSegment().setCompression(compression); + } + + /** + * Sets the image IDE size. + * + * @param size The IDE size. + */ + public void setIDESize(byte size) { + getImageSegment().setIDESize(size); + } + + /** + * Sets the image IDE color model. + * + * @param colorModel the IDE color model. + */ + public void setIDEColorModel(byte colorModel) { + getImageSegment().setIDEColorModel(colorModel); + } + + /** + * Set the data of the image. + * + * @param data the image data + */ + public void setData(byte[] imageData) { + getImageSegment().setData(imageData); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.IMAGE); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + + if (imageSegment != null) { + final byte[] dataHeader = new byte[9]; + copySF(dataHeader, SF_CLASS, Type.DATA, Category.IMAGE); + final int lengthOffset = 1; + + // TODO save memory! + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + imageSegment.writeToStream(baos); + byte[] data = baos.toByteArray(); + writeChunksToStream(data, dataHeader, lengthOffset, MAX_DATA_LEN, os); + } + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.IMAGE); + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/IncludeObject.java b/src/java/org/apache/fop/afp/modca/IncludeObject.java new file mode 100644 index 000000000..2dff6bd87 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/IncludeObject.java @@ -0,0 +1,301 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.modca.triplets.MappingOptionTriplet; +import org.apache.fop.afp.modca.triplets.MeasurementUnitsTriplet; +import org.apache.fop.afp.modca.triplets.ObjectAreaSizeTriplet; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * An Include Object structured field references an object on a page or overlay. + * It optionally contains parameters that identify the object and that specify + * presentation parameters such as object position, size, orientation, mapping, + * and default color. + * <p> + * Where the presentation parameters conflict with parameters specified in the + * object's environment group (OEG), the parameters in the Include Object + * structured field override. If the referenced object is a page segment, the + * IOB parameters override the corresponding environment group parameters on all + * data objects in the page segment. + * </p> + */ +public class IncludeObject extends AbstractNamedAFPObject { + + /** the object referenced is of type page segment */ + public static final byte TYPE_PAGE_SEGMENT = (byte)0x5F; + + /** the object referenced is of type other */ + public static final byte TYPE_OTHER = (byte)0x92; + + /** the object referenced is of type graphic */ + public static final byte TYPE_GRAPHIC = (byte)0xBB; + + /** the object referenced is of type barcode */ + public static final byte TYPE_BARCODE = (byte)0xEB; + + /** the object referenced is of type image */ + public static final byte TYPE_IMAGE = (byte)0xFB; + + + /** the object type referenced (default is other) */ + private byte objectType = TYPE_OTHER; + + /** the X-axis origin of the object area */ + private int xoaOset = 0; + + /** the Y-axis origin of the object area */ + private int yoaOset = 0; + + /** the orientation of the referenced object */ + private int oaOrent = 0; + + /** the X-axis origin defined in the object */ + private int xocaOset = -1; + + /** the Y-axis origin defined in the object */ + private int yocaOset = -1; + + /** + * Constructor for the include object with the specified name, the name must + * be a fixed length of eight characters and is the name of the referenced + * object. + * + * @param name the name of this include object + */ + public IncludeObject(String name) { + super(name); + } + + /** + * Sets the orientation to use for the Include Object. + * + * @param orientation + * The orientation (0,90, 180, 270) + */ + public void setObjectAreaOrientation(int orientation) { + if (orientation == 0 || orientation == 90 || orientation == 180 + || orientation == 270) { + this.oaOrent = orientation; + } else { + throw new IllegalArgumentException( + "The orientation must be one of the values 0, 90, 180, 270"); + } + } + + /** + * Sets the x and y offset to the origin in the object area + * + * @param x the X-axis origin of the object area + * @param y the Y-axis origin of the object area + */ + public void setObjectAreaOffset(int x, int y) { + this.xoaOset = x; + this.yoaOset = y; + } + + /** + * Sets the x and y offset of the content area to the object area + * used in conjunction with the {@link MappingOptionTriplet.POSITION} and + * {@link MappingOptionTriplet.POSITION_AND_TRIM}. + * + * @param x the X-axis origin defined in the object + * @param y the Y-axis origin defined in the object + */ + public void setContentAreaOffset(int x, int y) { + this.xocaOset = x; + this.yocaOset = y; + } + + /** + * Sets the data object type + * + * @param type the data object type + */ + public void setObjectType(byte type) { + this.objectType = type; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[36]; + super.copySF(data, Type.INCLUDE, Category.DATA_RESOURCE); + + // Set the total record length + int tripletDataLength = getTripletDataLength(); + byte[] len = BinaryUtils.convert(35 + tripletDataLength, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; + + data[17] = 0x00; // reserved + data[18] = objectType; + + //XoaOset (object area) + if (xoaOset > -1) { + byte[] x = BinaryUtils.convert(xoaOset, 3); + data[19] = x[0]; + data[20] = x[1]; + data[21] = x[2]; + } else { + data[19] = (byte)0xFF; + data[20] = (byte)0xFF; + data[21] = (byte)0xFF; + } + + // YoaOset (object area) + if (yoaOset > -1) { + byte[] y = BinaryUtils.convert(yoaOset, 3); + data[22] = y[0]; + data[23] = y[1]; + data[24] = y[2]; + } else { + data[22] = (byte)0xFF; + data[23] = (byte)0xFF; + data[24] = (byte)0xFF; + } + + // XoaOrent/YoaOrent + switch (oaOrent) { + case -1: // use x/y axis orientation defined in object + data[25] = (byte)0xFF; // x axis rotation + data[26] = (byte)0xFF; // + data[27] = (byte)0xFF; // y axis rotation + data[28] = (byte)0xFF; + break; + case 90: + data[25] = 0x2D; + data[26] = 0x00; + data[27] = 0x5A; + data[28] = 0x00; + break; + case 180: + data[25] = 0x5A; + data[25] = 0x00; + data[27] = (byte)0x87; + data[28] = 0x00; + break; + case 270: + data[25] = (byte)0x87; + data[26] = 0x00; + data[27] = 0x00; + data[28] = 0x00; + break; + default: // 0 degrees + data[25] = 0x00; + data[26] = 0x00; + data[27] = 0x2D; + data[28] = 0x00; + break; + } + + // XocaOset (object content) + if (xocaOset > -1) { + byte[] x = BinaryUtils.convert(xocaOset, 3); + data[29] = x[0]; + data[30] = x[1]; + data[31] = x[2]; + } else { + data[29] = (byte)0xFF; + data[30] = (byte)0xFF; + data[31] = (byte)0xFF; + } + + // YocaOset (object content) + if (yocaOset > -1) { + byte[] y = BinaryUtils.convert(yocaOset, 3); + data[32] = y[0]; + data[33] = y[1]; + data[34] = y[2]; + } else { + data[32] = (byte)0xFF; + data[33] = (byte)0xFF; + data[34] = (byte)0xFF; + } + // RefCSys (Reference coordinate system) + data[35] = 0x01; // Page or overlay coordinate system + + // Write structured field data + os.write(data); + + // Write triplet for FQN internal/external object reference + writeTriplets(os); + } + + private String getObjectTypeName() { + String objectTypeName = null; + if (objectType == TYPE_PAGE_SEGMENT) { + objectTypeName = "page segment"; + } else if (objectType == TYPE_OTHER) { + objectTypeName = "other"; + } else if (objectType == TYPE_GRAPHIC) { + objectTypeName = "graphic"; + } else if (objectType == TYPE_BARCODE) { + objectTypeName = "barcode"; + } else if (objectType == TYPE_IMAGE) { + objectTypeName = "image"; + } + return objectTypeName; + } + + /** {@inheritDoc} */ + public String toString() { + return "IncludeObject{name=" + this.getName() + + ", objectType=" + getObjectTypeName() + + ", xoaOset=" + xoaOset + + ", yoaOset=" + yoaOset + + ", oaOrent" + oaOrent + + ", xocaOset=" + xocaOset + + ", yocaOset=" + yocaOset + + "}"; + } + + /** + * Sets the mapping option + * + * @param optionValue the mapping option value + */ + public void setMappingOption(byte optionValue) { + addTriplet(new MappingOptionTriplet(optionValue)); + } + + /** + * Sets the extent of an object area in the X and Y directions + * + * @param x the x direction extent + * @param y the y direction extent + */ + public void setObjectAreaSize(int x, int y) { + addTriplet(new ObjectAreaSizeTriplet(x, y)); + } + + /** + * Sets the measurement units used to specify the units of measure + * + * @param xRes units per base on the x-axis + * @param yRes units per base on the y-axis + */ + public void setMeasurementUnits(int xRes, int yRes) { + addTriplet(new MeasurementUnitsTriplet(xRes, xRes)); + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java b/src/java/org/apache/fop/afp/modca/IncludePageOverlay.java index 7c52fe0a2..44f0edc5b 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageOverlay.java +++ b/src/java/org/apache/fop/afp/modca/IncludePageOverlay.java @@ -17,12 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.util.BinaryUtils; /** * @@ -56,6 +56,7 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { /** * Constructor for the Include Page Overlay + * * @param overlayName Name of the page segment * @param x The x position * @param y The y position @@ -63,13 +64,14 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { */ public IncludePageOverlay(String overlayName, int x, int y, int orientation) { super(overlayName); + this.x = x; this.y = y; setOrientation(orientation); } /** - * Sets the orienation to use for the overlay. + * Sets the orientation to use for the overlay. * * @param orientation * The orientation (0,90, 180, 270) @@ -84,45 +86,25 @@ public class IncludePageOverlay extends AbstractNamedAFPObject { } } - /** - * Accessor method to write the AFP datastream for the Include Page Overlay - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[25]; //(9 +16) - - data[0] = 0x5A; + copySF(data, Type.INCLUDE, Category.PAGE_OVERLAY); // Set the total record length byte[] len = BinaryUtils.convert(24, 2); //Ignore first byte data[1] = len[0]; data[2] = len[1]; - // Structured field ID for a IPO - data[3] = (byte) 0xD3; - data[4] = (byte) 0xAF; - data[5] = (byte) 0xD8; - - data[6] = 0x00; // Reserved - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - - byte[] xcoord = BinaryUtils.convert(x, 3); - data[17] = xcoord[0]; // x coordinate - data[18] = xcoord[1]; - data[19] = xcoord[2]; + byte[] xPos = BinaryUtils.convert(x, 3); + data[17] = xPos[0]; // x coordinate + data[18] = xPos[1]; + data[19] = xPos[2]; - byte[] ycoord = BinaryUtils.convert(y, 3); - data[20] = ycoord[0]; // y coordinate - data[21] = ycoord[1]; - data[22] = ycoord[2]; + byte[] yPos = BinaryUtils.convert(y, 3); + data[20] = yPos[0]; // y coordinate + data[21] = yPos[1]; + data[22] = yPos[2]; switch (orientation) { case 90: diff --git a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java b/src/java/org/apache/fop/afp/modca/IncludePageSegment.java index 7792a7162..7355e3b1a 100644 --- a/src/java/org/apache/fop/render/afp/modca/IncludePageSegment.java +++ b/src/java/org/apache/fop/afp/modca/IncludePageSegment.java @@ -17,12 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.util.BinaryUtils; /** * The Include Page Segment structured field references a page segment resource @@ -45,64 +45,46 @@ public class IncludePageSegment extends AbstractNamedAFPObject { /** * The x position where we need to put this object on the page */ - private byte[] x; - + private int x; + /** * The y position where we need to put this object on the page */ - private byte[] y; - + private int y; + /** * Constructor for the Include Page Segment + * * @param name Name of the page segment * @param x The x position * @param y The y position */ public IncludePageSegment(String name, int x, int y) { - super(name); - this.x = BinaryUtils.convert(x, 3); - this.y = BinaryUtils.convert(y, 3); - + + this.x = x; + this.y = y; } - /** - * Accessor method to write the AFP datastream for the Include Page Segment - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[23]; //(9 +14) - - data[0] = 0x5A; + copySF(data, Type.INCLUDE, Category.PAGE_SEGMENT); // Set the total record length - byte[] rl1 = BinaryUtils.convert(22, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; - - // Structured field ID for a IPS - data[3] = (byte) 0xD3; - data[4] = (byte) 0xAF; - data[5] = (byte) 0x5F; - - data[6] = 0x00; // Reserved - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - - data[17] = x[0]; // x coordinate - data[18] = x[1]; - data[19] = x[2]; - - data[20] = y[0]; // y coordinate - data[21] = y[1]; - data[22] = y[2]; + byte[] len = BinaryUtils.convert(22, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; + + byte[] xPos = BinaryUtils.convert(x, 3); + data[17] = xPos[0]; // x coordinate + data[18] = xPos[1]; + data[19] = xPos[2]; + + byte[] yPos = BinaryUtils.convert(y, 3); + data[20] = yPos[0]; // y coordinate + data[21] = yPos[1]; + data[22] = yPos[2]; os.write(data); } diff --git a/src/java/org/apache/fop/afp/modca/InterchangeSet.java b/src/java/org/apache/fop/afp/modca/InterchangeSet.java new file mode 100644 index 000000000..28a4da42b --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/InterchangeSet.java @@ -0,0 +1,115 @@ +/* + * 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.afp.modca; + +/** + * MO:DCA Interchange Set + */ +public class InterchangeSet { + /** interchange set 1 string value */ + public static final String MODCA_PRESENTATION_INTERCHANGE_SET_1 = "MO:DCA-P IS/1"; + + /** interchange set 2 string value */ + public static final String MODCA_PRESENTATION_INTERCHANGE_SET_2 = "MO:DCA-P IS/2"; + + /** resource interchange set string value */ + public static final String MODCA_RESOURCE_INTERCHANGE_SET = "MO:DCA-L"; + + private static final String[] NAMES = { + MODCA_PRESENTATION_INTERCHANGE_SET_1, + MODCA_PRESENTATION_INTERCHANGE_SET_2, + MODCA_RESOURCE_INTERCHANGE_SET + }; + + private static final int SET_1 = 0; + private static final int SET_2 = 1; + private static final int RESOURCE_SET = 2; + + /** the actual interchange set in use */ + private int value; + + /** + * Returns the interchange set value of a given string + * + * @param str an interchange set value + * @return an interchange set + */ + public static InterchangeSet valueOf(String str) { + if (MODCA_PRESENTATION_INTERCHANGE_SET_1.equals(str)) { + return new InterchangeSet(SET_1); + } else if (MODCA_PRESENTATION_INTERCHANGE_SET_2.equals(str)) { + return new InterchangeSet(SET_2); + } else if (MODCA_RESOURCE_INTERCHANGE_SET.equals(str)) { + return new InterchangeSet(RESOURCE_SET); + } else { + throw new IllegalArgumentException("Invalid MO:DCA interchange set :" + str); + } + } + + /** + * Main constructor + * + * @param value the interchange set value + */ + public InterchangeSet(int value) { + this.value = value; + } + + /** + * Returns true if complies with MOD:CA interchange set 1 + * + * @return true if complies with MOD:CA interchange set 1 + */ + protected boolean is1() { + return value == SET_1; + } + + /** + * Returns true if complies with MOD:CA interchange set 2 + * + * @return true if complies with MOD:CA interchange set 2 + */ + public boolean is2() { + return value == SET_2; + } + + /** + * Returns true if complies with MOD:CA resource set + * + * @return true if complies with MOD:CA resource set + */ + public boolean isResource() { + return value == RESOURCE_SET; + } + + /** {@inheritDoc} */ + public String toString() { + return NAMES[value]; + } + + /** + * Returns true if MOD:CA interchange set 2 (resource groups) is supported + * + * @return true if MOD:CA interchange set 2 (resource groups) is supported + */ + public boolean supportsLevel2() { + return is2() || isResource(); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java b/src/java/org/apache/fop/afp/modca/InvokeMediumMap.java index f38096ade..f910a0b9c 100644 --- a/src/java/org/apache/fop/render/afp/modca/InvokeMediumMap.java +++ b/src/java/org/apache/fop/afp/modca/InvokeMediumMap.java @@ -17,12 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.util.BinaryUtils; /** * The Invoke Medium Map structured field identifies the Medium Map that is to @@ -34,48 +34,24 @@ public class InvokeMediumMap extends AbstractNamedAFPObject { /** * Constructor for the Invoke Medium Map - * @param mediumMapName Name of the medium map + * + * @param name the name of the medium map */ - public InvokeMediumMap(String mediumMapName) { - - super(mediumMapName); - + public InvokeMediumMap(String name) { + super(name); } - /** - * Accessor method to write the AFP datastream for the Invoke Medium Map - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[17]; - - data[0] = 0x5A; + copySF(data, Type.MAP, Category.MEDIUM_MAP); // Set the total record length - byte[] rl1 = BinaryUtils.convert(16, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; - - // Structured field ID for a IPO - data[3] = (byte) 0xD3; - data[4] = (byte) 0xAB; - data[5] = (byte) 0xCC; - - data[6] = 0x00; // Reserved - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } + byte[] len = BinaryUtils.convert(16, 2); //Ignore first byte + data[1] = len[0]; + data[2] = len[1]; os.write(data); - } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java b/src/java/org/apache/fop/afp/modca/MapCodedFont.java index f0f372fcb..54b4d1796 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapCodedFont.java +++ b/src/java/org/apache/fop/afp/modca/MapCodedFont.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -26,12 +26,13 @@ import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.List; -import org.apache.fop.render.afp.exceptions.FontRuntimeException; -import org.apache.fop.render.afp.fonts.AFPFont; -import org.apache.fop.render.afp.fonts.CharacterSet; -import org.apache.fop.render.afp.fonts.OutlineFont; -import org.apache.fop.render.afp.fonts.RasterFont; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.fonts.AFPFont; +import org.apache.fop.afp.fonts.CharacterSet; +import org.apache.fop.afp.fonts.FontRuntimeException; +import org.apache.fop.afp.fonts.OutlineFont; +import org.apache.fop.afp.fonts.RasterFont; +import org.apache.fop.afp.util.BinaryUtils; /** * The Map Coded Font structured field maps a unique coded font resource local @@ -39,46 +40,29 @@ import org.apache.fop.render.afp.tools.BinaryUtils; * descriptor, to the identifier of a coded font resource object. Additionally, * the Map Coded Font structured field specifies a set of resource attributes * for the coded font. - * - * @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a> */ -public class MapCodedFont extends AbstractAFPObject { +public class MapCodedFont extends AbstractStructuredObject { - /** - * The collection of map coded fonts (maximum of 254) - */ - private List fontList = null; + /** the collection of map coded fonts (maximum of 254) */ + private final List/*<FontDefinition>*/ fontList + = new java.util.ArrayList/*<FontDefinition>*/(); /** - * Constructor for the MapCodedFont + * Main constructor */ public MapCodedFont() { - - fontList = new java.util.ArrayList(); - } - /** - * Accessor method to write the AFP datastream for the Map Coded Font - * @param os The stream to write to - * @throws java.io.IOException an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) throws IOException { - + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write(0x5A); - baos.write(new byte[] {0x00, 0x00}); - - // Field identifier for a MapCodedFont - baos.write(new byte[] {(byte) 0xD3, (byte) 0xAB, (byte) 0x8A}); - - // Reserved - baos.write(new byte[] {0x00, 0x00, 0x00}); + byte[] startData = new byte[9]; + copySF(startData, Type.MAP, Category.CODED_FONT); + baos.write(startData); Iterator iter = fontList.iterator(); while (iter.hasNext()) { - FontDefinition fd = (FontDefinition) iter.next(); // Start of repeating groups (occurs 1 to 254) @@ -138,7 +122,6 @@ public class MapCodedFont extends AbstractAFPObject { baos.write(0x5D); baos.write(BinaryUtils.convert(fd.scale, 2)); } - } byte[] data = baos.toByteArray(); @@ -149,7 +132,6 @@ public class MapCodedFont extends AbstractAFPObject { data[2] = rl1[1]; os.write(data); - } /** @@ -168,29 +150,27 @@ public class MapCodedFont extends AbstractAFPObject { public void addFont(int fontReference, AFPFont font, int size, int orientation) throws MaximumSizeExceededException { - FontDefinition fd = new FontDefinition(); + FontDefinition fontDefinition = new FontDefinition(); - fd.fontReferenceKey = BinaryUtils.convert(fontReference)[0]; + fontDefinition.fontReferenceKey = BinaryUtils.convert(fontReference)[0]; switch (orientation) { case 90: - fd.orientation = 0x2D; + fontDefinition.orientation = 0x2D; break; case 180: - fd.orientation = 0x5A; + fontDefinition.orientation = 0x5A; break; case 270: - fd.orientation = (byte) 0x87; + fontDefinition.orientation = (byte) 0x87; break; default: - fd.orientation = 0x00; + fontDefinition.orientation = 0x00; break; } try { - if (font instanceof RasterFont) { - RasterFont raster = (RasterFont) font; CharacterSet cs = raster.getCharacterSet(size); if (cs == null) { @@ -200,45 +180,43 @@ public class MapCodedFont extends AbstractAFPObject { throw new FontRuntimeException(msg); } - fd.characterSet = cs.getNameBytes(); + fontDefinition.characterSet = cs.getNameBytes(); - if (fd.characterSet.length != 8) { + if (fontDefinition.characterSet.length != 8) { throw new IllegalArgumentException("The character set " - + new String(fd.characterSet, + + new String(fontDefinition.characterSet, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } - fd.codePage = cs.getCodePage().getBytes( + fontDefinition.codePage = cs.getCodePage().getBytes( AFPConstants.EBCIDIC_ENCODING); - if (fd.codePage.length != 8) { + if (fontDefinition.codePage.length != 8) { throw new IllegalArgumentException("The code page " - + new String(fd.codePage, + + new String(fontDefinition.codePage, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } } else if (font instanceof OutlineFont) { - OutlineFont outline = (OutlineFont) font; CharacterSet cs = outline.getCharacterSet(); - fd.characterSet = cs.getNameBytes(); + fontDefinition.characterSet = cs.getNameBytes(); // There are approximately 72 points to 1 inch or 20 1440ths per point. - fd.scale = ((size / 1000) * 20); + fontDefinition.scale = ((size / 1000) * 20); - fd.codePage = cs.getCodePage().getBytes( + fontDefinition.codePage = cs.getCodePage().getBytes( AFPConstants.EBCIDIC_ENCODING); - if (fd.codePage.length != 8) { + if (fontDefinition.codePage.length != 8) { throw new IllegalArgumentException("The code page " - + new String(fd.codePage, + + new String(fontDefinition.codePage, AFPConstants.EBCIDIC_ENCODING) + " must have a fixed length of 8 characters."); } - } else { String msg = "Font of type " + font.getClass().getName() + " not recognized."; @@ -247,22 +225,19 @@ public class MapCodedFont extends AbstractAFPObject { } if (fontList.size() > 253) { - // Throw an exception if the size is exceeded throw new MaximumSizeExceededException(); - } else { - fontList.add(fd); + fontList.add(fontDefinition); } } catch (UnsupportedEncodingException ex) { - throw new FontRuntimeException("Failed to create font " + " due to a UnsupportedEncodingException", ex); - } } + /** * Private utility class used as a container for font attributes */ @@ -292,7 +267,6 @@ public class MapCodedFont extends AbstractAFPObject { * The scale (only specified for outline fonts) */ private int scale = 0; - } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/afp/modca/MapContainerData.java b/src/java/org/apache/fop/afp/modca/MapContainerData.java new file mode 100644 index 000000000..8411592aa --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/MapContainerData.java @@ -0,0 +1,59 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.modca.triplets.MappingOptionTriplet; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Map Container Data structured field specifies how a presentation data object + * that is carried in an Object Container is mapped into its object area. + */ +public class MapContainerData extends AbstractTripletStructuredObject { + + /** + * Main constructor + * + * @param optionValue the mapping option value + */ + public MapContainerData(byte optionValue) { + super.addTriplet(new MappingOptionTriplet(optionValue)); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[11]; + copySF(data, Type.MAP, Category.OBJECT_CONTAINER); + int tripletLen = getTripletDataLength(); + + byte[] len = BinaryUtils.convert(10 + tripletLen, 2); + data[1] = len[0]; + data[2] = len[1]; + + len = BinaryUtils.convert(2 + tripletLen, 2); + data[9] = len[0]; + data[10] = len[1]; + os.write(data); + writeTriplets(os); + } +} diff --git a/src/java/org/apache/fop/afp/modca/MapDataResource.java b/src/java/org/apache/fop/afp/modca/MapDataResource.java new file mode 100644 index 000000000..566f60ce5 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/MapDataResource.java @@ -0,0 +1,58 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Map Data Resource structured field specifies resources that are + * required for presentation. + */ +public class MapDataResource extends AbstractTripletStructuredObject { + + /** + * Main constructor + */ + public MapDataResource() { + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + super.writeStart(os); + byte[] data = new byte[11]; + copySF(data, Type.MAP, Category.DATA_RESOURCE); + + int tripletDataLen = getTripletDataLength(); + + byte[] len = BinaryUtils.convert(10 + tripletDataLen, 2); + data[1] = len[0]; + data[2] = len[1]; + + len = BinaryUtils.convert(2 + tripletDataLen, 2); + data[9] = len[0]; + data[10] = len[1]; + + os.write(data); + writeTriplets(os); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java b/src/java/org/apache/fop/afp/modca/MapPageOverlay.java index 129a3f5a1..9fd3c7059 100644 --- a/src/java/org/apache/fop/render/afp/modca/MapPageOverlay.java +++ b/src/java/org/apache/fop/afp/modca/MapPageOverlay.java @@ -17,14 +17,15 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.List; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.util.BinaryUtils; /** * The Map Page Overlay structured field maps a Resource Local ID to the name of @@ -33,18 +34,26 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class MapPageOverlay extends AbstractAFPObject { + private static final int MAX_SIZE = 253; + /** * The collection of overlays (maximum of 254 stored as byte[]) */ - private List overLays = new java.util.ArrayList(); + private List overLays = null; /** * Constructor for the Map Page Overlay */ public MapPageOverlay() { - } + private List getOverlays() { + if (overLays == null) { + this.overLays = new java.util.ArrayList(); + } + return this.overLays; + } + /** * Add an overlay to to the map page overlay object. * @@ -53,36 +62,28 @@ public class MapPageOverlay extends AbstractAFPObject { * @throws MaximumSizeExceededException if the maximum size is reached */ public void addOverlay(String name) throws MaximumSizeExceededException { - - if (overLays.size() > 253) { + if (getOverlays().size() > MAX_SIZE) { throw new MaximumSizeExceededException(); } - if (name.length() != 8) { throw new IllegalArgumentException("The name of overlay " + name + " must be 8 characters"); } - if (log.isDebugEnabled()) { log.debug("addOverlay():: adding overlay " + name); } - try { byte[] data = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - overLays.add(data); + getOverlays().add(data); } catch (UnsupportedEncodingException usee) { log.error("addOverlay():: UnsupportedEncodingException translating the name " + name); } } - /** - * Accessor method to write the AFP datastream for the Map Page Overlay - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred - */ - public void writeDataStream(OutputStream os) throws IOException { - int oLayCount = overLays.size(); + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + int oLayCount = getOverlays().size(); int recordlength = oLayCount * 18; byte[] data = new byte[recordlength + 9]; @@ -98,8 +99,8 @@ public class MapPageOverlay extends AbstractAFPObject { // Structured field ID for a MPO data[3] = (byte) 0xD3; - data[4] = (byte) 0xAB; - data[5] = (byte) 0xD8; + data[4] = (byte) Type.MAP; + data[5] = (byte) Category.PAGE_OVERLAY; data[6] = 0x00; // Reserved data[7] = 0x00; // Reserved diff --git a/src/java/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java b/src/java/org/apache/fop/afp/modca/MaximumSizeExceededException.java index a66fa9b30..6d1c74156 100644 --- a/src/java/org/apache/fop/render/afp/modca/MaximumSizeExceededException.java +++ b/src/java/org/apache/fop/afp/modca/MaximumSizeExceededException.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; /** * An exception to handle maximum sizes being exceeded. diff --git a/src/java/org/apache/fop/render/afp/modca/NoOperation.java b/src/java/org/apache/fop/afp/modca/NoOperation.java index 54515a070..cb5841346 100644 --- a/src/java/org/apache/fop/render/afp/modca/NoOperation.java +++ b/src/java/org/apache/fop/afp/modca/NoOperation.java @@ -17,12 +17,13 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.util.BinaryUtils; /** * The No Operation structured field may be used to carry comments @@ -60,7 +61,7 @@ public class NoOperation extends AbstractAFPObject { * @param os The outputsteam stream * @throws java.io.IOException if an I/O exception occurs during processing */ - public void writeDataStream(OutputStream os) throws IOException { + public void writeToStream(OutputStream os) throws IOException { byte[] contentData = content.getBytes(AFPConstants.EBCIDIC_ENCODING); int contentLen = contentData.length; diff --git a/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java new file mode 100644 index 000000000..25323b864 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ObjectAreaDescriptor.java @@ -0,0 +1,72 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.modca.triplets.DescriptorPositionTriplet; +import org.apache.fop.afp.modca.triplets.MeasurementUnitsTriplet; +import org.apache.fop.afp.modca.triplets.ObjectAreaSizeTriplet; +import org.apache.fop.afp.modca.triplets.PresentationSpaceResetMixingTriplet; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Object Area Descriptor structured field specifies the size and attributes + * of an object area presentation space. + */ +public class ObjectAreaDescriptor extends AbstractDescriptor { + + /** + * Construct an object area descriptor for the specified object width + * and object height. + * + * @param width the object width. + * @param height the object height. + * @param widthRes the object width resolution. + * @param heightRes the object height resolution. + */ + public ObjectAreaDescriptor(int width, int height, int widthRes, int heightRes) { + super(width, height, widthRes, heightRes); + } + + private static final byte OBJECT_AREA_POSITION_ID = 0x01; + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[9]; + copySF(data, Type.DESCRIPTOR, Category.OBJECT_AREA); + + addTriplet(new DescriptorPositionTriplet(OBJECT_AREA_POSITION_ID)); + addTriplet(new MeasurementUnitsTriplet(widthRes, heightRes)); + addTriplet(new ObjectAreaSizeTriplet(width, height)); + addTriplet(new PresentationSpaceResetMixingTriplet( + PresentationSpaceResetMixingTriplet.NOT_RESET)); + + int tripletDataLength = getTripletDataLength(); + byte[] len = BinaryUtils.convert(data.length + tripletDataLength - 1, 2); + data[1] = len[0]; // Length + data[2] = len[1]; + os.write(data); + + writeTriplets(os); + } + +} diff --git a/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java new file mode 100644 index 000000000..3929c1196 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ObjectAreaPosition.java @@ -0,0 +1,112 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Object Area Position structured field specifies the origin and + * orientation of the object area, and the origin and orientation of the + * object content within the object area. + */ +public class ObjectAreaPosition extends AbstractAFPObject { + + private final int x; + private final int y; + private final int rotation; + private int xOffset; + private int yOffset; + + /** + * Construct an object area position for the specified object y, y position. + * + * @param x The x coordinate. + * @param y The y coordinate. + * @param rotation The coordinate system rotation (must be 0, 90, 180, 270). + */ + public ObjectAreaPosition(int x, int y, int rotation) { + this.x = x; + this.y = y; + this.rotation = rotation; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[33]; + copySF(data, Type.POSITION, Category.OBJECT_AREA); + + byte[] len = BinaryUtils.convert(32, 2); + data[1] = len[0]; // Length + data[2] = len[1]; + + data[9] = 0x01; // OAPosID = 1 + data[10] = 0x17; // RGLength = 23 + + byte[] xcoord = BinaryUtils.convert(x, 3); + data[11] = xcoord[0]; // XoaOSet + data[12] = xcoord[1]; + data[13] = xcoord[2]; + + byte[] ycoord = BinaryUtils.convert(y, 3); + data[14] = ycoord[0]; // YoaOSet + data[15] = ycoord[1]; + data[16] = ycoord[2]; + + byte xorient = (byte)(rotation / 2); + data[17] = xorient; // XoaOrent + + byte yorient = (byte)(rotation / 2 + 45); + data[19] = yorient; // YoaOrent + + byte[] xoffset = BinaryUtils.convert(xOffset, 3); + data[22] = xoffset[0]; // XocaOSet + data[23] = xoffset[1]; + data[24] = xoffset[2]; + + byte[] yoffset = BinaryUtils.convert(yOffset, 3); + data[25] = yoffset[0]; // YocaOSet + data[26] = yoffset[1]; + data[27] = yoffset[2]; + + data[28] = 0x00; // XocaOrent + data[29] = 0x00; + + data[30] = 0x2D; // YocaOrent + data[31] = 0x00; + + data[32] = 0x01; // RefCSys + + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return "ObjectAreaPosition{" + + "x=" + x + + ", y=" + y + + ", rotation=" + rotation + + ", rotation=" + rotation + + ", xOffset=" + xOffset + + ", yOffset=" + yOffset; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/afp/modca/ObjectContainer.java new file mode 100644 index 000000000..39b935d01 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ObjectContainer.java @@ -0,0 +1,123 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceLevel; +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.modca.triplets.MappingOptionTriplet; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * Object containers are MO:DCA objects that envelop and carry object data. + */ +public class ObjectContainer extends AbstractDataObject { + + /** the object container data maximum length */ + private static final int MAX_DATA_LEN = 32759; + + private byte[] data; + + /** + * Main constructor + * + * @param factory the object factory + * @param name the name of this object container + */ + public ObjectContainer(Factory factory, String name) { + super(factory, name); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] headerData = new byte[17]; + copySF(headerData, Type.BEGIN, Category.OBJECT_CONTAINER); + + // Set the total record length + int containerLen = headerData.length + getTripletDataLength() - 1; + byte[] len = BinaryUtils.convert(containerLen, 2); + headerData[1] = len[0]; // Length byte 1 + headerData[2] = len[1]; // Length byte 2 + + os.write(headerData); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); // write triplets and OEG + + // write OCDs + byte[] dataHeader = new byte[9]; + copySF(dataHeader, SF_CLASS, Type.DATA, Category.OBJECT_CONTAINER); + final int lengthOffset = 1; + + if (data != null) { + writeChunksToStream(data, dataHeader, lengthOffset, MAX_DATA_LEN, os); + } + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.OBJECT_CONTAINER); + os.write(data); + } + + /** {@inheritDoc} */ + public void setViewport(AFPDataObjectInfo dataObjectInfo) { + AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo(); + AFPResourceLevel resourceLevel = resourceInfo.getLevel(); + + // only need to set MCD and CDD when OC when is inlined (pre-2000 apps) + if (resourceLevel.isInline()) { + super.setViewport(dataObjectInfo); + + MapContainerData mapContainerData + = factory.createMapContainerData(MappingOptionTriplet.SCALE_TO_FIT); + getObjectEnvironmentGroup().setMapContainerData(mapContainerData); + + int dataWidth = dataObjectInfo.getDataWidth(); + int dataHeight = dataObjectInfo.getDataHeight(); + + AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); + int widthRes = objectAreaInfo.getWidthRes(); + int heightRes = objectAreaInfo.getHeightRes(); + + ContainerDataDescriptor containerDataDescriptor + = factory.createContainerDataDescriptor( + dataWidth, dataHeight, widthRes, heightRes); + getObjectEnvironmentGroup().setDataDescriptor(containerDataDescriptor); + } + } + + /** + * Sets the inputstream for the the object container data + * + * @param inputStream the inputstream for the object container data + */ + public void setData(byte[] data) { + this.data = data; + } +} diff --git a/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java new file mode 100644 index 000000000..bc0cc5a63 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ObjectEnvironmentGroup.java @@ -0,0 +1,184 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * An Object Environment Group (OEG) may be associated with an object and is contained + * within the object's begin-end envelope. + * The object environment group defines the object's origin and orientation on the page, + * and can contain font and color attribute table information. The scope of an object + * environment group is the scope of its containing object. + * + * An application that creates a data-stream document may omit some of the parameters + * normally contained in the object environment group, or it may specify that one or + * more default values are to be used. + */ +public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject { + + /** the PresentationEnvironmentControl for the object environment group */ + private PresentationEnvironmentControl presentationEnvironmentControl; + + /** the ObjectAreaDescriptor for the object environment group */ + private ObjectAreaDescriptor objectAreaDescriptor; + + /** the ObjectAreaPosition for the object environment group */ + private ObjectAreaPosition objectAreaPosition; + + /** the DataDescriptor for the object environment group */ + private AbstractDescriptor dataDescriptor; + + /** the MapDataResource for the object environment group */ + private MapDataResource mapDataResource; + + /** the MapContainerData for the object environment group */ + private MapContainerData mapContainerData; + + /** + * Constructor for the ObjectEnvironmentGroup, this takes a + * name parameter which must be 8 characters long. + * + * @param name the object environment group name + */ + public ObjectEnvironmentGroup(String name) { + super(name); + } + + /** + * Sets the Object Area Descriptor + * + * @param objectAreaDescriptor the object area descriptor + */ + public void setObjectAreaDescriptor(ObjectAreaDescriptor objectAreaDescriptor) { + this.objectAreaDescriptor = objectAreaDescriptor; + } + + /** + * Sets the Object Area Position + * + * @param objectAreaPosition the object area position + */ + public void setObjectAreaPosition(ObjectAreaPosition objectAreaPosition) { + this.objectAreaPosition = objectAreaPosition; + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.OBJECT_ENVIRONMENT_GROUP); + + int tripletDataLength = getTripletDataLength(); + int sfLen = data.length + tripletDataLength - 1; + byte[] len = BinaryUtils.convert(sfLen, 2); + data[1] = len[0]; + data[2] = len[1]; + + os.write(data); + + writeTriplets(os); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + + if (presentationEnvironmentControl != null) { + presentationEnvironmentControl.writeToStream(os); + } + + if (objectAreaDescriptor != null) { + objectAreaDescriptor.writeToStream(os); + } + + if (objectAreaPosition != null) { + objectAreaPosition.writeToStream(os); + } + + if (mapContainerData != null) { + mapContainerData.writeToStream(os); + } + + if (mapDataResource != null) { + mapDataResource.writeToStream(os); + } + + if (dataDescriptor != null) { + dataDescriptor.writeToStream(os); + } + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.OBJECT_ENVIRONMENT_GROUP); + os.write(data); + } + + /** + * Sets the presentation environment control + * + * @param presentationEnvironmentControl the presentation environment control + */ + public void setPresentationEnvironmentControl( + PresentationEnvironmentControl presentationEnvironmentControl) { + this.presentationEnvironmentControl = presentationEnvironmentControl; + } + + /** + * Sets the data descriptor + * + * @param dataDescriptor the data descriptor + */ + public void setDataDescriptor(AbstractDescriptor dataDescriptor) { + this.dataDescriptor = dataDescriptor; + } + + /** + * Sets the map data resource + * + * @param mapDataResource the map data resource + */ + public void setMapDataResource(MapDataResource mapDataResource) { + this.mapDataResource = mapDataResource; + } + + /** + * Sets the map container data + * + * @param mapContainerData the map container data + */ + public void setMapContainerData(MapContainerData mapContainerData) { + this.mapContainerData = mapContainerData; + } + + /** + * Returns the object area descriptor + * + * @return the object area descriptor + */ + public ObjectAreaDescriptor getObjectAreaDescriptor() { + return this.objectAreaDescriptor; + } + +} diff --git a/src/java/org/apache/fop/afp/modca/Overlay.java b/src/java/org/apache/fop/afp/modca/Overlay.java new file mode 100644 index 000000000..ea9619b20 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/Overlay.java @@ -0,0 +1,87 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Factory; + + +/** + * An overlay is a MO:DCA-P resource object. + * + * It may be stored in an external resource library or it may be + * carried in a resource group. An overlay is similar to a page in + * that it defines its own environment and carries the same data objects. + */ +public class Overlay extends PageObject { + + /** + * Construct a new overlay object for the specified name argument, the overlay + * name should be an 8 character identifier. + * + * @param factory + * the resource manager of the page. + * @param name + * the name of the page. + * @param width + * the width of the page. + * @param height + * the height of the page. + * @param rotation + * the rotation of the page. + * @param widthResolution + * the width resolution of the page. + * @param heightResolution + * the height resolution of the page. + */ + public Overlay(Factory factory, + String name, int width, int height, int rotation, + int widthResolution, int heightResolution) { + super(factory, name, width, height, rotation, widthResolution, heightResolution); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.OVERLAY); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + + getActiveEnvironmentGroup().writeToStream(os); + + writeObjects(includePageSegments, os); + writeObjects(tagLogicalElements, os); + writeObjects(objects, os); + } + + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.OVERLAY); + os.write(data); + } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/afp/modca/PageDescriptor.java index 541df823e..502123def 100644 --- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java +++ b/src/java/org/apache/fop/afp/modca/PageDescriptor.java @@ -17,11 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.util.BinaryUtils; /** * The Page Descriptor structured field specifies the size and attributes of @@ -33,47 +34,35 @@ public class PageDescriptor extends AbstractDescriptor { /** * Construct a page descriptor for the specified page width * and page height. + * * @param width The page width. * @param height The page height. - * @param widthResolution The page width resolution - * @param heightResolution The page height resolution + * @param widthRes The page width resolution + * @param heightRes The page height resolution */ - public PageDescriptor(int width, int height, int widthResolution, int heightResolution) { - super(width, height, widthResolution, heightResolution); + public PageDescriptor(int width, int height, int widthRes, int heightRes) { + super(width, height, widthRes, heightRes); } - /** - * Accessor method to write the AFP datastream for the Page Descriptor - * @param os The stream to write to - * @throws java.io.IOException in the event that an I/O Exception occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - log.debug("width=" + width); - log.debug("height=" + height); + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[24]; - data[0] = 0x5A; - data[1] = 0x00; + copySF(data, Type.DESCRIPTOR, Category.PAGE); data[2] = 0x17; - data[3] = (byte) 0xD3; - data[4] = (byte) 0xA6; - data[5] = (byte) 0xAF; - - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved + // XpgBase data[9] = 0x00; // XpgBase = 10 inches + + // YpgBase data[10] = 0x00; // YpgBase = 10 inches // XpgUnits - byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); data[11] = xdpi[0]; data[12] = xdpi[1]; // YpgUnits - byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); data[13] = ydpi[0]; data[14] = ydpi[1]; diff --git a/src/java/org/apache/fop/afp/modca/PageGroup.java b/src/java/org/apache/fop/afp/modca/PageGroup.java new file mode 100644 index 000000000..13be9745e --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/PageGroup.java @@ -0,0 +1,105 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.apache.fop.afp.Factory; + +/** + * A page group is used in the data stream to define a named, logical grouping + * of sequential pages. Page groups are delimited by begin-end structured fields + * that carry the name of the page group. Page groups are defined so that the + * pages that comprise the group can be referenced or processed as a single + * entity. Page groups are often processed in stand-alone fashion; that is, they + * are indexed, retrieved, and presented outside the context of the containing + * document. + */ +public class PageGroup extends AbstractResourceEnvironmentGroupContainer { + + /** The tag logical elements contained within this group */ + private List tagLogicalElements = null; + + /** + * Constructor for the PageGroup. + * + * @param factory the resource manager + * @param name the name of the page group + */ + public PageGroup(Factory factory, String name) { + super(factory, name); + } + + private List getTagLogicalElements() { + if (tagLogicalElements == null) { + this.tagLogicalElements = new java.util.ArrayList(); + } + return this.tagLogicalElements; + } + + /** + * Creates a TagLogicalElement on the page. + * + * @param name + * the name of the tag + * @param value + * the value of the tag + */ + public void createTagLogicalElement(String name, String value) { + TagLogicalElement tle = factory.createTagLogicalElement(name, value); + if (!getTagLogicalElements().contains(tle)) { + getTagLogicalElements().add(tle); + } + } + + /** + * Method to mark the end of the page group. + */ + public void endPageGroup() { + complete = true; + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + writeObjects(tagLogicalElements, os); + super.writeContent(os); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.PAGE_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.PAGE_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return this.getName(); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/PageObject.java b/src/java/org/apache/fop/afp/modca/PageObject.java new file mode 100644 index 000000000..33852d90b --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/PageObject.java @@ -0,0 +1,219 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Factory; +import org.apache.fop.afp.ioca.ImageCellPosition; +import org.apache.fop.afp.ioca.ImageInputDescriptor; +import org.apache.fop.afp.ioca.ImageOutputControl; +import org.apache.fop.afp.ioca.ImageRasterData; +import org.apache.fop.afp.ioca.ImageRasterPattern; + +/** + * Pages contain the data objects that comprise a presentation document. Each + * page has a set of data objects associated with it. Each page within a + * document is independent from any other page, and each must establish its own + * environment parameters. + * + * The page is the level in the document component hierarchy that is used for + * printing or displaying a document's content. The data objects contained in + * the page envelope in the data stream are presented when the page is + * presented. Each data object has layout information associated with it that + * directs the placement and orientation of the data on the page. In addition, + * each page contains layout information that specifies the measurement units, + * page width, and page depth. + * + * A page is initiated by a begin page structured field and terminated by an end + * page structured field. Structured fields that define objects and active + * environment groups or that specify attributes of the page may be encountered + * in page state. + * + */ +public class PageObject extends AbstractResourceGroupContainer { + + /** + * Construct a new page object for the specified name argument, the page + * name should be an 8 character identifier. + * + * @param factory the resource manager + * + * @param name + * the name of the page. + * @param width + * the width of the page. + * @param height + * the height of the page. + * @param rotation + * the rotation of the page. + * @param widthRes + * the width resolution of the page. + * @param heightRes + * the height resolution of the page. + */ + public PageObject(Factory factory, + String name, int width, int height, int rotation, + int widthRes, int heightRes) { + super(factory, name, width, height, rotation, widthRes, heightRes); + } + + /** + * Creates an IncludePageOverlay on the page. + * + * @param name + * the name of the overlay + * @param x + * the x position of the overlay + * @param y + * the y position of the overlay + * @param orientation + * the orientation required for the overlay + */ + public void createIncludePageOverlay(String name, int x, int y, int orientation) { + getActiveEnvironmentGroup().createOverlay(name); + IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation); + addObject(ipo); + } + + /** + * This method will create shading on the page using the specified + * coordinates (the shading contrast is controlled via the red, green blue + * parameters, by converting this to grayscale). + * + * @param x + * the x coordinate of the shading + * @param y + * the y coordinate of the shading + * @param w + * the width of the shaded area + * @param h + * the height of the shaded area + * @param red + * the red value + * @param green + * the green value + * @param blue + * the blue value + */ + public void createShading(int x, int y, int w, int h, int red, int green, int blue) { + int xCoord = 0; + int yCoord = 0; + int areaWidth = 0; + int areaHeight = 0; + switch (rotation) { + case 90: + xCoord = areaWidth - y - h; + yCoord = x; + areaWidth = h; + areaHeight = w; + break; + case 180: + xCoord = areaWidth - x - w; + yCoord = areaHeight - y - h; + areaWidth = w; + areaHeight = h; + break; + case 270: + xCoord = y; + yCoord = areaHeight - x - w; + areaWidth = h; + areaHeight = w; + break; + default: + xCoord = x; + yCoord = y; + areaWidth = w; + areaHeight = h; + break; + } + + // Convert the color to grey scale + float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11)); + + int grayscale = Math.round((shade / 255) * 16); + + IMImageObject imImageObject = factory.createIMImageObject(); + + ImageOutputControl imageOutputControl = new ImageOutputControl(0, 0); + ImageInputDescriptor imageInputDescriptor = new ImageInputDescriptor(); + ImageCellPosition imageCellPosition = new ImageCellPosition(xCoord, yCoord); + imageCellPosition.setXFillSize(areaWidth); + imageCellPosition.setYFillSize(areaHeight); + imageCellPosition.setXSize(64); + imageCellPosition.setYSize(8); + + //defining this as a resource + byte[] rasterData = ImageRasterPattern.getRasterData(grayscale); + ImageRasterData imageRasterData = factory.createImageRasterData(rasterData); + + imImageObject.setImageOutputControl(imageOutputControl); + imImageObject.setImageInputDescriptor(imageInputDescriptor); + imImageObject.setImageCellPosition(imageCellPosition); + imImageObject.setImageRasterData(imageRasterData); + addObject(imImageObject); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.PAGE); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + writeTriplets(os); + + getActiveEnvironmentGroup().writeToStream(os); + + writeObjects(includePageSegments, os); + writeObjects(tagLogicalElements, os); + writeObjects(objects, os); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.PAGE); + os.write(data); + } + + /** + * Adds an AFP object reference to this page + * + * @param obj an AFP object + */ + public void addObject(Object obj) { + endPresentationObject(); + super.addObject(obj); + } + + /** {@inheritDoc} */ + public String toString() { + return this.getName(); + } + + /** {@inheritDoc} */ + protected boolean canWrite(AbstractAFPObject ao) { + return true; + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/PageSegment.java b/src/java/org/apache/fop/afp/modca/PageSegment.java new file mode 100644 index 000000000..ab1388efb --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/PageSegment.java @@ -0,0 +1,90 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +/** + * A page segment is a MO:DCA-P resource object. It may be stored in an + * external resource library or it may be carried in a resource group. + * Page segments contain any combination of IOCA image objects and + * GOCA graphics objects. + */ +public class PageSegment extends AbstractNamedAFPObject { + + private List/*<AbstractAFPObject>*/ objects = null; + + /** + * Main constructor + * + * @param name the name of this object + */ + public PageSegment(String name) { + super(name); + } + + /** + * Returns a list of objects contained withing this page segment + * + * @return a list of objects contained within this page segment + */ + public List/*<AbstractAFPObject>*/ getObjects() { + if (objects == null) { + objects = new java.util.ArrayList(); + } + return objects; + } + + /** + * Adds a resource object (image/graphic) to this page segment + * + * @param object the resource objec to add to this page segment + */ + public void addObject(AbstractAFPObject object) { + getObjects().add(object); + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.PAGE_SEGMENT); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + super.writeContent(os); + writeObjects(objects, os); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.PAGE_SEGMENT); + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return this.name; + } +} diff --git a/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java b/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java new file mode 100644 index 000000000..72e261662 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/PreprocessPresentationObject.java @@ -0,0 +1,144 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Preprocess Presentation Object structured field specifies presentation + * parameters for a data object that has been mapped as a resource. + */ +public class PreprocessPresentationObject extends AbstractTripletStructuredObject { + private static final byte TYPE_OTHER = (byte)0x92; + private static final byte TYPE_OVERLAY = (byte)0xDF; + private static final byte TYPE_IMAGE = (byte)0xFB; + + private byte objType = TYPE_OTHER; + private byte objOrent = 0; // object always processed at 0 degree orientation + private int objXOffset = -1; + private int objYOffset = -1; + + /** + * Main constructor + * + * @param prePresObj the presentation object to be preprocessed + */ + public PreprocessPresentationObject(AbstractTripletStructuredObject prePresObj) { + if (prePresObj instanceof ImageObject || prePresObj instanceof Overlay) { + if (prePresObj instanceof ImageObject) { + this.objType = TYPE_IMAGE; + } else { + this.objType = TYPE_OVERLAY; + } + setFullyQualifiedName( + FullyQualifiedNameTriplet.TYPE_BEGIN_RESOURCE_OBJECT_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, + prePresObj.getFullyQualifiedName()); + } else { + this.objType = TYPE_OTHER; + } + } + + public static final byte ORIENTATION_ZERO_DEGREES = 1; + public static final byte ORIENTATION_90_DEGREES = 2; + public static final byte ORIENTATION_180_DEGREES = 4; + public static final byte ORIENTATION_270_DEGREES = 8; + + /** + * Sets the object orientations relative to media leading edge + * + * @param orientation the object orientations relative to media leading edge + */ + public void setOrientation(byte orientation) { + objOrent = orientation; + } + + /** + * Sets the X axis origin for object content + * + * @param xOffset the X axis origin for object content + */ + public void setXOffset(int xOffset) { + this.objXOffset = xOffset; + } + + /** + * Sets the Y axis origin for object content + * + * @param yOffset the Y axis origin for object content + */ + public void setYOffset(int yOffset) { + this.objYOffset = yOffset; + } + + /** {@inheritDoc} */ + public void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + byte[] data = new byte[9]; + copySF(data, Type.PROCESS, Category.DATA_RESOURCE); + + byte[] l = BinaryUtils.convert(19 + getTripletDataLength(), 2); + data[1] = l[0]; // Length byte 1 + data[2] = l[1]; // Length byte 1 + + os.write(data); + } + + /** {@inheritDoc} */ + public void writeContent(OutputStream os) throws IOException { + byte[] data = new byte[12]; + byte[] l = BinaryUtils.convert(12 + getTripletDataLength(), 2); + data[0] = l[0]; // RGLength + data[1] = l[1]; // RGLength + data[2] = objType; // ObjType + data[3] = 0x00; // Reserved + data[4] = 0x00; // Reserved + data[5] = objOrent; // ObjOrent + if (objXOffset > 0) { + byte[] xOff = BinaryUtils.convert(objYOffset, 3); + data[6] = xOff[0]; // XocaOset (not specified) + data[7] = xOff[1]; // XocaOset + data[8] = xOff[2]; // XocaOset + } else { + data[6] = (byte)0xFF; // XocaOset (not specified) + data[7] = (byte)0xFF; // XocaOset + data[8] = (byte)0xFF; // XocaOset + } + if (objYOffset > 0) { + byte[] yOff = BinaryUtils.convert(objYOffset, 3); + data[9] = yOff[0]; // YocaOset (not specified) + data[10] = yOff[1]; // YocaOset + data[11] = yOff[2]; // YocaOset + } else { + data[9] = (byte)0xFF; // YocaOset (not specified) + data[10] = (byte)0xFF; // YocaOset + data[11] = (byte)0xFF; // YocaOset + } + os.write(data); + + writeTriplets(os); + } + +} diff --git a/src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java b/src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java new file mode 100644 index 000000000..a2ebe22f6 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/PresentationEnvironmentControl.java @@ -0,0 +1,98 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Presentation Environment Control structured field specifies parameters that + * affect the rendering of presentation data and the appearance that is to be assumed + * by the presentation device. + */ +public class PresentationEnvironmentControl extends AbstractTripletStructuredObject { + + /** + * Main constructor + */ + public PresentationEnvironmentControl() { + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = new byte[11]; + copySF(data, Type.CONTROL, Category.DOCUMENT); + int tripletDataLen = getTripletDataLength(); + byte[] len = BinaryUtils.convert(10 + tripletDataLen); + data[1] = len[0]; + data[2] = len[1]; + data[9] = 0x00; // Reserved; must be zero + data[10] = 0x00; // Reserved; must be zero + + os.write(data); + + writeTriplets(os); + } + +// /** +// * Sets the object offset +// */ +// public void setObjectOffset() { +// addTriplet(new ObjectOffsetTriplet()); +// } +// +// /** +// * Sets the rendering intent +// */ +// public void setRenderingIntent() { +// addTriplet(new RenderingIntentTriplet()); +// } +// +// /** +// * Sets the device appearance +// */ +// public void setDeviceAppearance() { +// addTriplet(new DeviceAppearanceTriplet()); +// } + + + // TODO +// private class DeviceAppearanceTriplet extends AbstractTriplet { +// public DeviceAppearanceTriplet() { +// super(AbstractTriplet.DEVICE_APPEARANCE); +// } +// } + + // TODO +// private class RenderingIntentTriplet extends AbstractTriplet { +// public RenderingIntentTriplet() { +// super(AbstractTriplet.RENDERING_INTENT); +// } +// } + + // TODO +// private class ObjectOffsetTriplet extends AbstractTriplet { +// public ObjectOffsetTriplet() { +// super(AbstractTriplet.OBJECT_OFFSET); +// } +// } +} diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/afp/modca/PresentationTextData.java index 98beb96f7..645a461d8 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java +++ b/src/java/org/apache/fop/afp/modca/PresentationTextData.java @@ -17,14 +17,17 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.awt.Color; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.UnsupportedEncodingException; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.fop.afp.AFPLineDataInfo; +import org.apache.fop.afp.AFPTextDataInfo; +import org.apache.fop.afp.util.BinaryUtils; /** * Presentation text data contains the graphic characters and the control @@ -48,58 +51,38 @@ import org.apache.fop.render.afp.tools.BinaryUtils; */ public class PresentationTextData extends AbstractAFPObject { - /** - * The maximum size of the presentation text data. - */ + /** the maximum size of the presentation text data.*/ private static final int MAX_SIZE = 8192; - /** - * The afp data relating to this presentaion text data. - */ - private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024); + /** the AFP data relating to this presentation text data. */ + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - /** - * The current x coordinate. - */ - private int _currentXCoordinate = -1; + /** the current x coordinate. */ + private int currentX = -1; - /** - * The current y cooridnate - */ - private int _currentYCoordinate = -1; + /** the current y cooridnate */ + private int currentY = -1; - /** - * The current font - */ - private String _currentFont = ""; + /** the current font */ + private String currentFont = ""; - /** - * The current orientation - */ - private int _currentOrientation = 0; + /** the current orientation */ + private int currentOrientation = 0; - /** - * The current color - */ - private Color _currentColor = new Color(0, 0, 0); + /** the current color */ + private Color currentColor = new Color(0, 0, 0); - /** - * The current variable space increment - */ - private int _currentVariableSpaceCharacterIncrement = 0; + /** the current variable space increment */ + private int currentVariableSpaceCharacterIncrement = 0; - /** - * The current inter character adjustment - */ - private int _currentInterCharacterAdjustment = 0; + /** the current inter character adjustment */ + private int currentInterCharacterAdjustment = 0; /** * Default constructor for the PresentationTextData. */ public PresentationTextData() { - this(false); - } /** @@ -111,22 +94,22 @@ public class PresentationTextData extends AbstractAFPObject { * The control sequence indicator. */ public PresentationTextData(boolean controlInd) { - - _baos.write(new byte[] { 0x5A, // Structured field identifier - 0x00, // Record length byte 1 - 0x00, // Record length byte 2 - (byte) 0xD3, // PresentationTextData identifier byte 1 - (byte) 0xEE, // PresentationTextData identifier byte 2 - (byte) 0x9B, // PresentationTextData identifier byte 3 - 0x00, // Flag - 0x00, // Reserved - 0x00, // Reserved - }, 0, 9); + final byte[] data = { + 0x5A, // Structured field identifier + 0x00, // Record length byte 1 + 0x00, // Record length byte 2 + SF_CLASS, // PresentationTextData identifier byte 1 + Type.DATA, // PresentationTextData identifier byte 2 + Category.PRESENTATION_TEXT, // PresentationTextData identifier byte 3 + 0x00, // Flag + 0x00, // Reserved + 0x00, // Reserved + }; + baos.write(data, 0, 9); if (controlInd) { - _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2); + baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2); } - } /** @@ -140,16 +123,14 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void setCodedFont(byte font, ByteArrayOutputStream afpdata) { - // Avoid unnecessary specification of the font - if (String.valueOf(font).equals(_currentFont)) { + if (String.valueOf(font).equals(currentFont)) { return; } else { - _currentFont = String.valueOf(font); + currentFont = String.valueOf(font); } - afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3); - + afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3); } /** @@ -163,14 +144,10 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void absoluteMoveInline(int coordinate, - ByteArrayOutputStream afpdata) { - + ByteArrayOutputStream afpdata) { byte[] b = BinaryUtils.convert(coordinate, 2); - - afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4); - - _currentXCoordinate = coordinate; - + afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4); + currentX = coordinate; } /** @@ -184,16 +161,14 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void absoluteMoveBaseline(int coordinate, - ByteArrayOutputStream afpdata) { - + ByteArrayOutputStream afpdata) { byte[] b = BinaryUtils.convert(coordinate, 2); - - afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4); - - _currentYCoordinate = coordinate; - + afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4); + currentY = coordinate; } + private static final int TRANSPARENT_MAX_SIZE = 253; + /** * The Transparent Data control sequence contains a sequence of code points * that are presented without a scan for embedded control sequences. @@ -204,21 +179,16 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void addTransparentData(byte[] data, ByteArrayOutputStream afpdata) { - // Calculate the length int l = data.length + 2; - if (l > 255) { // Check that we are not exceeding the maximum length throw new IllegalArgumentException( - "Transparent data is longer than 253 bytes: " + data); + "Transparent data is longer than " + TRANSPARENT_MAX_SIZE + " bytes: " + data); } - - afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, }, - 0, 2); - + afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB}, + 0, 2); afpdata.write(data, 0, data.length); - } /** @@ -234,12 +204,11 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void drawBaxisRule(int length, int width, - ByteArrayOutputStream afpdata) { - - afpdata.write(new byte[] { 0x07, // Length - (byte) 0xE7, // Type + ByteArrayOutputStream afpdata) { + afpdata.write(new byte[] { + 0x07, // Length + (byte) 0xE7, // Type }, 0, 2); - // Rule length byte[] data1 = BinaryUtils.shortToByteArray((short) length); afpdata.write(data1, 0, data1.length); @@ -248,7 +217,6 @@ public class PresentationTextData extends AbstractAFPObject { afpdata.write(data2, 0, data2.length); // Rule width fraction afpdata.write(0x00); - } /** @@ -264,12 +232,11 @@ public class PresentationTextData extends AbstractAFPObject { * The output stream to which data should be written. */ private void drawIaxisRule(int length, int width, - ByteArrayOutputStream afpdata) { - - afpdata.write(new byte[] { 0x07, // Length - (byte) 0xE5, // Type + ByteArrayOutputStream afpdata) { + afpdata.write(new byte[] { + 0x07, // Length + (byte) 0xE5, // Type }, 0, 2); - // Rule length byte[] data1 = BinaryUtils.shortToByteArray((short) length); afpdata.write(data1, 0, data1.length); @@ -278,152 +245,170 @@ public class PresentationTextData extends AbstractAFPObject { afpdata.write(data2, 0, data2.length); // Rule width fraction afpdata.write(0x00); - } /** * Create the presentation text data for the byte array of data. * - * @param fontNumber - * The font resource identifier. - * @param x - * The x coordinate for the text data. - * @param y - * The y coordinate for the text data. - * @param orientation - * The orientation of the text data. - * @param col - * The text color. - * @param vsci - * The variable space character increment. - * @param ica - * The inter character adjustment. - * @param data - * The text data to be created. + * @param textDataInfo + * the afp text data * @throws MaximumSizeExceededException + * thrown if the maximum number of text data is exceeded + * @throws UnsupportedEncodingException + * thrown if character encoding is not supported */ - public void createTextData(int fontNumber, int x, int y, int orientation, - Color col, int vsci, int ica, byte[] data) - throws MaximumSizeExceededException { + public void createTextData(AFPTextDataInfo textDataInfo) + throws MaximumSizeExceededException, UnsupportedEncodingException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (_currentOrientation != orientation) { - setTextOrientation(orientation, afpdata); - _currentOrientation = orientation; - _currentXCoordinate = -1; - _currentYCoordinate = -1; + int rotation = textDataInfo.getRotation(); + if (currentOrientation != rotation) { + setTextOrientation(rotation, afpdata); + currentOrientation = rotation; + currentX = -1; + currentY = -1; } - // Avoid unnecessary specification of the Y co-ordinate - if (y != _currentYCoordinate) { + // Avoid unnecessary specification of the Y coordinate + int y = textDataInfo.getY(); + if (currentY != y) { absoluteMoveBaseline(y, afpdata); - _currentXCoordinate = -1; + currentX = -1; } - // Avoid unnecessary specification of the X co-ordinate - if (x != _currentXCoordinate) { + // Avoid unnecessary specification of the X coordinate + int x = textDataInfo.getX(); + if (currentX != x) { absoluteMoveInline(x, afpdata); } // Avoid unnecessary specification of the variable space increment - if (vsci != _currentVariableSpaceCharacterIncrement) { - setVariableSpaceCharacterIncrement(vsci, afpdata); - _currentVariableSpaceCharacterIncrement = vsci; + if (textDataInfo.getVariableSpaceCharacterIncrement() + != currentVariableSpaceCharacterIncrement) { + setVariableSpaceCharacterIncrement(textDataInfo + .getVariableSpaceCharacterIncrement(), afpdata); + currentVariableSpaceCharacterIncrement = textDataInfo + .getVariableSpaceCharacterIncrement(); } // Avoid unnecessary specification of the inter character adjustment - if (ica != _currentInterCharacterAdjustment) { - setInterCharacterAdjustment(ica, afpdata); - _currentInterCharacterAdjustment = ica; + if (textDataInfo.getInterCharacterAdjustment() != currentInterCharacterAdjustment) { + setInterCharacterAdjustment(textDataInfo.getInterCharacterAdjustment(), + afpdata); + currentInterCharacterAdjustment = textDataInfo + .getInterCharacterAdjustment(); } // Avoid unnecessary specification of the text color - if (!col.equals(_currentColor)) { - setExtendedTextColor(col, afpdata); - _currentColor = col; + if (!textDataInfo.getColor().equals(currentColor)) { + setExtendedTextColor(textDataInfo.getColor(), afpdata); + currentColor = textDataInfo.getColor(); } - setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata); - addTransparentData(data, afpdata); - _currentXCoordinate = -1; + setCodedFont(BinaryUtils.convert(textDataInfo.getFontReference())[0], + afpdata); + + // Add transparent data + String textString = textDataInfo.getString(); + String encoding = textDataInfo.getEncoding(); + byte[] data = textString.getBytes(encoding); + if (data.length <= TRANSPARENT_MAX_SIZE) { + addTransparentData(data, afpdata); + } else { + // data size greater than TRANSPARENT_MAX_SIZE so slice + int numTransData = data.length / TRANSPARENT_MAX_SIZE; + byte[] buff = new byte[TRANSPARENT_MAX_SIZE]; + int currIndex = 0; + for (int transDataCnt = 0; transDataCnt < numTransData; transDataCnt++) { + currIndex = transDataCnt * TRANSPARENT_MAX_SIZE; + System.arraycopy(data, currIndex, buff, 0, TRANSPARENT_MAX_SIZE); + addTransparentData(buff, afpdata); + } + int remainingTransData = data.length / TRANSPARENT_MAX_SIZE; + buff = new byte[remainingTransData]; + System.arraycopy(data, currIndex, buff, 0, remainingTransData); + addTransparentData(buff, afpdata); + } + currentX = -1; - int s = afpdata.size(); + int dataSize = afpdata.size(); - if (_baos.size() + s > MAX_SIZE) { - _currentXCoordinate = -1; - _currentYCoordinate = -1; + if (baos.size() + dataSize > MAX_SIZE) { + currentX = -1; + currentY = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - _baos.write(outputdata, 0, outputdata.length); + baos.write(outputdata, 0, outputdata.length); + } + private int ensurePositive(int value) { + if (value < 0) { + return 0; + } + return value; } /** * Drawing of lines using the starting and ending coordinates, thickness and * colour arguments. * - * @param x1 - * The starting X coordinate. - * @param y1 - * The starting Y coordinate. - * @param x2 - * The ending X coordinate. - * @param y2 - * The ending Y coordinate. - * @param thickness - * The line thickness. - * @param orientation - * The orientation of the text data. - * @param col - * The text color. + * @param lineDataInfo the line data information. + * @throws MaximumSizeExceededException + * thrown if the maximum number of line data has been exceeded */ - public void createLineData(int x1, int y1, int x2, int y2, int thickness, - int orientation, Color col) throws MaximumSizeExceededException { + public void createLineData(AFPLineDataInfo lineDataInfo) throws MaximumSizeExceededException { ByteArrayOutputStream afpdata = new ByteArrayOutputStream(); - if (_currentOrientation != orientation) { + int orientation = lineDataInfo.getRotation(); + if (currentOrientation != orientation) { setTextOrientation(orientation, afpdata); - _currentOrientation = orientation; + currentOrientation = orientation; } // Avoid unnecessary specification of the Y coordinate - if (y1 != _currentYCoordinate) { + int y1 = ensurePositive(lineDataInfo.getY1()); + if (y1 != currentY) { absoluteMoveBaseline(y1, afpdata); } // Avoid unnecessary specification of the X coordinate - if (x1 != _currentXCoordinate) { + int x1 = ensurePositive(lineDataInfo.getX1()); + if (x1 != currentX) { absoluteMoveInline(x1, afpdata); } - if (!col.equals(_currentColor)) { - setExtendedTextColor(col, afpdata); - _currentColor = col; + Color color = lineDataInfo.getColor(); + if (!color.equals(currentColor)) { + setExtendedTextColor(color, afpdata); + currentColor = color; } + int x2 = ensurePositive(lineDataInfo.getX2()); + int y2 = ensurePositive(lineDataInfo.getY2()); + int thickness = lineDataInfo.getThickness(); if (y1 == y2) { drawIaxisRule(x2 - x1, thickness, afpdata); } else if (x1 == x2) { drawBaxisRule(y2 - y1, thickness, afpdata); } else { + log.error("Invalid axis rule unable to draw line"); return; } - int s = afpdata.size(); + int dataSize = afpdata.size(); - if (_baos.size() + s > MAX_SIZE) { - _currentXCoordinate = -1; - _currentYCoordinate = -1; + if (baos.size() + dataSize > MAX_SIZE) { + currentX = -1; + currentY = -1; throw new MaximumSizeExceededException(); } byte[] outputdata = afpdata.toByteArray(); - _baos.write(outputdata, 0, outputdata.length); - + baos.write(outputdata, 0, outputdata.length); } /** @@ -436,141 +421,117 @@ public class PresentationTextData extends AbstractAFPObject { * and minutes. * * @param orientation - * The text orientation (0,90, 180, 270). - * @param afpdata + * The text orientation (0, 90, 180, 270). + * @param os * The output stream to which data should be written. */ private void setTextOrientation(int orientation, - ByteArrayOutputStream afpdata) { - - afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2); - + ByteArrayOutputStream os) { + os.write(new byte[] {0x06, (byte) 0xF7, }, 0, 2); switch (orientation) { - case 90: - afpdata.write(0x2D); - afpdata.write(0x00); - afpdata.write(0x5A); - afpdata.write(0x00); - break; - case 180: - afpdata.write(0x5A); - afpdata.write(0x00); - afpdata.write(0x87); - afpdata.write(0x00); - break; - case 270: - afpdata.write(0x87); - afpdata.write(0x00); - afpdata.write(0x00); - afpdata.write(0x00); - break; - default: - afpdata.write(0x00); - afpdata.write(0x00); - afpdata.write(0x2D); - afpdata.write(0x00); - break; + case 90: + os.write(0x2D); + os.write(0x00); + os.write(0x5A); + os.write(0x00); + break; + case 180: + os.write(0x5A); + os.write(0x00); + os.write(0x87); + os.write(0x00); + break; + case 270: + os.write(0x87); + os.write(0x00); + os.write(0x00); + os.write(0x00); + break; + default: + os.write(0x00); + os.write(0x00); + os.write(0x2D); + os.write(0x00); + break; } - } /** * The Set Extended Text Color control sequence specifies a color value and - * defines the color space and encoding for that value. The specified color - * value is applied to foreground areas of the text presentation space. - * This is a modal control sequence. + * defines the color space and encoding for that value. The specified color + * value is applied to foreground areas of the text presentation space. This + * is a modal control sequence. * * @param col * The color to be set. - * @param afpdata + * @param os * The output stream to which data should be written. */ - private void setExtendedTextColor(Color col, - ByteArrayOutputStream afpdata) { - - afpdata.write(new byte[] { - 15 // Control sequence length - , (byte)0x81 // Control sequence function type - , 0x00 // Reserved; must be zero - , 0x01 // Color space - 0x01 = RGB - , 0x00 // Reserved; must be zero - , 0x00 // Reserved; must be zero - , 0x00 // Reserved; must be zero - , 0x00 // Reserved; must be zero - , 8 // Number of bits in component 1 - , 8 // Number of bits in component 2 - , 8 // Number of bits in component 3 - , 0 // Number of bits in component 4 - , (byte)(col.getRed()) // Red intensity - , (byte)(col.getGreen()) // Green intensity - , (byte)(col.getBlue()) // Blue intensity - }, 0, 15); - + private void setExtendedTextColor(Color col, ByteArrayOutputStream os) { + byte[] colorData = new byte[] { + 15, // Control sequence length + (byte) 0x81, // Control sequence function type + 0x00, // Reserved; must be zero + 0x01, // Color space - 0x01 = RGB + 0x00, // Reserved; must be zero + 0x00, // Reserved; must be zero + 0x00, // Reserved; must be zero + 0x00, // Reserved; must be zero + 8, // Number of bits in component 1 + 8, // Number of bits in component 2 + 8, // Number of bits in component 3 + 0, // Number of bits in component 4 + (byte) (col.getRed()), // Red intensity + (byte) (col.getGreen()), // Green intensity + (byte) (col.getBlue()), // Blue intensity + }; + + os.write(colorData, 0, colorData.length); } /** - * //TODO - * This is a modal control sequence. + * //TODO This is a modal control sequence. * * @param incr * The increment to be set. - * @param afpdata + * @param os * The output stream to which data should be written. */ private void setVariableSpaceCharacterIncrement(int incr, - ByteArrayOutputStream afpdata) { - + ByteArrayOutputStream os) { byte[] b = BinaryUtils.convert(incr, 2); - afpdata.write(new byte[] { - 4 // Control sequence length - , (byte)0xC5 // Control sequence function type - , b[0] - , b[1] - }, 0, 4); - + os.write(new byte[] { + 4, // Control sequence length + (byte) 0xC5, // Control sequence function type + b[0], b[1] }, + 0, 4); } /** - * //TODO - * This is a modal control sequence. + * //TODO This is a modal control sequence. * * @param incr * The increment to be set. - * @param afpdata + * @param os * The output stream to which data should be written. */ - private void setInterCharacterAdjustment(int incr, - ByteArrayOutputStream afpdata) { - + private void setInterCharacterAdjustment(int incr, ByteArrayOutputStream os) { byte[] b = BinaryUtils.convert(Math.abs(incr), 2); - - afpdata.write(new byte[] { - 5 // Control sequence length - , (byte)0xC3 // Control sequence function type - , b[0] - , b[1] - , (byte)(incr >= 0 ? 0 : 1) // Direction - }, 0, 5); - + os.write(new byte[] { + 5, // Control sequence length + (byte) 0xC3, // Control sequence function type + b[0], b[1], (byte) (incr >= 0 ? 0 : 1) // Direction + }, 0, 5); } - /** - * Accessor method to write the AFP datastream for - * the text data. - * @param os The stream to write to - * @throws java.io.IOException - */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = _baos.toByteArray(); + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = baos.toByteArray(); byte[] size = BinaryUtils.convert(data.length - 1, 2); data[1] = size[0]; data[2] = size[1]; - os.write(data); - } /** @@ -581,19 +542,15 @@ public class PresentationTextData extends AbstractAFPObject { * method terminates the control sequence. * * @throws MaximumSizeExceededException + * thrown in the event that maximum size has been exceeded */ public void endControlSequence() throws MaximumSizeExceededException { - byte[] data = new byte[2]; data[0] = 0x02; data[1] = (byte) 0xF8; - - if (data.length + _baos.size() > MAX_SIZE) { + if (data.length + baos.size() > MAX_SIZE) { throw new MaximumSizeExceededException(); } - - _baos.write(data, 0, data.length); - + baos.write(data, 0, data.length); } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/afp/modca/PresentationTextDescriptor.java index 3858f4169..ef2696da8 100644 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java +++ b/src/java/org/apache/fop/afp/modca/PresentationTextDescriptor.java @@ -17,11 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; + +import org.apache.fop.afp.util.BinaryUtils; /** * The Presentation Text Descriptor specifies the units of measure for the @@ -50,42 +51,34 @@ public class PresentationTextDescriptor extends AbstractDescriptor { /** * Constructor a PresentationTextDescriptor for the specified * width and height. + * * @param width The width of the page. * @param height The height of the page. - * @param widthResolution The width resolution of the page. - * @param heightResolution The height resolution of the page. + * @param widthRes The width resolution of the page. + * @param heightRes The height resolution of the page. */ public PresentationTextDescriptor(int width, int height, - int widthResolution, int heightResolution) { - super(width, height, widthResolution, heightResolution); + int widthRes, int heightRes) { + super(width, height, widthRes, heightRes); } - /** - * Accessor method to write the AFP datastream for the Presentation Text Descriptor - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { byte[] data = new byte[23]; - data[0] = 0x5A; - data[1] = 0x00; + + copySF(data, Type.MIGRATION, Category.PRESENTATION_TEXT); + + data[1] = 0x00; // length data[2] = 0x16; - data[3] = (byte) 0xD3; - data[4] = (byte) 0xB1; - data[5] = (byte) 0x9B; - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; + data[9] = 0x00; data[10] = 0x00; - byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); + byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2); data[11] = xdpi[0]; // xdpi data[12] = xdpi[1]; - byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); + byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2); data[13] = ydpi[0]; // ydpi data[14] = ydpi[1]; @@ -103,7 +96,6 @@ public class PresentationTextDescriptor extends AbstractDescriptor { data[22] = 0x00; os.write(data); - } }
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/afp/modca/PresentationTextObject.java new file mode 100644 index 000000000..4a8bbbb18 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/PresentationTextObject.java @@ -0,0 +1,174 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.util.List; + +import org.apache.fop.afp.AFPLineDataInfo; +import org.apache.fop.afp.AFPTextDataInfo; + +/** + * The Presentation Text object is the data object used in document processing + * environments for representing text which has been prepared for presentation. + * Text, as used here, means an ordered string of characters, such as graphic + * symbols, numbers, and letters, that are suitable for the specific purpose of + * representing coherent information. Text which has been prepared for + * presentation has been reduced to a primitive form through explicit + * specification of the characters and their placement in the presentation + * space. Control sequences which designate specific control functions may be + * embedded within the text. These functions extend the primitive form by + * applying specific characteristics to the text when it is presented. The + * collection of the graphic characters and control codes is called Presentation + * Text, and the object that contains the Presentation Text is called the + * PresentationText object. + */ +public class PresentationTextObject extends AbstractNamedAFPObject { + + /** + * The current presentation text data + */ + private PresentationTextData currentPresentationTextData = null; + + /** + * The presentation text data list + */ + private List/*<PresentationTextData>*/ presentationTextDataList = null; + + /** + * Construct a new PresentationTextObject for the specified name argument, + * the name should be an 8 character identifier. + * + * @param name the name of this presentation object + */ + public PresentationTextObject(String name) { + super(name); + } + + /** + * Create the presentation text data for the byte array of data. + * + * @param textDataInfo + * The afp text data + * @throws UnsupportedEncodingException thrown if character encoding is not supported + */ + public void createTextData(AFPTextDataInfo textDataInfo) throws UnsupportedEncodingException { + if (currentPresentationTextData == null) { + startPresentationTextData(); + } + try { + currentPresentationTextData.createTextData(textDataInfo); + } catch (MaximumSizeExceededException msee) { + endPresentationTextData(); + createTextData(textDataInfo); + } catch (UnsupportedEncodingException e) { + endPresentationTextData(); + throw e; + } + } + + /** + * Drawing of lines using the starting and ending coordinates, thickness and + * orientation arguments. + * + * @param lineDataInfo the line data information. + */ + public void createLineData(AFPLineDataInfo lineDataInfo) { + if (currentPresentationTextData == null) { + startPresentationTextData(); + } + try { + currentPresentationTextData.createLineData(lineDataInfo); + } catch (MaximumSizeExceededException msee) { + endPresentationTextData(); + createLineData(lineDataInfo); + } + } + + /** + * Helper method to mark the start of the presentation text data + */ + private void startPresentationTextData() { + if (presentationTextDataList == null) { + presentationTextDataList = new java.util.ArrayList/*<PresentationTextData>*/(); + } + if (presentationTextDataList.size() == 0) { + currentPresentationTextData = new PresentationTextData(true); + } else { + currentPresentationTextData = new PresentationTextData(); + } + presentationTextDataList.add(currentPresentationTextData); + } + + /** + * Helper method to mark the end of the presentation text data + */ + private void endPresentationTextData() { + this.currentPresentationTextData = null; + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.PRESENTATION_TEXT); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + writeObjects(this.presentationTextDataList, os); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.PRESENTATION_TEXT); + os.write(data); + } + + /** + * A control sequence is a sequence of bytes that specifies a control + * function. A control sequence consists of a control sequence introducer + * and zero or more parameters. The control sequence can extend multiple + * presentation text data objects, but must eventually be terminated. This + * method terminates the control sequence. + */ + public void endControlSequence() { + if (currentPresentationTextData == null) { + startPresentationTextData(); + } + try { + currentPresentationTextData.endControlSequence(); + } catch (MaximumSizeExceededException msee) { + endPresentationTextData(); + endControlSequence(); + } + } + + /** {@inheritDoc} */ + public String toString() { + if (presentationTextDataList != null) { + return presentationTextDataList.toString(); + } + return null; + } +} diff --git a/src/java/org/apache/fop/afp/modca/Registry.java b/src/java/org/apache/fop/afp/modca/Registry.java new file mode 100644 index 000000000..481a72afd --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/Registry.java @@ -0,0 +1,288 @@ +/* + * 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.afp.modca; + +import java.util.Collections; + +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * MOD:CA Registry of object types + */ +public final class Registry { + /** IOB supported object types */ + private static final byte COMPID_IOCA_FS10 = 5; + private static final byte COMPID_IOCA_FS11 = 11; + private static final byte COMPID_IOCA_FS40 = 55; + private static final byte COMPID_IOCA_FS45 = 12; + private static final byte COMPID_EPS = 13; + private static final byte COMPID_TIFF = 14; + private static final byte COMPID_GIF = 22; + private static final byte COMPID_JFIF = 23; // jpeg file interchange format + private static final byte COMPID_PDF_SINGLE_PAGE = 25; + private static final byte COMPID_PCL_PAGE_OBJECT = 34; + + private static final byte COMPID_TRUETYPE_OPENTYPE_FONT_RESOURCE_OBJECT = 51; + private static final byte COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT = 53; + + /** mime type entry mapping */ + private final java.util.Map/*<String, ObjectType>*/ mimeObjectTypeMap + = Collections.synchronizedMap( + new java.util.HashMap/*<String, ObjectType>*/()); + + /** singleton instance */ + private static Registry instance = null; + + /** + * Returns a single instance of a MO:DCA Registry + * + * @return a single instance of an MO:DCA Registry + */ + public static Registry getInstance() { + synchronized (Registry.class) { + if (instance == null) { + instance = new Registry(); + } + } + return instance; + } + + /** + * private constructor + */ + private Registry() { + init(); + } + + /** + * Initializes the mimetype map + */ + private void init() { + mimeObjectTypeMap.put( + MimeConstants.MIME_AFP_IOCA_FS10, + new ObjectType( + COMPID_IOCA_FS10, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x05}, + "IOCA FS10", + true, + MimeConstants.MIME_AFP_IOCA_FS10 + ) + ); + mimeObjectTypeMap.put( + MimeConstants.MIME_AFP_IOCA_FS11, + new ObjectType( + COMPID_IOCA_FS11, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x11}, + "IOCA FS11", + true, + MimeConstants.MIME_AFP_IOCA_FS11 + ) + ); +// mimeObjectTypeMap.put( +// MimeConstants.MIME_AFP_IOCA_FS40, +// new ObjectType( +// COMPID_IOCA_FS40, +// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x37}, +// "IOCA FS40", +// true, +// MimeConstants.MIME_AFP_IOCA_FS40 +// ) +//); + mimeObjectTypeMap.put( + MimeConstants.MIME_AFP_IOCA_FS45, + new ObjectType( + COMPID_IOCA_FS45, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x12}, + "IOCA FS45", + true, + MimeConstants.MIME_AFP_IOCA_FS45 + ) + ); + mimeObjectTypeMap.put( + MimeConstants.MIME_EPS, + new ObjectType( + COMPID_EPS, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0D}, + "Encapsulated Postscript", + true, + MimeConstants.MIME_EPS + ) + ); + mimeObjectTypeMap.put( + MimeConstants.MIME_TIFF, + new ObjectType( + COMPID_TIFF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x0E}, + "TIFF", + true, + MimeConstants.MIME_TIFF + ) + ); + mimeObjectTypeMap.put( + MimeConstants.MIME_GIF, + new ObjectType( + COMPID_GIF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x16}, + "GIF", + true, + MimeConstants.MIME_GIF + ) + ); + mimeObjectTypeMap.put( + MimeConstants.MIME_JPEG, + new ObjectType( + COMPID_JFIF, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x17}, + "JFIF", + true, + MimeConstants.MIME_JPEG + ) + ); + mimeObjectTypeMap.put(MimeConstants.MIME_PDF, + new ObjectType( + COMPID_PDF_SINGLE_PAGE, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x19}, + "PDF Single-page Object", + true, + MimeConstants.MIME_PDF + ) + ); + mimeObjectTypeMap.put( + MimeConstants.MIME_PCL, + new ObjectType( + COMPID_PCL_PAGE_OBJECT, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x22}, + "PCL Page Object", + true, + MimeConstants.MIME_PCL + ) + ); +// mimeObjectTypeMap.put( +// null, +// new ObjectType( +// COMPID_TRUETYPE_OPENTYPE_FONT_RESOURCE_OBJECT, +// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33}, +// "TrueType/OpenType Font Resource Object", +// true, +// null +// ) +// ); +// mimeObjectTypeMap.put( +// null, +// new ObjectType( +// COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT, +// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x35}, +// "TrueType/OpenType Font Collection Resource Object", +// true, +// null +// ) +// ); + } + + /** + * Returns the MOD:CA object type given a mimetype + * + * @param mimeType the object mimetype + * @return the MOD:CA object type + */ + public ObjectType getObjectType(String mimeType) { + return (ObjectType)mimeObjectTypeMap.get(mimeType); + } + + /** + * Encapsulates a MOD:CA Registry Object Type entry + */ + public class ObjectType { + private final byte componentId; + private final byte[] oid; + private final String name; + private final boolean includable; + private final String mimeType; + + /** + * Main constructor + * + * @param componentId the component id of this object type + * @param oid the object id of this object type + * @param name the object type name + * @param includable true if this object can be included with an IOB structured field + * @param mimeType the mime type associated with this object type + */ + public ObjectType(byte componentId, byte[] oid, String name, + boolean includable, String mimeType) { + this.componentId = componentId; + this.oid = oid; + this.name = name; + this.includable = includable; + this.mimeType = mimeType; + } + + /** + * Returns a MOD:CA object type OID from a given a componentId + * + * @return the corresponding object type id for a given component id + * or null if the component id is unknown and the object type OID was not found. + */ + public byte[] getOID() { + return this.oid; + } + + /** + * Returns the object type name for the given componentId + * + * @return the object type name for the given componentId + */ + public String getName() { + return this.name; + } + + /** + * Returns the compontentId for this entry + * + * @return the compontentId for this entry + */ + public byte getComponentId() { + return this.componentId; + } + + /** + * Returns true if this component can be included with an IOB structured field + * + * @return true if this component can be included with an IOB structured field + */ + public boolean isIncludable() { + return this.includable; + } + + /** + * Returns the mime type associated with this object type + * + * @return the mime type associated with this object type + */ + public String getMimeType() { + return this.mimeType; + } + + /** {@inheritDoc} */ + public String toString() { + return this.getName(); + } + } +} diff --git a/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java new file mode 100644 index 000000000..2e4f57314 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ResourceEnvironmentGroup.java @@ -0,0 +1,128 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import org.apache.fop.afp.Completable; + +/** + * A Resource Environment Group contains a set of resources for a document + * or for a group of pages in a document. + */ +public class ResourceEnvironmentGroup extends AbstractEnvironmentGroup implements Completable { + + /** default name for the resource group */ + private static final String DEFAULT_NAME = "REG00001"; + + /** the maps data resources contained in this resource environment group */ + private List/*<MapDataResource>*/ mapDataResources = null; + + /** the maps page overlays contained in this resource environment group */ + private List mapPageOverlays = null; + + /** the pre-process presentation objects contained in this resource environment group */ + private List/*<PreprocessPresentationObject>*/ preProcessPresentationObjects = null; + + /** the resource environment group state */ + private boolean complete = false; + + /** + * Default constructor + */ + public ResourceEnvironmentGroup() { + this(DEFAULT_NAME); + } + + private List/*<MapDataResource>*/ getMapDataResources() { + if (mapDataResources == null) { + this.mapDataResources = new java.util.ArrayList/*<MapDataResource>*/(); + } + return this.mapDataResources; + } + + private List getMapPageOverlays() { + if (mapPageOverlays == null) { + this.mapPageOverlays = new java.util.ArrayList(); + } + return this.mapPageOverlays; + } + + private List/*<PreprocessPresentationObject>*/ getPreprocessPresentationObjects() { + if (preProcessPresentationObjects == null) { + this.preProcessPresentationObjects + = new java.util.ArrayList/*<PreprocessPresentationObject>*/(); + } + return this.preProcessPresentationObjects; + } + + /** + * Constructor for the ResourceEnvironmentGroup, this takes a + * name parameter which must be 8 characters long. + * @param name the resource environment group name + */ + public ResourceEnvironmentGroup(String name) { + super(name); + } + +// /** +// * Adds an AFP object mapping reference to this resource environment group +// * @param obj the object to add +// */ +// public void addObject(AbstractStructuredAFPObject obj) { +// getMapDataResources().add(new MapDataResource(obj)); +// createOverlay(obj.get); +// getPreprocessPresentationObjects().add(new PreprocessPresentationObject(obj)); +// } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.RESOURCE_ENVIROMENT_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.RESOURCE_ENVIROMENT_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + writeObjects(mapDataResources, os); + writeObjects(mapPageOverlays, os); + writeObjects(preProcessPresentationObjects, os); + } + + /** {@inheritDoc} */ + public void setComplete(boolean complete) { + this.complete = complete; + } + + /** {@inheritDoc} */ + public boolean isComplete() { + return complete; + } + +} diff --git a/src/java/org/apache/fop/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/afp/modca/ResourceGroup.java new file mode 100644 index 000000000..2218998a0 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ResourceGroup.java @@ -0,0 +1,107 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.Set; + +import org.apache.fop.afp.Streamable; + +/** + * A Resource Group contains a set of overlays. + */ +public class ResourceGroup extends AbstractNamedAFPObject { + + /** Set of resource uri */ + private final Set/*<String>*/ resourceSet = new java.util.HashSet/*<String>*/(); + + /** + * Constructor for the ResourceGroup, this takes a + * name parameter which must be 8 characters long. + * + * @param name the resource group name + */ + public ResourceGroup(String name) { + super(name); + } + + /** + * Add this named object to this resource group + * + * @param namedObject a named object + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + public void addObject(AbstractNamedAFPObject namedObject) throws IOException { + resourceSet.add(namedObject); + } + + /** + * Returns the number of resources contained in this resource group + * + * @return the number of resources contained in this resource group + */ + public int getResourceCount() { + return resourceSet.size(); + } + + /** + * Returns true if the resource exists within this resource group, + * false otherwise. + * + * @param uri the uri of the resource + * @return true if the resource exists within this resource group + */ + public boolean resourceExists(String uri) { + return resourceSet.contains(uri); + } + + /** {@inheritDoc} */ + public void writeStart(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.BEGIN, Category.RESOURCE_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + public void writeContent(OutputStream os) throws IOException { + Iterator it = resourceSet.iterator(); + while (it.hasNext()) { + Object object = it.next(); + if (object instanceof Streamable) { + Streamable streamableObject = (Streamable)object; + streamableObject.writeToStream(os); + } + } + } + + /** {@inheritDoc} */ + public void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.RESOURCE_GROUP); + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return this.name + " " + resourceSet/*getResourceMap()*/; + } +} diff --git a/src/java/org/apache/fop/afp/modca/ResourceObject.java b/src/java/org/apache/fop/afp/modca/ResourceObject.java new file mode 100644 index 000000000..0f555a42e --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/ResourceObject.java @@ -0,0 +1,150 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.modca.triplets.ResourceObjectTypeTriplet; +import org.apache.fop.afp.util.BinaryUtils; + +/** + * This resource structured field begins an envelope that is used to carry + * resource objects in print-file-level (external) resource groups. + */ +public class ResourceObject extends AbstractNamedAFPObject { + + /** graphics object type */ + public static final byte TYPE_GRAPHIC = 0x03; + + /** barcode object type */ + public static final byte TYPE_BARCODE = 0x05; + + /** image object type */ + public static final byte TYPE_IMAGE = 0x06; + + /** font character set type */ + public static final byte TYPE_FONT_CHARACTER_SET = 0x40; + + /** code page type */ + public static final byte TYPE_CODE_PAGE = 0x41; + + /** coded font type */ + public static final byte TYPE_CODED_FONT = 0x42; + + /** object container type */ + public static final byte TYPE_OBJECT_CONTAINER = (byte) 0x92; + + /** document object type */ + public static final byte TYPE_DOCUMENT = (byte) 0xA8; + + /** page segment object type */ + public static final byte TYPE_PAGE_SEGMENT = (byte) 0xFB; + + /** overlay object type */ + public static final byte TYPE_OVERLAY_OBJECT = (byte) 0xFC; + + /** page def type */ + public static final byte TYPE_PAGEDEF = (byte) 0xFD; + + /** form def type */ + public static final byte TYPE_FORMDEF = (byte) 0xFE; + + private AbstractNamedAFPObject namedObject; + + /** + * Default constructor + * + * @param name the name of this resource (reference id) + */ + public ResourceObject(String name) { + super(name); + } + + /** + * Sets the data object referenced by this resource object + * + * @param namedObject the named data object + */ + public void setDataObject(AbstractNamedAFPObject namedObject) { + this.namedObject = namedObject; + } + + /** + * Returns the data object referenced by this resource object + * + * @return the data object referenced by this resource object + */ + public AbstractNamedAFPObject getDataObject() { + return namedObject; + } + + /** {@inheritDoc} */ + protected void writeStart(OutputStream os) throws IOException { + super.writeStart(os); + + byte[] data = new byte[19]; + copySF(data, Type.BEGIN, Category.NAME_RESOURCE); + + // Set the total record length + int tripletDataLength = getTripletDataLength(); + byte[] len = BinaryUtils.convert(18 + tripletDataLength, 2); + data[1] = len[0]; // Length byte 1 + data[2] = len[1]; // Length byte 2 + + // Set reserved bits + data[17] = 0x00; // Reserved + data[18] = 0x00; // Reserved + + os.write(data); + + // Write triplets + writeTriplets(os); + } + + /** {@inheritDoc} */ + protected void writeContent(OutputStream os) throws IOException { + if (namedObject != null) { + namedObject.writeToStream(os); + } + } + + /** {@inheritDoc} */ + protected void writeEnd(OutputStream os) throws IOException { + byte[] data = new byte[17]; + copySF(data, Type.END, Category.NAME_RESOURCE); + os.write(data); + } + + /** {@inheritDoc} */ + public String toString() { + return this.getName(); + } + + /** + * Sets Resource Object Type triplet + * + * @param type the resource object type + */ + public void setType(byte type) { + getTriplets().add(new ResourceObjectTypeTriplet(type)); + } + +} diff --git a/src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java b/src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java new file mode 100644 index 000000000..65df33ae4 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/StreamedResourceGroup.java @@ -0,0 +1,96 @@ +/* + * 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.afp.modca; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.Completable; + +/** + * A print-file resource group + */ +public class StreamedResourceGroup extends ResourceGroup implements Completable { + /** the outputstream to write to */ + private final OutputStream os; + + private boolean started = false; + + private boolean complete = false; + + /** + * Main constructor + * + * @param name the resource group name + * @param os the outputstream + */ + public StreamedResourceGroup(String name, OutputStream os) { + super(name); + this.os = os; + } + + /** + * Adds a resource to the external resource group + * + * @param namedObject a named object + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + public void addObject(AbstractNamedAFPObject namedObject) throws IOException { + if (!started) { + writeStart(os); + started = true; + } + try { + namedObject.writeToStream(os); + } finally { + os.flush(); + } + } + + /** + * Closes this external resource group file + * + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + public void close() throws IOException { + writeEnd(os); + complete = true; + } + + /** + * Returns the outputstream + * + * @return the outputstream + */ + public OutputStream getOutputStream() { + return this.os; + } + + /** {@inheritDoc} */ + public void setComplete(boolean complete) { + this.complete = complete; + } + + /** {@inheritDoc} */ + public boolean isComplete() { + return this.complete; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java b/src/java/org/apache/fop/afp/modca/TagLogicalElement.java index 937f2019a..2e1fa5e07 100644 --- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElement.java +++ b/src/java/org/apache/fop/afp/modca/TagLogicalElement.java @@ -17,13 +17,14 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import org.apache.fop.render.afp.tools.BinaryUtils; +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.util.BinaryUtils; /** * A Tag Logical Element structured field assigns an attribute name and an @@ -49,72 +50,41 @@ public class TagLogicalElement extends AbstractAFPObject { /** * Name of the key, used within the TLE */ - private String tleName = null; + private String name = null; /** * Value returned by the key */ - private String tleValue = null; - - /** - * Byte representaion of the name - */ - private byte[] tleByteName = null; - - /** - * Byte representaion of the value - */ - private byte[] tleByteValue = null; + private String value = null; /** * Construct a tag logical element with the name and value specified. + * * @param name the name of the tag logical element * @param value the value of the tag logical element */ public TagLogicalElement(String name, String value) { - - this.tleName = name; - this.tleValue = value; - - try { - - this.tleByteName = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - this.tleByteValue = value.getBytes(AFPConstants.EBCIDIC_ENCODING); - - } catch (UnsupportedEncodingException usee) { - - this.tleByteName = name.getBytes(); - this.tleByteValue = value.getBytes(); - log.warn( - "Constructor:: UnsupportedEncodingException translating the name " - + name); - - } - + this.name = name; + this.value = value; } - /** - * Accessor method to obtain the byte array AFP datastream for the - * TagLogicalElement. - * @param os The outputsteam stream - * @throws java.io.IOException if an I/O exception occurred - */ - public void writeDataStream(OutputStream os) throws IOException { + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { - byte[] data = new byte[17 + tleName.length() + tleValue.length()]; + byte[] data = new byte[17 + name.length() + value.length()]; data[0] = 0x5A; // Set the total record length byte[] rl1 - = BinaryUtils.convert(16 + tleName.length() + tleValue.length(), 2); + = BinaryUtils.convert(16 + name.length() + value.length(), 2); //Ignore first byte data[1] = rl1[0]; data[2] = rl1[1]; // Structured field ID for a TLE data[3] = (byte) 0xD3; - data[4] = (byte) 0xA0; - data[5] = (byte) 0x90; + data[4] = (byte) Type.ATTRIBUTE; + data[5] = (byte) Category.PROCESS_ELEMENT; data[6] = 0x00; // Reserved data[7] = 0x00; // Reserved @@ -122,12 +92,25 @@ public class TagLogicalElement extends AbstractAFPObject { //Use 2 triplets, attrubute name and value (the key for indexing) - byte[] rl2 = BinaryUtils.convert(tleName.length() + 4, 1); + byte[] rl2 = BinaryUtils.convert(name.length() + 4, 1); data[9] = rl2[0]; // length of the triplet, including this field data[10] = 0x02; //Identifies it as a FQN triplet data[11] = 0x0B; // GID format data[12] = 0x00; + byte[] tleByteName = null; + byte[] tleByteValue = null; + try { + tleByteName = name.getBytes(AFPConstants.EBCIDIC_ENCODING); + tleByteValue = value.getBytes(AFPConstants.EBCIDIC_ENCODING); + } catch (UnsupportedEncodingException usee) { + tleByteName = name.getBytes(); + tleByteValue = value.getBytes(); + log.warn( + "Constructor:: UnsupportedEncodingException translating the name " + + name); + } + int pos = 13; for (int i = 0; i < tleByteName.length; i++) { data[pos++] = tleByteName[i]; diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java index 29ac9eb5d..5d4523777 100644 --- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java +++ b/src/java/org/apache/fop/afp/modca/TagLogicalElementBean.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.modca; +package org.apache.fop.afp.modca; /** * The TagLogicalElementBean provides a bean for holding the attributes of @@ -34,6 +34,7 @@ public class TagLogicalElementBean { /** * Constructor for the TagLogicalElementBean. + * * @param key the key attribute * @param value the value attribute */ @@ -44,6 +45,7 @@ public class TagLogicalElementBean { /** * Getter for the key attribute. + * * @return the key */ public String getKey() { @@ -52,6 +54,7 @@ public class TagLogicalElementBean { /** * Getter for the value attribute. + * * @return the value */ public String getValue() { diff --git a/src/java/org/apache/fop/afp/modca/package.html b/src/java/org/apache/fop/afp/modca/package.html new file mode 100644 index 000000000..572743558 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.modca Package</TITLE> +<BODY> +<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) structured objects.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java new file mode 100644 index 000000000..4e75d4204 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/AbstractTriplet.java @@ -0,0 +1,120 @@ +/* + * 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.afp.modca.triplets; + +import org.apache.fop.afp.Streamable; +import org.apache.fop.afp.StructuredData; + +/** + * A simple implementation of a MOD:CA triplet + */ +public abstract class AbstractTriplet implements Streamable, StructuredData { + public static final byte CODED_GRAPHIC_CHARACTER_SET_GLOBAL_IDENTIFIER = 0x01; + + /** Triplet identifiers */ + public static final byte FULLY_QUALIFIED_NAME = 0x02; + public static final byte MAPPING_OPTION = 0x04; + public static final byte OBJECT_CLASSIFICATION = 0x10; + public static final byte MODCA_INTERCHANGE_SET = 0x18; + public static final byte FONT_DESCRIPTOR_SPECIFICATION = 0x1F; + public static final byte OBJECT_FUNCTION_SET_SPECIFICATION = 0x21; + public static final byte EXTENDED_RESOURCE_LOCAL_IDENTIFIER = 0x22; + public static final byte RESOURCE_LOCAL_IDENTIFIER = 0x24; + public static final byte RESOURCE_SECTION_NUMBER = 0x25; + public static final byte CHARACTER_ROTATION = 0x26; + public static final byte OBJECT_BYTE_OFFSET = 0x2D; + public static final byte ATTRIBUTE_VALUE = 0x36; + public static final byte DESCRIPTOR_POSITION = 0x43; + public static final byte MEDIA_EJECT_CONTROL = 0x45; + public static final byte PAGE_OVERLAY_CONDITIONAL_PROCESSING = 0x46; + public static final byte RESOURCE_USAGE_ATTRIBUTE = 0x47; + public static final byte MEASUREMENT_UNITS = 0x4B; + public static final byte OBJECT_AREA_SIZE = 0x4C; + public static final byte AREA_DEFINITION = 0x4D; + public static final byte COLOR_SPECIFICATION = 0x4E; + public static final byte ENCODING_SCHEME_ID = 0x50; + public static final byte MEDIUM_MAP_PAGE_NUMBER = 0x56; + public static final byte OBJECT_BYTE_EXTENT = 0x57; + public static final byte OBJECT_STRUCTURED_FIELD_OFFSET = 0x58; + public static final byte OBJECT_STRUCTURED_FIELD_EXTENT = 0x59; + public static final byte OBJECT_OFFSET = 0x5A; + public static final byte FONT_HORIZONTAL_SCALE_FACTOR = 0x5D; + public static final byte OBJECT_COUNT = 0x5E; + public static final byte OBJECT_DATE_AND_TIMESTAMP = 0x62; + public static final byte COMMENT = 0x65; + public static final byte MEDIUM_ORIENTATION = 0x68; + public static final byte RESOURCE_OBJECT_INCLUDE = 0x6C; + public static final byte PRESENTATION_SPACE_RESET_MIXING = 0x70; + public static final byte PRESENTATION_SPACE_MIXING_RULE = 0x71; + public static final byte UNIVERSAL_DATE_AND_TIMESTAMP = 0x72; + public static final byte TONER_SAVER = 0x74; + public static final byte COLOR_FIDELITY = 0x75; + public static final byte FONT_FIDELITY = 0x78; + public static final byte ATTRIBUTE_QUALIFIER = (byte)0x80; + public static final byte PAGE_POSITION_INFORMATION = (byte)0x81; + public static final byte PARAMETER_VALUE = (byte)0x82; + public static final byte PRESENTATION_CONTROL = (byte)0x83; + public static final byte FONT_RESOLUTION_AND_METRIC_TECHNOLOGY = (byte)0x84; + public static final byte FINISHING_OPERATION = (byte)0x85; + public static final byte TEXT_FIDELITY = (byte)0x86; + public static final byte MEDIA_FIDELITY = (byte)0x87; + public static final byte FINISHING_FIDELITY = (byte)0x88; + public static final byte DATA_OBJECT_FONT_DESCRIPTOR = (byte)0x8B; + public static final byte LOCALE_SELECTOR = (byte)0x8C; + public static final byte UP3I_FINISHING_OPERATION = (byte)0x8E; + public static final byte COLOR_MANAGEMENT_RESOURCE_DESCRIPTOR = (byte)0x91; + public static final byte RENDERING_INTENT = (byte)0x95; + public static final byte CMR_TAG_FIDELITY = (byte)0x96; + public static final byte DEVICE_APPEARANCE = (byte)0x97; + + /** the triplet identifier */ + protected final byte id; + + /** + * Constructor + * + * @param id the triplet identifier (see static definitions above) + */ + public AbstractTriplet(byte id) { + this.id = id; + } + + /** + * Returns the triplet identifier + * + * @return the triplet identifier + */ + public byte getId() { + return this.id; + } + + /** + * Returns the structured triplet data array + * + * @return the structured triplet data array + */ + public byte[] getData() { + int dataLen = getDataLength(); + byte[] data = new byte[dataLen]; + data[0] = (byte)dataLen; + data[1] = id; + return data; + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java new file mode 100644 index 000000000..9b15de8c1 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/CommentTriplet.java @@ -0,0 +1,52 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.AFPConstants; + +/** + * An inline comment triplet. + */ +public class CommentTriplet extends AbstractTriplet { + + private final String commentString; + + public CommentTriplet(byte id, String commentString) { + super(id); + this.commentString = commentString; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2 + commentString.length(); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + byte[] strData = commentString.getBytes(AFPConstants.EBCIDIC_ENCODING); + System.arraycopy(strData, 0, data, 2, strData.length); + os.write(data); + } + +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java new file mode 100644 index 000000000..cff6400af --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/DescriptorPositionTriplet.java @@ -0,0 +1,53 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Associates an ObjectAreaPosition with and ObjectAreaDescriptor structured field + */ +public class DescriptorPositionTriplet extends AbstractTriplet { + + private final byte oapId; + + /** + * Main constructor + * + * @param oapId the object area position id + */ + public DescriptorPositionTriplet(byte oapId) { + super(DESCRIPTOR_POSITION); + this.oapId = oapId; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 3; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = oapId; + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java new file mode 100644 index 000000000..af9452fcb --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/ExtendedResourceLocalIdentifierTriplet.java @@ -0,0 +1,75 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Extended Resource Local Identifier triplet specifies a resource type and a + * four byte local identifier or LID. The LID usually is associated with a specific + * resource name by a map structured field, such as a Map Data Resource structured + * field, or a Map Media Type structured field. + */ +public class ExtendedResourceLocalIdentifierTriplet extends AbstractTriplet { + + /** the image resource type */ + public static final byte TYPE_IMAGE_RESOURCE = 0x10; + + /** the retired value type */ + public static final byte TYPE_RETIRED_VALUE = 0x30; + + /** the retired value type */ + public static final byte TYPE_MEDIA_RESOURCE = 0x40; + + /** the resource type */ + private final byte type; + + /** the resource local id */ + private final int localId; + + /** + * Main constructor + * + * @param type the resource type + * @param localId the resource local id + */ + public ExtendedResourceLocalIdentifierTriplet(byte type, int localId) { + super(AbstractTriplet.EXTENDED_RESOURCE_LOCAL_IDENTIFIER); + this.type = type; + this.localId = localId; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = type; + byte[] resLID = BinaryUtils.convert(localId, 4); // 4 bytes + System.arraycopy(resLID, 0, data, 3, resLID.length); + os.write(data); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 7; + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java new file mode 100644 index 000000000..55653457c --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -0,0 +1,208 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.fop.afp.AFPConstants; + +/** + * A Fully Qualified Name triplet enable the identification and referencing of + * objects using Gloabl Identifiers (GIDs). + */ +public class FullyQualifiedNameTriplet extends AbstractTriplet { + + // Specifies how the GID will be used + + /** This GID replaces the first parameter in the structured field that contains a GID name. */ + public static final byte TYPE_REPLACE_FIRST_GID_NAME = 0x01; + + /** This triplet contains the name of a font family. */ + public static final byte TYPE_FONT_FAMILY_NAME = 0x07; + + /** This triplet contains the name of a font typeface. */ + public static final byte TYPE_FONT_TYPEFACE_NAME = 0x08; + + /** This triplet specifies a reference to the MO:DCA resource hierarchy. */ + public static final byte TYPE_MODCA_RESOURCE_HIERARCHY_REF = 0x09; + + /** The triplet contains a GID reference to a begin resource group structured field. */ + public static final byte TYPE_BEGIN_RESOURCE_GROUP_REF = 0x0A; + + /** The triplet contains a GID reference to a document attribute. */ + public static final byte TYPE_ATTRIBUTE_GID = 0x0B; + + /** The triplet contains the GID of a process element. */ + public static final byte TYPE_PROCESS_ELEMENT_GID = 0x0C; + + /** The triplet contains a reference to a begin page group structured field. */ + public static final byte TYPE_BEGIN_PAGE_GROUP_REF = 0x0D; + + /** The triplet contains a reference to a media type. */ + public static final byte TYPE_MEDIA_TYPE_REF = 0x11; + + /** The triplet contains a reference to a color management resource. */ + public static final byte TYPE_COLOR_MANAGEMENT_RESOURCE_REF = 0x41; + + /** The triplet contains a reference to a data-object font file that defines a base font. */ + public static final byte TYPE_DATA_OBJECT_FONT_BASE_FONT_ID = 0x6E; + + /** The triplet contains a reference to a data-object font file that defines a linked font. */ + public static final byte TYPE_DATA_OBJECT_FONT_LINKED_FONT_ID = 0x7E; + + /** The triplet contains a reference to a begin document structured field. */ + public static final byte TYPE_BEGIN_DOCUMENT_REF = (byte)0x83; + + /** + * The triplet contains a reference to a begin structured field associated with a resource; + * or contains a GID reference to a coded font. + */ + public static final byte TYPE_BEGIN_RESOURCE_OBJECT_REF = (byte)0x84; + + /** + * The triplet contains a GID reference to a code page that specifies the code points and + * graphic character names for a coded font. + */ + public static final byte TYPE_CODE_PAGE_NAME_REF = (byte)0x85; + + /** + * The triplet contains a GID name reference to a font character set that specifies + * a set of graphics characters. + */ + public static final byte TYPE_FONT_CHARSET_NAME_REF = (byte)0x86; + + /** The triplet contains a GID reference to a begin page structured field. */ + public static final byte TYPE_BEGIN_PAGE_REF = (byte)0x87; + + /** The triplet contains a GID reference to a begin medium map structured field. */ + public static final byte TYPE_BEGIN_MEDIUM_MAP_REF = (byte)0x8D; + + /** + * The triplet contains a GID reference to a coded font, which identifies a specific + * code page and a specific font character set. + */ + public static final byte TYPE_CODED_FONT_NAME_REF = (byte)0x8E; + + /** The triplet contains a GID reference to a begin document index structured field. */ + public static final byte TYPE_BEGIN_DOCUMENT_INDEX_REF = (byte)0x98; + + /** The triplet contains a GID reference to a begin overlay structured field. */ + public static final byte TYPE_BEGIN_OVERLAY_REF = (byte)0xB0; + + /** The triplet contains a GID reference to a resource used by a data object. */ + public static final byte TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF = (byte)0xBE; + + /** The triplet contains a GID reference to an index element structured field. */ + public static final byte TYPE_INDEX_ELEMENT_GID = (byte)0xCA; + + /** + * The triplet contains a reference to other object data which may or may + * not be defined by an IBM presentation architecture. + */ + public static final byte TYPE_OTHER_OBJECT_DATA_REF = (byte)0xCE; + + /** + * The triplet contains a reference to a resource used by a data object. + * The GID may be a filename or any other identifier associated with the + * resource and is used to located the resource object in the resource hierarchy. + * The data object that uses the resource may or may not be defined by an + * IBM presentation architecture. + */ + public static final byte TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF = (byte)0xDE; + + + // GID Format + + /** The GID is a character encoded name. */ + public static final byte FORMAT_CHARSTR = (byte)0x00; + + /** the GID is a ASN.1 object identifier (OID). */ + public static final byte FORMAT_OID = (byte)0x10; + + /** the GID is a uniform resource locator (URL). */ + public static final byte FORMAT_URL = (byte)0x20; + + /** the fully qualified name type */ + private final byte type; + + /** the fully qualified name format */ + private final byte format; + + /** the actual fully qualified name */ + private final String fqName; + + /** + * Main constructor + * + * @param type the fully qualified name type + * @param format the fully qualified name format + * @param fqName the fully qualified name + */ + public FullyQualifiedNameTriplet(byte type, byte format, String fqName) { + super(FULLY_QUALIFIED_NAME); + this.type = type; + this.format = format; + this.fqName = fqName; + } + + /** + * Returns the actual fully qualified name + * + * @return the actual fully qualified name + */ + public String getFullyQualifiedName() { + return fqName; + } + + /** {@inheritDoc} */ + public String toString() { + return this.fqName; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 4 + fqName.length(); + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = type; + data[3] = format; + + // FQName + byte[] fqNameBytes; + String encoding = AFPConstants.EBCIDIC_ENCODING; + if (format == FORMAT_URL) { + encoding = AFPConstants.US_ASCII_ENCODING; + } + try { + fqNameBytes = fqName.getBytes(encoding); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException( + encoding + " encoding failed"); + } + System.arraycopy(fqNameBytes, 0, data, 4, fqNameBytes.length); + + os.write(data); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java new file mode 100644 index 000000000..0d20d0227 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/MappingOptionTriplet.java @@ -0,0 +1,87 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Specifies the mapping of data object presentation space to object area + */ +public class MappingOptionTriplet extends AbstractTriplet { + /** + * the data object is placed in the upper left corner, all data must be presented + * within the object area extents + */ + public static final byte POSITION = 0x00; + + /** + * the data object is placed in the upper left corner, all data that falls within + * the object area extents will be presented but data that falls outside will not be presented + */ + public static final byte POSITION_AND_TRIM = 0x10; + + /** + * the data object is centred and symmetrically scaled up or down + * while preserving aspect ratio + */ + public static final byte SCALE_TO_FIT = 0x20; + + /** + * the data object is centred, all data that falls within the object area extents + * will be presented but data that falls outside will not be presented + */ + public static final byte CENTER_AND_TRIM = 0x30; + +// public static final byte MIGRATION_MAPPING_1 = 0x41; +// public static final byte MIGRATION_MAPPING_2 = 0x42; +// public static final byte MIGRATION_MAPPING_3 = 0x50; + + /** the data object is centred, aspect ratio is not always preserved */ + public static final byte SCALE_TO_FILL = 0x60; + + /** used to map ip3i print data objects */ + public static final byte UP3I_PRINT_DATA = 0x70; + + private final byte mapValue; + + /** + * Main constructor + * + * @param mapValue the mapping option to use + */ + public MappingOptionTriplet(byte mapValue) { + super(AbstractTriplet.MAPPING_OPTION); + this.mapValue = mapValue; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 3; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = mapValue; + + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java new file mode 100644 index 000000000..68d3fc40c --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/MeasurementUnitsTriplet.java @@ -0,0 +1,72 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Measurement Units triplet is used to specify the units of measure + * for a presentation space + */ +public class MeasurementUnitsTriplet extends AbstractTriplet { + + private static final byte TEN_INCHES = 0x00; + private static final byte TEN_CM = 0x01; + private final int xRes; + private final int yRes; + + /** + * Main constructor + * + * @param xRes units per base on the x-axis + * @param yRes units per base on the y-axis + */ + public MeasurementUnitsTriplet(int xRes, int yRes) { + super(MEASUREMENT_UNITS); + this.xRes = xRes; + this.yRes = yRes; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 8; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + + data[2] = TEN_INCHES; // XoaBase + data[3] = TEN_INCHES; // YoaBase + + byte[] xUnits = BinaryUtils.convert(xRes * 10, 2); + data[4] = xUnits[0]; // XoaUnits (x units per unit base) + data[5] = xUnits[1]; + + byte[] yUnits = BinaryUtils.convert(yRes * 10, 2); + data[6] = yUnits[0]; // YoaUnits (y units per unit base) + data[7] = yUnits[1]; + + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java new file mode 100644 index 000000000..3d408639e --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/ObjectAreaSizeTriplet.java @@ -0,0 +1,84 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Object Area Size triplet is used to specify the extent of an object area + * in the X and Y directions + */ +public class ObjectAreaSizeTriplet extends AbstractTriplet { + + private final int x; + private final int y; + private final byte type; + + /** + * Main constructor + * + * @param x the object area extent for the X axis + * @param y the object area extent for the Y axis + * @param type the object area size type + */ + public ObjectAreaSizeTriplet(int x, int y, byte type) { + super(AbstractTriplet.OBJECT_AREA_SIZE); + this.x = x; + this.y = y; + this.type = type; + } + + /** + * Main constructor + * + * @param x the object area extent for the X axis + * @param y the object area extent for the Y axis + */ + public ObjectAreaSizeTriplet(int x, int y) { + this(x, y, (byte)0x02); + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 9; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + + data[2] = type; // SizeType + + byte[] xOASize = BinaryUtils.convert(x, 3); + data[3] = xOASize[0]; // XoaSize - Object area extent for X axis + data[4] = xOASize[1]; + data[5] = xOASize[2]; + + byte[] yOASize = BinaryUtils.convert(y, 3); + data[6] = yOASize[0]; // YoaSize - Object area extent for Y axis + data[7] = yOASize[1]; + data[8] = yOASize[2]; + + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java new file mode 100644 index 000000000..3aaa6969a --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/ObjectByteExtentTriplet.java @@ -0,0 +1,56 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.util.BinaryUtils; + +/** + * The Object Byte Extent triplet is used to specify the number of bytes contained in an object + */ +public class ObjectByteExtentTriplet extends AbstractTriplet { + + private final int byteExt; + + /** + * Main constructor + * + * @param byteExt the number of bytes contained in the object + */ + public ObjectByteExtentTriplet(int byteExt) { + super(OBJECT_BYTE_EXTENT); + this.byteExt = byteExt; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 6; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + byte[] extData = BinaryUtils.convert(byteExt, 4); + System.arraycopy(extData, 0, data, 2, extData.length); + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java new file mode 100644 index 000000000..9c2ab7bc4 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/ObjectClassificationTriplet.java @@ -0,0 +1,214 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.fop.afp.AFPConstants; +import org.apache.fop.afp.modca.Registry.ObjectType; +import org.apache.fop.afp.util.StringUtils; + +/** + * The Object Classification is used to classify and identify object data. + * The object data may or may not be defined by an IBM presentation architecture + */ +public class ObjectClassificationTriplet extends AbstractTriplet { + + /** + * The scope of this object is the including page or overlay + */ + public static final byte CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT = 0x01; + + /** + * The scope of this object is not defined + */ + public static final byte CLASS_TIME_VARIANT_PRESENTATION_OBJECT = 0x10; + + /** + * This is not a presentation object, the scope of this object is not defined + */ + public static final byte CLASS_EXECUTABLE_PROGRAM = 0x20; + + /** + * Setup information file, document level. This is not a presentation object, + */ + public static final byte CLASS_SETUP_FILE = 0x30; + + /** + * This is a resource used by a presentation object that may itself be a resource. + * The scope of the resource is the object that uses the resource. + */ + public static final byte CLASS_SECONDARY_RESOURCE = 0x40; + + /** + * Data object font. This is a non-FOCA font resource used to present + * text in a data object. The scope of the resource is the object that + * uses the resource. + */ + public static final byte CLASS_DATA_OBJECT_FONT = 0x41; + + /** the object class */ + private final byte objectClass; + + /** the object type */ + private final ObjectType objectType; + + /** whether the container has an object environment group */ + private final boolean containerHasOEG; + + /** whether the data resides within the container */ + private final boolean dataInContainer; + + /** whether the data resides within the object container data */ + private final boolean dataInOCD; + + /** the object level (version) */ + private final String objectLevel; + + /** the company/organization name */ + private final String companyName; + + + /** + * Main constructor + * + * @param objectClass the object class type + * @param objectType the object type registry entry + * @param dataInContainer whether the data resides in the container + * @param containerHasOEG whether the container has an object environment group + * @param dataInOCD whether the data resides in a object container data structured field + */ + public ObjectClassificationTriplet(byte objectClass, ObjectType objectType, + boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD) { + // no object level or company name specified + this(objectClass, objectType, dataInContainer, containerHasOEG, dataInOCD, null, null); + } + + /** + * Fully parameterized constructor + * + * @param objectClass the object class type + * @param objectType the object type registry entry + * @param dataInContainer whether the data resides in the container + * @param containerHasOEG whether the container has an object environment group + * @param dataInOCD whether the data resides in a object container data structured field + * @param objLev the release level or version number of the object type + * @param compName the name of the company or organization that owns the object definition + */ + public ObjectClassificationTriplet(byte objectClass, ObjectType objectType, + boolean dataInContainer, boolean containerHasOEG, boolean dataInOCD, + String objLev, String compName) { + super(OBJECT_CLASSIFICATION); + + this.objectClass = objectClass; + if (objectType == null) { + throw new IllegalArgumentException("MO:DCA Registry object type is null"); + } + this.objectType = objectType; + this.dataInContainer = dataInContainer; + this.containerHasOEG = containerHasOEG; + this.dataInOCD = dataInOCD; + this.objectLevel = objLev; + this.companyName = compName; + } + + /** + * Returns the structured field flags + * + * @param dataInContainer true if the object data in carried in the object container + * @param containerHasOEG true if the object container has an object environment group + * @param dataInOCD true if the object container data carries the object data + * + * @return the byte value of this structure + */ + public byte[] getStructureFlagsAsBytes(boolean dataInContainer, boolean containerHasOEG, + boolean dataInOCD) { + byte[] strucFlgs = new byte[2]; + // Object Container (BOC/EOC) + if (dataInContainer) { + strucFlgs[0] |= 3 << 6; + } else { + strucFlgs[0] |= 1 << 6; + } + // Object Environment Group (OEG) + if (containerHasOEG) { + strucFlgs[0] |= 3 << 4; + } else { + strucFlgs[0] |= 1 << 4; + } + // Object Container Data (OCD) structured fields + if (dataInOCD) { + strucFlgs[0] |= 3 << 2; + } else { + strucFlgs[0] |= 1 << 2; + } + strucFlgs[1] = 0x00; + return strucFlgs; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 96; + } + + private static final int OBJECT_LEVEL_LEN = 8; + private static final int OBJECT_TYPE_NAME_LEN = 32; + private static final int COMPANY_NAME_LEN = 32; + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = 0x00; // reserved (must be zero) + data[3] = objectClass; // ObjClass + data[4] = 0x00; // reserved (must be zero) + data[5] = 0x00; // reserved (must be zero) + + // StrucFlgs - Information on the structure of the object container + byte[] structureFlagsBytes = getStructureFlagsAsBytes(dataInContainer, containerHasOEG, dataInOCD); + data[6] = structureFlagsBytes[0]; + data[7] = structureFlagsBytes[1]; + + byte[] objectIdBytes = objectType.getOID(); + // RegObjId - MOD:CA-registered ASN.1 OID for object type (8-23) + System.arraycopy(objectIdBytes, 0, data, 8, objectIdBytes.length); + + // ObjTpName - name of object type (24-55) + byte[] objectTypeNameBytes; + objectTypeNameBytes + = StringUtils.rpad(objectType.getName(), ' ', OBJECT_TYPE_NAME_LEN).getBytes( + AFPConstants.EBCIDIC_ENCODING); + System.arraycopy(objectTypeNameBytes, 0, data, 24, objectTypeNameBytes.length); + + // ObjLev - release level or version number of object type (56-63) + byte[] objectLevelBytes; + objectLevelBytes = StringUtils.rpad(objectLevel, ' ', OBJECT_LEVEL_LEN).getBytes( + AFPConstants.EBCIDIC_ENCODING); + System.arraycopy(objectLevelBytes, 0, data, 56, objectLevelBytes.length); + + // CompName - name of company or organization that owns object definition (64-95) + byte[] companyNameBytes; + companyNameBytes = StringUtils.rpad(companyName, ' ', COMPANY_NAME_LEN).getBytes( + AFPConstants.EBCIDIC_ENCODING); + System.arraycopy(companyNameBytes, 0, data, 64, companyNameBytes.length); + + os.write(data); + } +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java new file mode 100644 index 000000000..b93ec5477 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceMixingRulesTriplet.java @@ -0,0 +1,80 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * This triplet is used to specify the resulting appearance when data in a new + * presentation space is merged with data in an existing presentation space. + */ +public class PresentationSpaceMixingRulesTriplet extends AbstractTriplet { + + /** background on background mixing rule */ + public static final byte RULE_BACK_ON_BACK = 0x70; + + /** background on foreground mixing rule */ + public static final byte RULE_BACK_ON_FORE = 0x71; + + /** foreground on background mixing rule */ + public static final byte RULE_FORE_ON_BACK = 0x72; + + /** foreground on foreground mixing rule */ + public static final byte RULE_FORE_ON_FORE = 0x73; + + + /** overpaint */ + public static final byte OVERPAINT = (byte)0x01; + + /** underpaint */ + public static final byte UNDERPAINT = (byte)0x02; + + /** blend */ + public static final byte BLEND = (byte)0x03; + + /** MO:DCA default mixing */ + public static final byte DEFAULT = (byte)0xFF; + + /** the mixing rules */ + private final byte[] rules; + + /** + * Main constructor + * + * @param rules the mixing rules + */ + public PresentationSpaceMixingRulesTriplet(byte[] rules) { + super(PRESENTATION_SPACE_MIXING_RULE); + this.rules = rules; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 2 + rules.length; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + System.arraycopy(rules, 0, data, 2, rules.length); + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java new file mode 100644 index 000000000..cecd40910 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/PresentationSpaceResetMixingTriplet.java @@ -0,0 +1,66 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * This triplet is used to specify the resulting appearance when data in a new + * presentation space is merged with data in an existing presentation space. + */ +public class PresentationSpaceResetMixingTriplet extends AbstractTriplet { + + /** + * Do not reset to the color of the medium prior to + * placing data into this MO:DCA presentation space. + */ + public static final byte NOT_RESET = 0x00; + + /** + * Reset to the color of the medium prior to placing + * data into this MO:DCA presentation space. + */ + public static final byte RESET = 0x01; + + private final byte backgroundMixFlag; + + /** + * Main constructor + * + * @param backgroundMixFlag the background mixing flag + */ + public PresentationSpaceResetMixingTriplet(byte backgroundMixFlag) { + super(PRESENTATION_SPACE_RESET_MIXING); + this.backgroundMixFlag = backgroundMixFlag; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 3; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = backgroundMixFlag; + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java new file mode 100644 index 000000000..e4b13177d --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/ResourceObjectTypeTriplet.java @@ -0,0 +1,54 @@ +/* + * 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.afp.modca.triplets; + +import java.io.IOException; +import java.io.OutputStream; + +/** A Resource Object Type Triplet */ +public class ResourceObjectTypeTriplet extends AbstractTriplet { + + private static final byte RESOURCE_OBJECT = 0x21; + + /** the resource object type */ + private final byte objectType; + + /** + * Main constructor + * + * @param objectType the resource object type + */ + public ResourceObjectTypeTriplet(byte objectType) { + super(RESOURCE_OBJECT); + this.objectType = objectType; + } + + /** {@inheritDoc} */ + public int getDataLength() { + return 10; + } + + /** {@inheritDoc} */ + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = objectType; + os.write(data); + } +} diff --git a/src/java/org/apache/fop/afp/modca/triplets/package.html b/src/java/org/apache/fop/afp/modca/triplets/package.html new file mode 100644 index 000000000..99ae55a45 --- /dev/null +++ b/src/java/org/apache/fop/afp/modca/triplets/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.modca.triplets Package</TITLE> +<BODY> +<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) triplet classes.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/package.html b/src/java/org/apache/fop/afp/package.html new file mode 100644 index 000000000..d67498159 --- /dev/null +++ b/src/java/org/apache/fop/afp/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp Package</TITLE> +<BODY> +<P>Contains an AFP library.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java new file mode 100644 index 000000000..48c1001ef --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPBridgeContext.java @@ -0,0 +1,108 @@ +/* + * 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.afp.svg; + +import java.awt.geom.AffineTransform; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.DocumentLoader; +import org.apache.batik.bridge.UserAgent; +import org.apache.batik.gvt.TextPainter; +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.svg.AbstractFOPBridgeContext; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + +/** + * An AFP specific implementation of a Batik BridgeContext + */ +public class AFPBridgeContext extends AbstractFOPBridgeContext { + + private final AFPGraphics2D g2d; + + /** + * Constructs a new bridge context. + * + * @param userAgent the user agent + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null + * @param g2d an AFPGraphics 2D implementation + */ + public AFPBridgeContext(UserAgent userAgent, FontInfo fontInfo, + ImageManager imageManager, ImageSessionContext imageSessionContext, + AffineTransform linkTransform, AFPGraphics2D g2d) { + super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform); + this.g2d = g2d; + } + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param loader the Document Loader to use for referenced documents. + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param linkTransform AffineTransform to properly place links, + * may be null + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null + * @param an AFPGraphics 2D implementation + */ + public AFPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader, + FontInfo fontInfo, ImageManager imageManager, + ImageSessionContext imageSessionContext, + AffineTransform linkTransform, AFPGraphics2D g2d) { + super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform); + this.g2d = g2d; + } + + /** {@inheritDoc} */ + public void registerSVGBridges() { + super.registerSVGBridges(); + + if (fontInfo != null) { + AFPTextHandler textHandler = new AFPTextHandler(fontInfo); + g2d.setCustomTextHandler(textHandler); + + TextPainter textPainter = new AFPTextPainter(textHandler); + setTextPainter(textPainter); + + putBridge(new AFPTextElementBridge(textPainter)); + } + + putBridge(new AFPImageElementBridge()); + } + + /** {@inheritDoc} */ + public BridgeContext createBridgeContext() { + return new AFPBridgeContext(getUserAgent(), getDocumentLoader(), + fontInfo, + getImageManager(), + getImageSessionContext(), + linkTransform, g2d); + } + +} diff --git a/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java b/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java new file mode 100644 index 000000000..76d6396e3 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java @@ -0,0 +1,150 @@ +/* + * 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.afp.svg; + +import java.awt.GraphicsDevice; +import java.awt.Rectangle; +import java.awt.Transparency; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.svg.GraphicsConfiguration; + +/** + * Our implementation of the class that returns information about + * roughly what we can handle and want to see (alpha for example). + */ +public class AFPGraphicsConfiguration extends GraphicsConfiguration { + // We use this to get a good colormodel.. + private static final BufferedImage BI_WITH_ALPHA + = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + // We use this to get a good colormodel.. + private static final BufferedImage BI_WITHOUT_ALPHA + = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + + /** + * Construct a buffered image with an alpha channel, unless + * transparencty is OPAQUE (no alpha at all). + * + * @param width the width of the image + * @param height the height of the image + * @param transparency the alpha value of the image + * @return the new buffered image + */ + public BufferedImage createCompatibleImage(int width, int height, + int transparency) { + if (transparency == Transparency.OPAQUE) { + return new BufferedImage(width, height, + BufferedImage.TYPE_INT_RGB); + } else { + return new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + } + } + + /** + * Construct a buffered image with an alpha channel. + * + * @param width the width of the image + * @param height the height of the image + * @return the new buffered image + */ + public BufferedImage createCompatibleImage(int width, int height) { + return new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + } + + /** + * TODO: This should return the page bounds in Pts, + * I couldn't figure out how to get this for the current + * page (this still works for now, + * but it should be fixed...). + * + * @return the bounds of the page + */ + public Rectangle getBounds() { + return null; + } + + /** + * Return a good default color model for this 'device'. + * @return the colour model for the configuration + */ + public ColorModel getColorModel() { + return BI_WITH_ALPHA.getColorModel(); + } + + /** + * Return a good color model given <tt>transparency</tt> + * + * @param transparency the alpha value for the colour model + * @return the colour model for the configuration + */ + public ColorModel getColorModel(int transparency) { + if (transparency == Transparency.OPAQUE) { + return BI_WITHOUT_ALPHA.getColorModel(); + } else { + return BI_WITH_ALPHA.getColorModel(); + } + } + + private static final Log log = LogFactory.getLog(AFPGraphicsConfiguration.class); + + private AffineTransform defaultTransform = null; + private AffineTransform normalizingTransform = null; + private final GraphicsDevice graphicsDevice = new AFPGraphicsDevice(this);; + + /** + * The default transform (1:1). + * + * @return the default transform for the configuration + */ + public AffineTransform getDefaultTransform() { + log.debug("getDefaultTransform()"); + if (defaultTransform == null) { + defaultTransform = new AffineTransform(); + } + return defaultTransform; + } + + /** + * The normalizing transform (1:1) (since we currently + * render images at 72dpi, which we might want to change + * in the future). + * + * @return the normalizing transform for the configuration + */ + public AffineTransform getNormalizingTransform() { + log.debug("getNormalizingTransform()"); + if (normalizingTransform == null) { + normalizingTransform = new AffineTransform(2, 0, 0, 2, 0, 0); + } + return normalizingTransform; + } + + /** {@inheritDoc} */ + public GraphicsDevice getDevice() { + log.debug("getDevice()"); + return graphicsDevice; + } +} diff --git a/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java b/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java new file mode 100644 index 000000000..daa25aaa0 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java @@ -0,0 +1,80 @@ +/* + * 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.afp.svg; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; + +/** + * This implements the GraphicsDevice interface as appropriate for + * an AFPGraphics2D. + */ +public class AFPGraphicsDevice extends GraphicsDevice { + + /** + * The Graphics Config that created us... + */ + protected GraphicsConfiguration gc; + + /** + * Create a new AF{ graphics device. + * + * @param gc The graphics configuration we should reference + */ + public AFPGraphicsDevice(AFPGraphicsConfiguration gc) { + this.gc = gc; + } + + /** + * Return an array of our one GraphicsConfig + * + * @return an array containing the one graphics configuration + */ + public GraphicsConfiguration[] getConfigurations() { + return new GraphicsConfiguration[] {gc}; + } + + /** + * Return out sole GraphicsConfig. + * + * @return the graphics configuration that created this object + */ + public GraphicsConfiguration getDefaultConfiguration() { + return this.gc; + } + + /** + * Generate an IdString.. + * + * @return the ID string for this device, uses toString + */ + public String getIDstring() { + return toString(); + } + + /** + * Let the caller know that we are "a printer" + * + * @return the type which is always printer + */ + public int getType() { + return GraphicsDevice.TYPE_PRINTER; + } +} diff --git a/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java new file mode 100644 index 000000000..63661940d --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java @@ -0,0 +1,40 @@ +/* + * 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.afp.svg; + +import org.apache.fop.svg.AbstractFOPImageElementBridge; +import org.apache.xmlgraphics.image.loader.ImageFlavor; + +/** + * An AFP specific implementation of a Batik SVGImageElementBridge + */ +public class AFPImageElementBridge extends AbstractFOPImageElementBridge { + + private final ImageFlavor[] supportedFlavors = new ImageFlavor[] + {ImageFlavor.RAW_JPEG, + ImageFlavor.RAW_CCITTFAX, + ImageFlavor.GRAPHICS2D, + ImageFlavor.XML_DOM}; + + /** {@inheritDoc} */ + protected ImageFlavor[] getSupportedFlavours() { + return supportedFlavors; + } +} diff --git a/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java new file mode 100644 index 000000000..31aa3fe60 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java @@ -0,0 +1,42 @@ +/* + * 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.afp.svg; + +import org.apache.batik.gvt.TextPainter; +import org.apache.fop.svg.AbstractFOPTextElementBridge; + +/** + * Bridge class for the <text> element. + * This bridge will use the direct text painter if the text + * for the element is simple. + */ +public class AFPTextElementBridge extends AbstractFOPTextElementBridge { + + /** + * Constructs a new bridge for the <text> element. + * + * @param textPainter the text painter to use + */ + public AFPTextElementBridge(TextPainter textPainter) { + super(textPainter); + } + +} + diff --git a/src/java/org/apache/fop/afp/svg/AFPTextHandler.java b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java new file mode 100644 index 000000000..f44fde269 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPTextHandler.java @@ -0,0 +1,145 @@ +/* + * 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.afp.svg; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.io.IOException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.fonts.AFPFont; +import org.apache.fop.afp.fonts.AFPFontAttributes; +import org.apache.fop.afp.fonts.AFPPageFonts; +import org.apache.fop.afp.modca.GraphicsObject; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.svg.FOPTextHandler; + +/** + * Specialized TextHandler implementation that the AFPGraphics2D class delegates to to paint text + * using AFP GOCA text operations. + */ +public class AFPTextHandler implements FOPTextHandler { + + /** logging instance */ + private static Log log = LogFactory.getLog(AFPTextHandler.class); + + /** Overriding FontState */ + protected Font overrideFont = null; + + /** Font information */ + private final FontInfo fontInfo; + + /** + * Main constructor. + * + * @param fontInfo the AFPGraphics2D instance + */ + public AFPTextHandler(FontInfo fontInfo) { + this.fontInfo = fontInfo; + } + + /** + * Return the font information associated with this object + * + * @return the FontInfo object + */ + public FontInfo getFontInfo() { + return fontInfo; + } + + /** + * Registers a page font + * + * @param internalFontName the internal font name + * @param internalFontName the internal font name + * @param fontSize the font size + * @return a font reference + */ + private int registerPageFont(AFPPageFonts pageFonts, String internalFontName, int fontSize) { + FontInfo fontInfo = getFontInfo(); + AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName); + // register if necessary + AFPFontAttributes afpFontAttributes = pageFonts.registerFont( + internalFontName, + afpFont, + fontSize + ); + return afpFontAttributes.getFontReference(); + } + + /** {@inheritDoc} */ + public void drawString(String text, float x, float y) throws IOException { + // TODO Remove me after removing the deprecated method in TextHandler. + throw new UnsupportedOperationException("Deprecated method!"); + } + + /** + * Add a text string to the current data object of the AFP datastream. + * The text is painted using text operations. + * + * {@inheritDoc} + */ + public void drawString(Graphics2D g, String str, float x, float y) throws IOException { + log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y); + AFPGraphics2D g2d = (AFPGraphics2D)g; + GraphicsObject graphicsObj = g2d.getGraphicsObject(); + Color color = g2d.getColor(); + + // set the color + AFPPaintingState paintingState = g2d.getPaintingState(); + if (paintingState.setColor(color)) { + graphicsObj.setColor(color); + } + + // set the character set + int fontReference = 0; + AFPPageFonts pageFonts = paintingState.getPageFonts(); + if (overrideFont != null) { + String internalFontName = overrideFont.getFontName(); + int fontSize = overrideFont.getFontSize(); + fontReference = registerPageFont(pageFonts, internalFontName, fontSize); + } else { + java.awt.Font awtFont = g2d.getFont(); +// AffineTransform fontTransform = awtFont.getTransform(); + FontInfo fontInfo = getFontInfo(); + Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont); + String internalFontName = fopFont.getFontName(); + int fontSize = fopFont.getFontSize(); + fontReference = registerPageFont(pageFonts, internalFontName, fontSize); + } + graphicsObj.setCharacterSet(fontReference); + + // add the character string + graphicsObj.addString(str, Math.round(x), Math.round(y)); + } + + /** + * Sets the overriding font. + * + * @param overrideFont Overriding Font to set + */ + public void setOverrideFont(Font overrideFont) { + this.overrideFont = overrideFont; + } +} diff --git a/src/java/org/apache/fop/afp/svg/AFPTextPainter.java b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java new file mode 100644 index 000000000..c6a38b1b5 --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/AFPTextPainter.java @@ -0,0 +1,44 @@ +/* + * 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.afp.svg; + +import org.apache.fop.svg.AbstractFOPTextPainter; +import org.apache.fop.svg.FOPTextHandler; + + +/** + * Renders the attributed character iterator of a <tt>TextNode</tt>. + * This class draws the text directly into the AFPGraphics2D so that + * the text is not drawn using shapes. + * If the text is simple enough to draw then it sets the font and calls + * drawString. If the text is complex or the cannot be translated + * into a simple drawString the StrokingTextPainter is used instead. + */ +public class AFPTextPainter extends AbstractFOPTextPainter { + + /** + * Create a new text painter with the given font information. + * @param nativeTextHandler the NativeTextHandler instance used for text painting + */ + public AFPTextPainter(FOPTextHandler nativeTextHandler) { + super(nativeTextHandler); + } + +} diff --git a/src/java/org/apache/fop/afp/svg/package.html b/src/java/org/apache/fop/afp/svg/package.html new file mode 100644 index 000000000..bd24b246f --- /dev/null +++ b/src/java/org/apache/fop/afp/svg/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.modca.svg Package</TITLE> +<BODY> +<P>Contains a collection of AFP specific Batik bridges.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/tools/BinaryUtils.java b/src/java/org/apache/fop/afp/util/BinaryUtils.java index 31ba45bcf..2b2649415 100644 --- a/src/java/org/apache/fop/render/afp/tools/BinaryUtils.java +++ b/src/java/org/apache/fop/afp/util/BinaryUtils.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.tools; +package org.apache.fop.afp.util; import java.io.ByteArrayOutputStream; diff --git a/src/java/org/apache/fop/render/afp/tools/DTDEntityResolver.java b/src/java/org/apache/fop/afp/util/DTDEntityResolver.java index e9554ecea..dcf5ad7d9 100644 --- a/src/java/org/apache/fop/render/afp/tools/DTDEntityResolver.java +++ b/src/java/org/apache/fop/afp/util/DTDEntityResolver.java @@ -17,12 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.afp.tools; +package org.apache.fop.afp.util; import java.io.IOException; import java.net.URL; -import org.apache.fop.render.afp.exceptions.FontRuntimeException; +import org.apache.fop.afp.fonts.FontRuntimeException; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; diff --git a/src/java/org/apache/fop/render/afp/tools/StringUtils.java b/src/java/org/apache/fop/afp/util/StringUtils.java index c49509aa0..ce68d27be 100644 --- a/src/java/org/apache/fop/render/afp/tools/StringUtils.java +++ b/src/java/org/apache/fop/afp/util/StringUtils.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.tools; +package org.apache.fop.afp.util; /** * Library of utility methods useful in dealing with strings. diff --git a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java b/src/java/org/apache/fop/afp/util/StructuredFieldReader.java index 48beff023..34add3bbe 100644 --- a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java +++ b/src/java/org/apache/fop/afp/util/StructuredFieldReader.java @@ -17,7 +17,7 @@ /* $Id$ */ -package org.apache.fop.render.afp.tools; +package org.apache.fop.afp.util; import java.io.IOException; import java.io.InputStream; diff --git a/src/java/org/apache/fop/afp/util/package.html b/src/java/org/apache/fop/afp/util/package.html new file mode 100644 index 000000000..525bdbe2a --- /dev/null +++ b/src/java/org/apache/fop/afp/util/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.afp.modca.triplets Package</TITLE> +<BODY> +<P>Contains a collection of useful AFP utility classes.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/apps/MimeConstants.java b/src/java/org/apache/fop/apps/MimeConstants.java index 02a7ba81b..87048fa4d 100644 --- a/src/java/org/apache/fop/apps/MimeConstants.java +++ b/src/java/org/apache/fop/apps/MimeConstants.java @@ -22,50 +22,7 @@ package org.apache.fop.apps; /** * Frequently used MIME types for various file formats used when working with Apache FOP. */ -public interface MimeConstants { - - /** Portable Document Format */ - String MIME_PDF = "application/pdf"; - - /** PostScript */ - String MIME_POSTSCRIPT = "application/postscript"; - /** Encapsulated PostScript (same MIME type as PostScript) */ - String MIME_EPS = MIME_POSTSCRIPT; - - /** HP's PCL */ - String MIME_PCL = "application/x-pcl"; - /** HP's PCL (alternative MIME type) */ - String MIME_PCL_ALT = "application/vnd.hp-PCL"; - - /** IBM's AFP */ - String MIME_AFP = "application/x-afp"; - /** IBM's AFP (alternative MIME type) */ - String MIME_AFP_ALT = "application/vnd.ibm.modcap"; - - /** Plain text */ - String MIME_PLAIN_TEXT = "text/plain"; - - /** Rich text format */ - String MIME_RTF = "application/rtf"; - /** Rich text format (alternative 1) */ - String MIME_RTF_ALT1 = "text/richtext"; - /** Rich text format (alternative 2) */ - String MIME_RTF_ALT2 = "text/rtf"; - - /** FrameMaker's MIF */ - String MIME_MIF = "application/mif"; - - /** Scalable Vector Graphics */ - String MIME_SVG = "image/svg+xml"; - - /** GIF images */ - String MIME_GIF = "image/gif"; - /** PNG images */ - String MIME_PNG = "image/png"; - /** JPEG images */ - String MIME_JPEG = "image/jpeg"; - /** TIFF images */ - String MIME_TIFF = "image/tiff"; +public interface MimeConstants extends org.apache.xmlgraphics.util.MimeConstants { /** Apache FOP's AWT preview (non-standard MIME type) */ String MIME_FOP_AWT_PREVIEW = "application/X-fop-awt-preview"; @@ -74,7 +31,4 @@ public interface MimeConstants { /** Apache FOP's area tree XML */ String MIME_FOP_AREA_TREE = "application/X-fop-areatree"; - /** Proposed but non-registered MIME type for XSL-FO */ - String MIME_XSL_FO = "text/xsl"; - } diff --git a/src/java/org/apache/fop/area/Area.java b/src/java/org/apache/fop/area/Area.java index 1379e566d..87ba2146a 100644 --- a/src/java/org/apache/fop/area/Area.java +++ b/src/java/org/apache/fop/area/Area.java @@ -119,8 +119,10 @@ public class Area extends AreaTreeObject implements Serializable { public static final int CLASS_MAX = CLASS_SIDE_FLOAT + 1; private int areaClass = CLASS_NORMAL; + /** the area's inline-progression-dimension */ protected int ipd; + /** the area's block-progression-dimension */ protected int bpd; @@ -141,7 +143,7 @@ public class Area extends AreaTreeObject implements Serializable { * @return the area class */ public int getAreaClass() { - return areaClass; + return this.areaClass; } /** @@ -157,11 +159,11 @@ public class Area extends AreaTreeObject implements Serializable { * Set the inline progression dimension of content rectangle * for this area. * - * @param i the new inline progression dimension - * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">ipd</a> + * @param ipd the new inline progression dimension + * @see <a href="http://www.w3.org/TR/xsl/#inline-progression-dimension">ipd</a> */ - public void setIPD(int i) { - ipd = i; + public void setIPD(int ipd) { + this.ipd = ipd; } /** @@ -169,10 +171,10 @@ public class Area extends AreaTreeObject implements Serializable { * for this area. * * @return the inline progression dimension - * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">ipd</a> + * @see <a href="http://www.w3.org/TR/xsl/#inline-progression-dimension">ipd</a> */ public int getIPD() { - return ipd; + return this.ipd; } /** @@ -180,7 +182,7 @@ public class Area extends AreaTreeObject implements Serializable { * for this area. * * @param b the new block progression dimension - * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">bpd</a> + * @see <a href="http://www.w3.org/TR/xsl/#block-progression-dimension">bpd</a> */ public void setBPD(int b) { bpd = b; @@ -191,7 +193,7 @@ public class Area extends AreaTreeObject implements Serializable { * for this area. * * @return the block progression dimension - * @see <a href="http://www.w3.org/TR/xsl/slice4.html#area-common">bpd</a> + * @see <a href="http://www.w3.org/TR/xsl/#block-progression-dimension">bpd</a> */ public int getBPD() { return bpd; diff --git a/src/java/org/apache/fop/area/AreaTreeHandler.java b/src/java/org/apache/fop/area/AreaTreeHandler.java index 59995741b..128fc8ce9 100644 --- a/src/java/org/apache/fop/area/AreaTreeHandler.java +++ b/src/java/org/apache/fop/area/AreaTreeHandler.java @@ -101,12 +101,12 @@ public class AreaTreeHandler extends FOEventHandler { setupModel(userAgent, outputFormat, stream); - lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride(); + this.lmMaker = userAgent.getFactory().getLayoutManagerMakerOverride(); if (lmMaker == null) { lmMaker = new LayoutManagerMapping(); } - idTracker = new IDTracker(); + this.idTracker = new IDTracker(); if (log.isDebugEnabled()) { statistics = new Statistics(); @@ -124,7 +124,7 @@ public class AreaTreeHandler extends FOEventHandler { */ protected void setupModel(FOUserAgent userAgent, String outputFormat, OutputStream stream) throws FOPException { - model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream); + this.model = new RenderPagesModel(userAgent, outputFormat, fontInfo, stream); } /** @@ -133,7 +133,7 @@ public class AreaTreeHandler extends FOEventHandler { * @return AreaTreeModel the model being used for this area tree */ public AreaTreeModel getAreaTreeModel() { - return model; + return this.model; } /** @@ -143,7 +143,7 @@ public class AreaTreeHandler extends FOEventHandler { * area tree */ public LayoutManagerMaker getLayoutManagerMaker() { - return lmMaker; + return this.lmMaker; } /** @@ -152,7 +152,7 @@ public class AreaTreeHandler extends FOEventHandler { * @return IDTracker used to track reference ids for items in this area tree */ public IDTracker getIDTracker() { - return idTracker; + return this.idTracker; } /** @@ -207,9 +207,9 @@ public class AreaTreeHandler extends FOEventHandler { } private void wrapAndAddExtensionAttachments(List list) { - Iterator i = list.iterator(); - while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment) i.next(); + Iterator it = list.iterator(); + while (it.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment) it.next(); addOffDocumentItem(new OffDocumentExtensionAttachment(attachment)); } } @@ -357,7 +357,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param id the property ID of the area * @param pv a page viewport that contains the area with this ID - * @deprecated use getIdTracker().associateIDWithPageViewport(id, pv) instead + * @deprecated use getIDTracker().associateIDWithPageViewport(id, pv) instead */ public void associateIDWithPageViewport(String id, PageViewport pv) { idTracker.associateIDWithPageViewport(id, pv); @@ -369,7 +369,7 @@ public class AreaTreeHandler extends FOEventHandler { * know when an id can be resolved. * * @param id the id of the object being processed - * @deprecated use getIdTracker().signalPendingID(id) instead + * @deprecated use getIDTracker().signalPendingID(id) instead */ public void signalPendingID(String id) { idTracker.signalPendingID(id); @@ -381,7 +381,7 @@ public class AreaTreeHandler extends FOEventHandler { * ref-ids can be resolved. * * @param id the id of the formatting object which was just finished - * @deprecated use getIdTracker().signalIDProcessed(id) instead + * @deprecated use getIDTracker().signalIDProcessed(id) instead */ public void signalIDProcessed(String id) { idTracker.signalIDProcessed(id); @@ -392,7 +392,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param id the id to check * @return true if the ID has been resolved - * @deprecated use getIdTracker().alreadyResolvedID(id) instead + * @deprecated use getIDTracker().alreadyResolvedID(id) instead */ public boolean alreadyResolvedID(String id) { return idTracker.alreadyResolvedID(id); @@ -402,7 +402,7 @@ public class AreaTreeHandler extends FOEventHandler { * Tries to resolve all unresolved ID references on the given page. * * @param pv page viewport whose ID refs to resolve - * @deprecated use getIdTracker().tryIDResolution(pv) instead + * @deprecated use getIDTracker().tryIDResolution(pv) instead */ public void tryIDResolution(PageViewport pv) { idTracker.tryIDResolution(pv); @@ -413,7 +413,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param id the id to lookup * @return the list of PageViewports - * @deprecated use getIdTracker().getPageViewportsContainingID(id) instead + * @deprecated use getIDTracker().getPageViewportsContainingID(id) instead */ public List getPageViewportsContainingID(String id) { return idTracker.getPageViewportsContainingID(id); @@ -424,7 +424,7 @@ public class AreaTreeHandler extends FOEventHandler { * * @param idref the idref whose target id has not yet been located * @param res the Resolvable object needing the idref to be resolved - * @deprecated use getIdTracker().addUnresolvedIDRef(idref, res) instead + * @deprecated use getIDTracker().addUnresolvedIDRef(idref, res) instead */ public void addUnresolvedIDRef(String idref, Resolvable res) { idTracker.addUnresolvedIDRef(idref, res); diff --git a/src/java/org/apache/fop/area/AreaTreeModel.java b/src/java/org/apache/fop/area/AreaTreeModel.java index acf51b913..e5f6db17b 100644 --- a/src/java/org/apache/fop/area/AreaTreeModel.java +++ b/src/java/org/apache/fop/area/AreaTreeModel.java @@ -36,11 +36,11 @@ import org.apache.commons.logging.LogFactory; * the life of the area tree model. */ public class AreaTreeModel { - private List pageSequenceList = null; + private List/*<PageSequence>*/ pageSequenceList = null; private int currentPageSequenceIndex = -1; /** the current page sequence */ protected PageSequence currentPageSequence; - private List offDocumentItems = new java.util.ArrayList(); +// private List offDocumentItems = new java.util.ArrayList(); /** logger instance */ protected static Log log = LogFactory.getLog(AreaTreeModel.class); @@ -48,7 +48,7 @@ public class AreaTreeModel { * Create a new store pages model */ public AreaTreeModel() { - pageSequenceList = new java.util.ArrayList(); + pageSequenceList = new java.util.ArrayList/*<PageSequence>*/(); } /** @@ -83,13 +83,13 @@ public class AreaTreeModel { * Handle an OffDocumentItem * @param ext the extension to handle */ - public void handleOffDocumentItem(OffDocumentItem ext) {}; + public void handleOffDocumentItem(OffDocumentItem ext) { }; /** * Signal the end of the document for any processing. * @throws SAXException if a problem was encountered. */ - public void endDocument() throws SAXException {}; + public void endDocument() throws SAXException { }; /** * Returns the currently active page-sequence. diff --git a/src/java/org/apache/fop/area/AreaTreeObject.java b/src/java/org/apache/fop/area/AreaTreeObject.java index 83e7727db..5929e7c4e 100644 --- a/src/java/org/apache/fop/area/AreaTreeObject.java +++ b/src/java/org/apache/fop/area/AreaTreeObject.java @@ -21,6 +21,7 @@ package org.apache.fop.area; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.apache.xmlgraphics.util.QName; @@ -33,6 +34,9 @@ public abstract class AreaTreeObject { /** Foreign attributes */ protected Map foreignAttributes = null; + /** Extension attachments */ + protected List/*<ExtensionAttachment>*/ extensionAttachments = null; + /** * Sets a foreign attribute. * @param name the qualified name of the attribute @@ -83,6 +87,21 @@ public abstract class AreaTreeObject { return Collections.EMPTY_MAP; } } + + /** + * Set extension attachments from a List + * @param extensionAttachments a List with extension attachments + */ + public void setExtensionAttachments(List extensionAttachments) { + this.extensionAttachments = extensionAttachments; + } - + /** @return the extension attachments associated with this area */ + public List getExtensionAttachments() { + if (this.foreignAttributes != null) { + return Collections.unmodifiableList(this.extensionAttachments); + } else { + return Collections.EMPTY_LIST; + } + } } diff --git a/src/java/org/apache/fop/area/IDTracker.java b/src/java/org/apache/fop/area/IDTracker.java index 9f9023717..b55ed7983 100644 --- a/src/java/org/apache/fop/area/IDTracker.java +++ b/src/java/org/apache/fop/area/IDTracker.java @@ -20,8 +20,6 @@ package org.apache.fop.area; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -36,20 +34,20 @@ import org.apache.commons.logging.LogFactory; */ public class IDTracker { - private static Log log = LogFactory.getLog(IDTracker.class); + private static final Log log = LogFactory.getLog(IDTracker.class); // HashMap of ID's whose area is located on one or more consecutive // PageViewports. Each ID has an arraylist of PageViewports that // form the defined area of this ID - private Map idLocations = new HashMap(); + private Map idLocations = new java.util.HashMap(); // idref's whose target PageViewports have yet to be identified // Each idref has a HashSet of Resolvable objects containing that idref - private Map unresolvedIDRefs = new HashMap(); + private Map unresolvedIDRefs = new java.util.HashMap(); - private Set unfinishedIDs = new HashSet(); + private Set unfinishedIDs = new java.util.HashSet(); - private Set alreadyResolvedIDs = new HashSet(); + private Set alreadyResolvedIDs = new java.util.HashSet(); /** * Tie a PageViewport with an ID found on a child area of the PV. Note that @@ -198,7 +196,7 @@ public class IDTracker { public void addUnresolvedIDRef(String idref, Resolvable res) { Set todo = (Set) unresolvedIDRefs.get(idref); if (todo == null) { - todo = new HashSet(); + todo = new java.util.HashSet(); unresolvedIDRefs.put(idref, todo); } // add Resolvable object to this HashSet diff --git a/src/java/org/apache/fop/area/PageViewport.java b/src/java/org/apache/fop/area/PageViewport.java index 23d066099..a7523530b 100644 --- a/src/java/org/apache/fop/area/PageViewport.java +++ b/src/java/org/apache/fop/area/PageViewport.java @@ -89,7 +89,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl //Arbitrary attachments to the page from extensions that need to pass information //down to the renderers. - private List extensionAttachments = null; + private List/*<ExtensionAttachment>*/ extensionAttachments = null; /** * logging instance @@ -122,7 +122,8 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl */ public PageViewport(PageViewport original) { if (original.extensionAttachments != null) { - this.extensionAttachments = new java.util.ArrayList(original.extensionAttachments); + this.extensionAttachments + = new java.util.ArrayList/*<ExtensionAttachment>*/(original.extensionAttachments); } this.pageIndex = original.pageIndex; this.pageNumber = original.pageNumber; @@ -588,7 +589,7 @@ public class PageViewport extends AreaTreeObject implements Resolvable, Cloneabl */ public void addExtensionAttachment(ExtensionAttachment attachment) { if (this.extensionAttachments == null) { - this.extensionAttachments = new java.util.ArrayList(); + this.extensionAttachments = new java.util.ArrayList/*<ExtensionAttachment>*/(); } extensionAttachments.add(attachment); } diff --git a/src/java/org/apache/fop/area/RegionReference.java b/src/java/org/apache/fop/area/RegionReference.java index eac90ce41..bee597673 100644 --- a/src/java/org/apache/fop/area/RegionReference.java +++ b/src/java/org/apache/fop/area/RegionReference.java @@ -160,4 +160,13 @@ public class RegionReference extends Area implements Cloneable { return rr; } + /** {@inheritDoc} */ + public String toString() { + StringBuffer sb = new StringBuffer(super.toString()); + sb.append(" {regionName=").append(regionName); + sb.append(", regionClass=").append(regionClass); + sb.append(", ctm=").append(ctm); + sb.append("}"); + return sb.toString(); + } } diff --git a/src/java/org/apache/fop/area/RenderPagesModel.java b/src/java/org/apache/fop/area/RenderPagesModel.java index e75fd4e79..13995b099 100644 --- a/src/java/org/apache/fop/area/RenderPagesModel.java +++ b/src/java/org/apache/fop/area/RenderPagesModel.java @@ -50,9 +50,9 @@ public class RenderPagesModel extends AreaTreeModel { /** * Pages that have been prepared but not rendered yet. */ - protected List prepared = new java.util.ArrayList(); - private List pendingODI = new java.util.ArrayList(); - private List endDocODI = new java.util.ArrayList(); + protected List/*<PageViewport>*/ prepared = new java.util.ArrayList/*<PageViewport>*/(); + private List/*<OffDocumentItem>*/ pendingODI = new java.util.ArrayList/*<OffDocumentItem>*/(); + private List/*<OffDocumentItem>*/ endDocODI = new java.util.ArrayList/*<OffDocumentItem>*/(); /** * Create a new render pages model with the given renderer. @@ -66,7 +66,7 @@ public class RenderPagesModel extends AreaTreeModel { FontInfo fontInfo, OutputStream stream) throws FOPException { super(); - renderer = userAgent.getRendererFactory().createRenderer( + this.renderer = userAgent.getRendererFactory().createRenderer( userAgent, outputFormat); try { diff --git a/src/java/org/apache/fop/area/inline/FilledArea.java b/src/java/org/apache/fop/area/inline/FilledArea.java index 3e108db19..7df62e79b 100644 --- a/src/java/org/apache/fop/area/inline/FilledArea.java +++ b/src/java/org/apache/fop/area/inline/FilledArea.java @@ -70,10 +70,10 @@ public class FilledArea extends InlineParent { /** * Set the unit width for the areas to fill the full width. * - * @param w the unit width + * @param width the unit width */ - public void setUnitWidth(int w) { - unitWidth = w; + public void setUnitWidth(int width) { + this.unitWidth = width; } /** @@ -82,7 +82,7 @@ public class FilledArea extends InlineParent { * @return the unit width */ public int getUnitWidth() { - return unitWidth; + return this.unitWidth; } /** @@ -117,7 +117,7 @@ public class FilledArea extends InlineParent { } /** - * recursively apply the variation factor to all descendant areas + * Recursively apply the variation factor to all descendant areas * @param variationFactor the variation factor that must be applied to adjustments * @param lineStretch the total stretch of the line * @param lineShrink the total shrink of the line diff --git a/src/java/org/apache/fop/area/inline/Image.java b/src/java/org/apache/fop/area/inline/Image.java index 1fc3375e5..7d802db49 100644 --- a/src/java/org/apache/fop/area/inline/Image.java +++ b/src/java/org/apache/fop/area/inline/Image.java @@ -28,14 +28,14 @@ import org.apache.fop.area.Area; */ public class Image extends Area { private String url; - + /** * Create a new image with the given url. * - * @param u the url of the image + * @param url the url of the image */ - public Image(String u) { - url = u; + public Image(String url) { + this.url = url; } /** @@ -45,7 +45,7 @@ public class Image extends Area { * @return the url of this image */ public String getURL() { - return url; + return this.url; } } diff --git a/src/java/org/apache/fop/area/inline/InlineArea.java b/src/java/org/apache/fop/area/inline/InlineArea.java index d8936dd42..6d5d9ca98 100644 --- a/src/java/org/apache/fop/area/inline/InlineArea.java +++ b/src/java/org/apache/fop/area/inline/InlineArea.java @@ -221,7 +221,7 @@ public class InlineArea extends Area { notifyIPDVariation(ipdVariation); } - /** + /** * notify the parent area about the ipd variation of this area * or of a descendant area * @param ipdVariation the difference between new and old ipd diff --git a/src/java/org/apache/fop/area/inline/TextArea.java b/src/java/org/apache/fop/area/inline/TextArea.java index 102b0a330..f736b894c 100644 --- a/src/java/org/apache/fop/area/inline/TextArea.java +++ b/src/java/org/apache/fop/area/inline/TextArea.java @@ -63,6 +63,7 @@ public class TextArea extends AbstractTextArea { * * @param word the word string * @param offset the offset for the next area + * @param letterAdjust the letter adjustment array (may be null) */ public void addWord(String word, int offset, int[] letterAdjust) { WordArea wordArea = new WordArea(word, offset, letterAdjust); @@ -98,7 +99,7 @@ public class TextArea extends AbstractTextArea { StringBuffer text = new StringBuffer(); InlineArea child; // assemble the text - for (int i = 0; i < inlines.size(); i ++) { + for (int i = 0; i < inlines.size(); i++) { child = (InlineArea) inlines.get(i); if (child instanceof WordArea) { text.append(((WordArea) child).getWord()); @@ -109,5 +110,9 @@ public class TextArea extends AbstractTextArea { return text.toString(); } + /** {@inheritDoc} */ + public String toString() { + return "TextArea{text=" + getText() + "}"; + } } diff --git a/src/java/org/apache/fop/area/inline/Viewport.java b/src/java/org/apache/fop/area/inline/Viewport.java index fadc1ec2a..489f5afda 100644 --- a/src/java/org/apache/fop/area/inline/Viewport.java +++ b/src/java/org/apache/fop/area/inline/Viewport.java @@ -45,7 +45,7 @@ public class Viewport extends InlineArea { * @param child the child content area of this viewport */ public Viewport(Area child) { - content = child; + this.content = child; } /** @@ -54,7 +54,7 @@ public class Viewport extends InlineArea { * @param c true if this viewport should clip */ public void setClip(boolean c) { - clip = c; + this.clip = c; } /** @@ -63,7 +63,7 @@ public class Viewport extends InlineArea { * @return true if this viewport should clip */ public boolean getClip() { - return clip; + return this.clip; } /** @@ -72,7 +72,7 @@ public class Viewport extends InlineArea { * @param cp the position and size to place the content */ public void setContentPosition(Rectangle2D cp) { - contentPosition = cp; + this.contentPosition = cp; } /** @@ -81,7 +81,7 @@ public class Viewport extends InlineArea { * @return the position and size to place the content */ public Rectangle2D getContentPosition() { - return contentPosition; + return this.contentPosition; } /** @@ -98,7 +98,7 @@ public class Viewport extends InlineArea { * @return the content area */ public Area getContent() { - return content; + return this.content; } private void writeObject(java.io.ObjectOutputStream out) @@ -123,9 +123,9 @@ public class Viewport extends InlineArea { in.readFloat(), in.readFloat()); } - clip = in.readBoolean(); - props = (HashMap) in.readObject(); - content = (Area) in.readObject(); + this.clip = in.readBoolean(); + this.props = (HashMap) in.readObject(); + this.content = (Area) in.readObject(); } } diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java index 5e38b803a..4f49ea269 100644 --- a/src/java/org/apache/fop/cli/InputHandler.java +++ b/src/java/org/apache/fop/cli/InputHandler.java @@ -51,6 +51,9 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.fop.render.awt.viewer.Renderable; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; /** * Class for handling files input from command line diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml index 1c8c35b0b..9bd30609f 100644 --- a/src/java/org/apache/fop/events/EventFormatter.xml +++ b/src/java/org/apache/fop/events/EventFormatter.xml @@ -26,6 +26,7 @@ <message key="rule.childOfSPM">The element must be a child of fo:simple-page-master.</message> <message key="rule.childOfDeclarations">The element must be a child of fo:declarations.</message> <message key="rule.childOfSPMorDeclarations">The element must be a child of fo:declarations or fo:simple-page-master.</message> + <message key="rule.childOfInstreamForeignObjectorExternalGraphic">The element must be a child of fo:instream-foreign-object or fo:external-graphic.</message> <message key="rule.wrapperInvalidChildForParent">An fo:wrapper is only permitted to have children that would be permitted for its parent.</message> <message key="org.apache.fop.fo.FOValidationEventProducer.tooManyNodes">For "{elementName}", only one "{offendingNode}" may be declared.{{locator}}</message> <message key="org.apache.fop.fo.FOValidationEventProducer.nodeOutOfOrder">For "{elementName}", "{tooLateNode}" must be declared before "{tooEarlyNode}"!{{locator}}</message> @@ -102,4 +103,7 @@ Any reference to it will be considered a reference to the first occurrence in th <message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message> <message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message> <message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message> +<message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup"/> +<message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont"/> +<message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError"/> </catalogue> diff --git a/src/java/org/apache/fop/fo/ElementMapping.java b/src/java/org/apache/fop/fo/ElementMapping.java index d51c21993..9e9bb6c59 100644 --- a/src/java/org/apache/fop/fo/ElementMapping.java +++ b/src/java/org/apache/fop/fo/ElementMapping.java @@ -19,7 +19,7 @@ package org.apache.fop.fo; -import java.util.HashMap; +import java.util.Map; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -38,7 +38,7 @@ public abstract class ElementMapping { public static final String DEFAULT = "<default>"; /** The HashMap table of formatting objects defined by the ElementMapping */ - protected HashMap foObjs = null; + protected Map foObjs = null; /** The namespace for the ElementMapping */ protected String namespaceURI = null; @@ -48,7 +48,7 @@ public abstract class ElementMapping { * * @return Table of Maker objects for this ElementMapping */ - public HashMap getTable() { + public Map getTable() { if (foObjs == null) { initialize(); } diff --git a/src/java/org/apache/fop/fo/FObj.java b/src/java/org/apache/fop/fo/FObj.java index 3e369b934..e0624df69 100644 --- a/src/java/org/apache/fop/fo/FObj.java +++ b/src/java/org/apache/fop/fo/FObj.java @@ -573,6 +573,11 @@ public abstract class FObj extends FONode implements Constants { } } + /** @return true if this FObj has extension attachments */ + public boolean hasExtensionAttachments() { + return extensionAttachments != null; + } + /** * Adds a foreign attribute to this FObj. * @param attributeName the attribute name as a QName instance diff --git a/src/java/org/apache/fop/fonts/Base14Font.java b/src/java/org/apache/fop/fonts/Base14Font.java index 04349a148..9b2e95bc7 100644 --- a/src/java/org/apache/fop/fonts/Base14Font.java +++ b/src/java/org/apache/fop/fonts/Base14Font.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; + /** * Base class for all Base 14 fonts. */ diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java index eac794514..8f468f7a4 100644 --- a/src/java/org/apache/fop/fonts/CIDFont.java +++ b/src/java/org/apache/fop/fonts/CIDFont.java @@ -76,4 +76,4 @@ public abstract class CIDFont extends CustomFont { return true; } -}
\ No newline at end of file +} diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index 0b40dfecc..4cf24ae16 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/src/java/org/apache/fop/fonts/CustomFont.java @@ -26,6 +26,7 @@ import java.util.Set; import javax.xml.transform.Source; + /** * Abstract base class for custom fonts loaded from files, for example. */ diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index ebd45457d..e9740c00c 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -23,6 +23,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fonts.CodePointMapping; /** * This class holds font state information and provides access to the font diff --git a/src/java/org/apache/fop/fonts/FontCollection.java b/src/java/org/apache/fop/fonts/FontCollection.java index 3c9bba7f4..d481ae2f9 100644 --- a/src/java/org/apache/fop/fonts/FontCollection.java +++ b/src/java/org/apache/fop/fonts/FontCollection.java @@ -24,6 +24,7 @@ package org.apache.fop.fonts; * Sets up a set of fonts */ public interface FontCollection { + /** * Sets up fonts in a font info object. * diff --git a/src/java/org/apache/fop/fonts/FontDescriptor.java b/src/java/org/apache/fop/fonts/FontDescriptor.java index fadc73834..e7c81c9f3 100644 --- a/src/java/org/apache/fop/fonts/FontDescriptor.java +++ b/src/java/org/apache/fop/fonts/FontDescriptor.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; + /** * This interface enhances the font metrics interface with access methods to * value needed to register fonts in various target formats like PDF or diff --git a/src/java/org/apache/fop/fonts/FontEventListener.java b/src/java/org/apache/fop/fonts/FontEventListener.java index b508d7053..740a05fdc 100644 --- a/src/java/org/apache/fop/fonts/FontEventListener.java +++ b/src/java/org/apache/fop/fonts/FontEventListener.java @@ -19,7 +19,6 @@ package org.apache.fop.fonts; - /** * Event listener interface for font-related events. */ diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java index 2bcc6d7e1..8f8032767 100644 --- a/src/java/org/apache/fop/fonts/FontInfo.java +++ b/src/java/org/apache/fop/fonts/FontInfo.java @@ -110,6 +110,19 @@ public class FontInfo { } /** + * Adds a series of new font triplets given an array of font family names. + * @param name internal key + * @param families an array of font family names + * @param style font style (normal, italic, oblique...) + * @param weight font weight + */ + public void addFontProperties(String name, String[] families, String style, int weight) { + for (int i = 0; i < families.length; i++) { + addFontProperties(name, families[i], style, weight); + } + } + + /** * Adds a new font triplet. * @param internalFontKey internal font key * @param triplet the font triplet to associate with the internal key @@ -193,7 +206,8 @@ public class FontInfo { private FontTriplet fontLookup(String family, String style, int weight, boolean substitutable) { if (log.isTraceEnabled()) { - log.trace("Font lookup: " + family + " " + style + " " + weight); + log.trace("Font lookup: " + family + " " + style + " " + weight + + (substitutable ? " substitutable" : "")); } FontTriplet startKey = createFontKey(family, style, weight); @@ -215,7 +229,7 @@ public class FontInfo { } private FontTriplet fuzzyFontLookup(String family, String style, - int weight, FontTriplet startKey, boolean substFont) { + int weight, FontTriplet startKey, boolean substitutable) { FontTriplet key; String internalFontKey = null; if (!family.equals(startKey.getName())) { @@ -232,7 +246,8 @@ public class FontInfo { internalFontKey = getInternalFontKey(key); } - if (!substFont && internalFontKey == null) { + // return null if not found and not substitutable + if (!substitutable && internalFontKey == null) { return null; } @@ -263,18 +278,18 @@ public class FontInfo { // fallback 2: try the same font-family with default style and weight /* obsolete: replaced by the loop above - if (f == null) { + if (internalFontKey == null) { key = createFontKey(family, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - f = getInternalFontKey(key); + internalFontKey = getInternalFontKey(key); }*/ - // fallback 3: try any family with orig style/weight + // fallback 3: try any family with original style/weight if (internalFontKey == null) { return fuzzyFontLookup("any", style, weight, startKey, false); } // last resort: use default - if (internalFontKey == null) { + if (key == null && internalFontKey == null) { key = Font.DEFAULT_FONT; internalFontKey = getInternalFontKey(key); } @@ -303,6 +318,7 @@ public class FontInfo { /** * Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size. + * * @param triplet the font triplet designating the requested font * @param fontSize the font size * @return the requested Font instance @@ -326,6 +342,57 @@ public class FontInfo { return font; } + private List/*<FontTriplet>*/ getTripletsForName(String fontName) { + List/*<FontTriplet>*/ matchedTriplets = new java.util.ArrayList/*<FontTriplet>*/(); + Iterator it = triplets.keySet().iterator(); + while (it.hasNext()) { + FontTriplet triplet = (FontTriplet)it.next(); + String tripletName = triplet.getName(); + if (tripletName.toLowerCase().equals(fontName.toLowerCase())) { + matchedTriplets.add(triplet); + } + } + return matchedTriplets; + } + + /** + * Returns a suitable internal font given an AWT Font instance. + * + * @param awtFont the AWT font + * @return a best matching internal Font + */ + public Font getFontInstanceForAWTFont(java.awt.Font awtFont) { + String awtFontName = awtFont.getName(); + String awtFontFamily = awtFont.getFamily(); + String awtFontStyle = awtFont.isItalic() ? Font.STYLE_ITALIC : Font.STYLE_NORMAL; + int awtFontWeight = awtFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL; + + FontTriplet matchedTriplet = null; + List/*<FontTriplet>*/ triplets = getTripletsForName(awtFontName); + if (!triplets.isEmpty()) { + Iterator it = triplets.iterator(); + while (it.hasNext()) { + FontTriplet triplet = (FontTriplet)it.next(); + boolean styleMatched = triplet.getStyle().equals(awtFontStyle); + boolean weightMatched = triplet.getWeight() == awtFontWeight; + if (styleMatched && weightMatched) { + matchedTriplet = triplet; + break; + } + } + } + + // not matched on font name so do a lookup using family + if (matchedTriplet == null) { + if (awtFontFamily.equals("sanserif")) { + awtFontFamily = "sans-serif"; + } + matchedTriplet = fontLookup(awtFontFamily, awtFontStyle, awtFontWeight); + } + int fontSize = Math.round(awtFont.getSize2D() * 1000); + return getFontInstance(matchedTriplet, fontSize); + } + /** * Lookup a font. * <br> @@ -345,7 +412,7 @@ public class FontInfo { private List/*<FontTriplet>*/ fontLookup(String[] families, String style, int weight, boolean substitutable) { - List matchingTriplets = new java.util.ArrayList(); + List/*<FontTriplet>*/ matchingTriplets = new java.util.ArrayList/*<FontTriplet>*/(); FontTriplet triplet = null; for (int i = 0; i < families.length; i++) { triplet = fontLookup(families[i], style, weight, substitutable); @@ -555,7 +622,7 @@ public class FontInfo { List/*<FontTriplet>*/ foundTriplets = new java.util.ArrayList(); for (Iterator iter = triplets.entrySet().iterator(); iter.hasNext();) { Map.Entry tripletEntry = (Map.Entry) iter.next(); - if (fontName.equals(((String)tripletEntry.getValue()))) { + if (fontName.equals((tripletEntry.getValue()))) { foundTriplets.add(tripletEntry.getKey()); } } diff --git a/src/java/org/apache/fop/fonts/FontMetrics.java b/src/java/org/apache/fop/fonts/FontMetrics.java index 7d5588690..29ade1ef3 100644 --- a/src/java/org/apache/fop/fonts/FontMetrics.java +++ b/src/java/org/apache/fop/fonts/FontMetrics.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; + /** * Main interface for access to font metrics. */ diff --git a/src/java/org/apache/fop/fonts/FontTriplet.java b/src/java/org/apache/fop/fonts/FontTriplet.java index 8e0acd8f2..f5cfe442a 100644 --- a/src/java/org/apache/fop/fonts/FontTriplet.java +++ b/src/java/org/apache/fop/fonts/FontTriplet.java @@ -21,6 +21,7 @@ package org.apache.fop.fonts; import java.io.Serializable; + /** * FontTriplet contains information on name, style and weight of one font */ diff --git a/src/java/org/apache/fop/fonts/FontType.java b/src/java/org/apache/fop/fonts/FontType.java index 0abe06a10..95b594ca4 100644 --- a/src/java/org/apache/fop/fonts/FontType.java +++ b/src/java/org/apache/fop/fonts/FontType.java @@ -19,12 +19,10 @@ package org.apache.fop.fonts; -import org.apache.avalon.framework.ValuedEnum; - /** * This class enumerates all supported font types. */ -public class FontType extends ValuedEnum { +public class FontType { /** * Collective identifier for "other" font types @@ -51,12 +49,16 @@ public class FontType extends ValuedEnum { */ public static final FontType TRUETYPE = new FontType("TrueType", 5); + private final String name; + private final int value; + /** * @see org.apache.avalon.framework.Enum#Enum(String) */ protected FontType(String name, int value) { - super(name, value); + this.name = name; + this.value = value; } @@ -107,4 +109,22 @@ public class FontType extends ValuedEnum { } } + /** + * Returns the name + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Returns the value + * + * @return the value + */ + public int getValue() { + return value; + } + } diff --git a/src/java/org/apache/fop/fonts/FontUtil.java b/src/java/org/apache/fop/fonts/FontUtil.java index 6ec89631f..49f23c12f 100644 --- a/src/java/org/apache/fop/fonts/FontUtil.java +++ b/src/java/org/apache/fop/fonts/FontUtil.java @@ -19,6 +19,7 @@ package org.apache.fop.fonts; + /** * Font utilities. */ diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index f25ca4e7e..b22b92e2f 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/src/java/org/apache/fop/fonts/MultiByteFont.java @@ -23,6 +23,7 @@ package org.apache.fop.fonts; import java.text.DecimalFormat; import java.util.Map; + /** * Generic MultiByte (CID) font */ diff --git a/src/java/org/apache/fop/fonts/MutableFont.java b/src/java/org/apache/fop/fonts/MutableFont.java index 5939bfed4..a5acf51b3 100644 --- a/src/java/org/apache/fop/fonts/MutableFont.java +++ b/src/java/org/apache/fop/fonts/MutableFont.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; + /** * This interface is used to set the values of a font during configuration time. */ diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java index 2fa8f1888..f4e317de3 100644 --- a/src/java/org/apache/fop/fonts/Typeface.java +++ b/src/java/org/apache/fop/fonts/Typeface.java @@ -139,4 +139,9 @@ public abstract class Typeface implements FontMetrics { } } } + + /** {@inheritDoc} */ + public String toString() { + return getFullName(); + } } diff --git a/src/java/org/apache/fop/fonts/package.html b/src/java/org/apache/fop/fonts/package.html index 33e1e2cb3..fee0bf827 100644 --- a/src/java/org/apache/fop/fonts/package.html +++ b/src/java/org/apache/fop/fonts/package.html @@ -1,3 +1,20 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> <HTML> <TITLE>org.apache.fop.fonts Package</TITLE> <BODY> diff --git a/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java b/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java new file mode 100644 index 000000000..ea92f748b --- /dev/null +++ b/src/java/org/apache/fop/image/loader/batik/Graphics2DImagePainterImpl.java @@ -0,0 +1,67 @@ +package org.apache.fop.image.loader.batik; + +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.gvt.GraphicsNode; + +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; + +/** + * A generic graphics 2D image painter implementation + */ +public class Graphics2DImagePainterImpl implements Graphics2DImagePainter { + + private final GraphicsNode root; + /** the Batik bridge context */ + protected final BridgeContext ctx; + /** the intrinsic size of the image */ + protected final Dimension imageSize; + + /** + * Main constructor + * + * @param root the graphics node root + * @param ctx the bridge context + * @param imageSize the image size + */ + public Graphics2DImagePainterImpl(GraphicsNode root, BridgeContext ctx, Dimension imageSize) { + this.root = root; + this.imageSize = imageSize; + this.ctx = ctx; + } + + /** {@inheritDoc} */ + public Dimension getImageSize() { + return imageSize; + } + + private void prepare(Graphics2D g2d, Rectangle2D area) { + // If no viewbox is defined in the svg file, a viewbox of 100x100 is + // assumed, as defined in SVGUserAgent.getViewportSize() + double tx = area.getX(); + double ty = area.getY(); + if (tx != 0 || ty != 0) { + g2d.translate(tx, ty); + } + + float iw = (float) ctx.getDocumentSize().getWidth(); + float ih = (float) ctx.getDocumentSize().getHeight(); + float w = (float) area.getWidth(); + float h = (float) area.getHeight(); + float sx = w / iw; + float sy = h / ih; + if (sx != 1.0 || sy != 1.0) { + g2d.scale(sx, sy); + } + } + + /** {@inheritDoc} */ + public void paint(Graphics2D g2d, Rectangle2D area) { + prepare(g2d, area); + root.paint(g2d); + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java index 9ea333af0..81c12a628 100644 --- a/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java +++ b/src/java/org/apache/fop/image/loader/batik/ImageConverterSVG2G2D.java @@ -20,9 +20,7 @@ package org.apache.fop.image.loader.batik; import java.awt.Dimension; -import java.awt.Graphics2D; import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; import java.util.Map; import org.apache.batik.bridge.BridgeContext; @@ -36,6 +34,7 @@ import org.apache.fop.svg.SimpleSVGUserAgent; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageProcessingHints; import org.apache.xmlgraphics.image.loader.XMLNamespaceEnabledImageFlavor; import org.apache.xmlgraphics.image.loader.impl.AbstractImageConverter; @@ -58,7 +57,7 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { private static Log log = LogFactory.getLog(ImageConverterSVG2G2D.class); /** {@inheritDoc} */ - public Image convert(Image src, Map hints) throws ImageException { + public Image convert(final Image src, Map hints) throws ImageException { checkSourceFlavor(src); final ImageXMLDOM svg = (ImageXMLDOM)src; if (!SVGDOMImplementation.SVG_NAMESPACE_URI.equals(svg.getRootNamespace())) { @@ -85,28 +84,14 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { } //Create the painter - Graphics2DImagePainter painter = new Graphics2DImagePainter() { - - public void paint(Graphics2D g2d, Rectangle2D area) { - // If no viewbox is defined in the svg file, a viewbox of 100x100 is - // assumed, as defined in SVGUserAgent.getViewportSize() - float iw = (float) ctx.getDocumentSize().getWidth(); - float ih = (float) ctx.getDocumentSize().getHeight(); - float w = (float) area.getWidth(); - float h = (float) area.getHeight(); - g2d.translate(area.getX(), area.getY()); - g2d.scale(w / iw, h / ih); - - root.paint(g2d); - } - - public Dimension getImageSize() { - return new Dimension(svg.getSize().getWidthMpt(), svg.getSize().getHeightMpt()); - } - - }; - - ImageGraphics2D g2dImage = new ImageGraphics2D(src.getInfo(), painter); + int width = svg.getSize().getWidthMpt(); + int height = svg.getSize().getHeightMpt(); + Dimension imageSize = new Dimension(width, height); + Graphics2DImagePainter painter = createPainter(ctx, root, imageSize); + + //Create g2d image + ImageInfo imageInfo = src.getInfo(); + ImageGraphics2D g2dImage = new ImageGraphics2D(imageInfo, painter); return g2dImage; } @@ -129,6 +114,19 @@ public class ImageConverterSVG2G2D extends AbstractImageConverter { }; } + /** + * Creates a Graphics 2D image painter + * + * @param ctx the bridge context + * @param root the graphics node root + * @param imageSize the image size + * @return the newly created graphics 2d image painter + */ + protected Graphics2DImagePainter createPainter( + BridgeContext ctx, GraphicsNode root, Dimension imageSize) { + return new Graphics2DImagePainterImpl(root, ctx, imageSize); + } + /** {@inheritDoc} */ public ImageFlavor getSourceFlavor() { return XMLNamespaceEnabledImageFlavor.SVG_DOM; diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java index 154d32e96..9cab6322b 100644 --- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java +++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java @@ -29,6 +29,7 @@ import org.apache.fop.datatypes.SimplePercentBaseContext; import org.apache.fop.fo.Constants; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; import org.apache.fop.fo.properties.CommonMarginBlock; +import org.apache.fop.fo.properties.CommonMarginBlock; import org.apache.fop.fo.properties.CommonTextDecoration; import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo; import org.apache.fop.fonts.Font; diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index 6b0e88cbb..dc8a020ae 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -20,12 +20,12 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.fo.flow.PageNumber; -import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.Trait; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.area.inline.InlineArea; +import org.apache.fop.area.inline.TextArea; +import org.apache.fop.area.Trait; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; diff --git a/src/java/org/apache/fop/pdf/PDFPaintingState.java b/src/java/org/apache/fop/pdf/PDFPaintingState.java new file mode 100644 index 000000000..11dfc635a --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFPaintingState.java @@ -0,0 +1,229 @@ +/* + * 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.pdf; + +import java.awt.Paint; +import java.awt.Shape; +import java.awt.geom.Area; +import java.awt.geom.GeneralPath; +import java.util.Iterator; + +import org.apache.fop.util.AbstractPaintingState; + +/** + * This keeps information about the current painting state when writing to pdf. + * It allows for creating new graphics states with the q operator. + * This class is only used to store the information about the state + * the caller needs to handle the actual pdf operators. + * + * When setting the state for pdf there are three possible ways of + * handling the situation. + * The values can be set to override previous or default values. + * A new state can be added and then the values set. + * The current state can be popped and values will return to a + * previous state then the necessary values can be overridden. + * The current transform behaves differently to other values as the + * matrix is combined with the current resolved value. + * It is impossible to optimise the result without analysing the all + * the possible combinations after completing. + */ +public class PDFPaintingState extends org.apache.fop.util.AbstractPaintingState { + + private static final long serialVersionUID = 5384726143906371279L; + + /** + * PDF State for storing graphics state. + */ + public PDFPaintingState() { + } + + /** + * Set the current paint. + * This checks if the paint will change and then sets the current paint. + * + * @param p the new paint + * @return true if the new paint changes the current paint + */ + public boolean setPaint(Paint p) { + Paint paint = ((PDFData)getData()).paint; + if (paint == null) { + if (p != null) { + ((PDFData)getData()).paint = p; + return true; + } + } else if (!paint.equals(p)) { + ((PDFData)getData()).paint = p; + return true; + } + return false; + } + + /** + * Check if the clip will change the current state. + * A clip is assumed to be used in a situation where it will add + * to any clip in the current or parent states. + * A clip cannot be cleared, this can only be achieved by going to + * a parent level with the correct clip. + * If the clip is different then it may start a new state so that + * it can return to the previous clip. + * + * @param cl the clip shape to check + * @return true if the clip will change the current clip. + */ + public boolean checkClip(Shape cl) { + Shape clip = ((PDFData)getData()).clip; + if (clip == null) { + if (cl != null) { + return true; + } + } else if (!new Area(clip).equals(new Area(cl))) { + return true; + } + //TODO check for clips that are larger than the current + return false; + } + + /** + * Set the current clip. + * This either sets a new clip or sets the clip to the intersect of + * the old clip and the new clip. + * + * @param cl the new clip in the current state + */ + public void setClip(Shape cl) { + Shape clip = ((PDFData)getData()).clip; + if (clip != null) { + Area newClip = new Area(clip); + newClip.intersect(new Area(cl)); + ((PDFData)getData()).clip = new GeneralPath(newClip); + } else { + ((PDFData)getData()).clip = cl; + } + } + + /** + * Get the current stack level. + * + * @return the current stack level + */ + public int getStackLevel() { + return getStateStack().size(); + } + + /** + * Get the graphics state. + * This gets the combination of all graphic states for + * the current context. + * This is the graphic state set with the gs operator not + * the other graphic state changes. + * + * @return the calculated ExtGState in the current context + */ + public PDFGState getGState() { + PDFGState defaultState = PDFGState.DEFAULT; + + PDFGState state; + PDFGState newState = new PDFGState(); + newState.addValues(defaultState); + for (Iterator it = getStateStack().iterator(); it.hasNext();) { + PDFData data = (PDFData)it.next(); + state = data.gstate; + if (state != null) { + newState.addValues(state); + } + } + if (((PDFData)getData()).gstate != null) { + newState.addValues(((PDFData)getData()).gstate); + } + return newState; + } + + /** {@inheritDoc} */ + protected AbstractData instantiateData() { + return new PDFData(); + } + + /** {@inheritDoc} */ + protected AbstractPaintingState instantiate() { + return new PDFPaintingState(); + } + + /** + * Push the current state onto the stack. + * This call should be used when the q operator is used + * so that the state is known when popped. + */ + public void save() { + AbstractData data = getData(); + AbstractData copy = (AbstractData)data.clone(); + data.clearTransform(); + getStateStack().add(copy); + } + + private class PDFData extends org.apache.fop.util.AbstractPaintingState.AbstractData { + + private static final long serialVersionUID = 3527950647293177764L; + + private Paint paint = null; + private Paint backPaint = null; + private int lineCap = 0; + private int lineJoin = 0; + private float miterLimit = 0; + private boolean text = false; + private int dashOffset = 0; + private Shape clip = null; + private PDFGState gstate = null; + + /** {@inheritDoc} */ + public Object clone() { + PDFData obj = (PDFData)super.clone(); + obj.paint = this.paint; + obj.backPaint = this.paint; + obj.lineCap = this.lineCap; + obj.lineJoin = this.lineJoin; + obj.miterLimit = this.miterLimit; + obj.text = this.text; + obj.dashOffset = this.dashOffset; + obj.clip = this.clip; + obj.gstate = this.gstate; + return obj; + } + + /** {@inheritDoc} */ + public String toString() { + return super.toString() + + ", paint=" + paint + + ", backPaint=" + backPaint + + ", lineCap=" + lineCap + + ", miterLimit=" + miterLimit + + ", text=" + text + + ", dashOffset=" + dashOffset + + ", clip=" + clip + + ", gstate=" + gstate; + } + + /** {@inheritDoc} */ + protected AbstractData instantiate() { + return new PDFData(); + } + } + +} + diff --git a/src/java/org/apache/fop/pdf/PDFState.java b/src/java/org/apache/fop/pdf/PDFState.java deleted file mode 100644 index 2e9bd6074..000000000 --- a/src/java/org/apache/fop/pdf/PDFState.java +++ /dev/null @@ -1,417 +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.pdf; - -import java.io.Serializable; -import java.util.List; -import java.util.Iterator; - -import java.awt.Color; -import java.awt.Paint; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.GeneralPath; - -/** - * This keeps information about the current state when writing to pdf. - * It allows for creating new graphics states with the q operator. - * This class is only used to store the information about the state - * the caller needs to handle the actual pdf operators. - * - * When setting the state for pdf there are three possible ways of - * handling the situation. - * The values can be set to override previous or default values. - * A new state can be added and then the values set. - * The current state can be popped and values will return to a - * previous state then the necessary values can be overridden. - * The current transform behaves differently to other values as the - * matrix is combined with the current resolved value. - * It is impossible to optimise the result without analysing the all - * the possible combinations after completing. - */ -public class PDFState { - - private Data data = new Data(); - - private List stateStack = new java.util.ArrayList(); - - /** - * PDF State for storing graphics state. - */ - public PDFState() { - - } - - /** - * Push the current state onto the stack. - * This call should be used when the q operator is used - * so that the state is known when popped. - */ - public void push() { - Data copy; - try { - copy = (Data)getData().clone(); - getData().resetTransform(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e.getMessage()); - } - stateStack.add(copy); - } - - /** - * @return the currently valid state - */ - public Data getData() { - return data; - } - - /** - * Pop the state from the stack and set current values to popped state. - * This should be called when a Q operator is used so - * the state is restored to the correct values. - * @return the restored state, null if the stack is empty - */ - public Data pop() { - if (getStackLevel() > 0) { - Data popped = (Data)stateStack.remove(stateStack.size() - 1); - - data = popped; - return popped; - } else { - return null; - } - } - - /** - * Get the current stack level. - * - * @return the current stack level - */ - public int getStackLevel() { - return stateStack.size(); - } - - /** - * Restore the state to a particular level. - * this can be used to restore to a known level without making - * multiple pop calls. - * - * @param stack the level to restore to - */ - /* - public void restoreLevel(int stack) { - int pos = stack; - while (stateStack.size() > pos + 1) { - stateStack.remove(stateStack.size() - 1); - } - if (stateStack.size() > pos) { - pop(); - } - }*/ - - /** - * Set the current line dash. - * Check if setting the line dash to the given values - * will make a change and then set the state to the new values. - * - * @param array the line dash array - * @param offset the line dash start offset - * @return true if the line dash has changed - */ - /* - public boolean setLineDash(int[] array, int offset) { - return false; - }*/ - - /** - * Set the current line width. - * @param width the line width in points - * @return true if the line width has changed - */ - public boolean setLineWidth(float width) { - if (getData().lineWidth != width) { - getData().lineWidth = width; - return true; - } else { - return false; - } - } - - /** - * Set the current color. - * Check if the new color is a change and then set the current color. - * - * @param col the color to set - * @return true if the color has changed - */ - public boolean setColor(Color col) { - if (!col.equals(getData().color)) { - getData().color = col; - return true; - } else { - return false; - } - } - - /** - * Set the current background color. - * Check if the background color will change and then set the new color. - * - * @param col the new background color - * @return true if the background color has changed - */ - public boolean setBackColor(Color col) { - if (!col.equals(getData().backcolor)) { - getData().backcolor = col; - return true; - } else { - return false; - } - } - - /** - * Set the current paint. - * This checks if the paint will change and then sets the current paint. - * - * @param p the new paint - * @return true if the new paint changes the current paint - */ - public boolean setPaint(Paint p) { - if (getData().paint == null) { - if (p != null) { - getData().paint = p; - return true; - } - } else if (!data.paint.equals(p)) { - getData().paint = p; - return true; - } - return false; - } - - /** - * Check if the clip will change the current state. - * A clip is assumed to be used in a situation where it will add - * to any clip in the current or parent states. - * A clip cannot be cleared, this can only be achieved by going to - * a parent level with the correct clip. - * If the clip is different then it may start a new state so that - * it can return to the previous clip. - * - * @param cl the clip shape to check - * @return true if the clip will change the current clip. - */ - public boolean checkClip(Shape cl) { - if (getData().clip == null) { - if (cl != null) { - return true; - } - } else if (!new Area(getData().clip).equals(new Area(cl))) { - return true; - } - //TODO check for clips that are larger than the current - return false; - } - - /** - * Set the current clip. - * This either sets a new clip or sets the clip to the intersect of - * the old clip and the new clip. - * - * @param cl the new clip in the current state - */ - public void setClip(Shape cl) { - if (getData().clip != null) { - Area newClip = new Area(getData().clip); - newClip.intersect(new Area(cl)); - getData().clip = new GeneralPath(newClip); - } else { - getData().clip = cl; - } - } - - /** - * Check the current transform. - * The transform for the current state is the combination of all - * transforms in the current state. The parameter is compared - * against this current transform. - * - * @param tf the transform the check against - * @return true if the new transform is different then the current transform - */ - public boolean checkTransform(AffineTransform tf) { - return !tf.equals(getData().transform); - } - - /** - * Set a new transform. - * This transform is appended to the transform of - * the current graphic state. - * - * @param tf the transform to concatonate to the current level transform - * @deprecated This method name is misleading. Use concatenate(AffineTransform) instead! - */ - public void setTransform(AffineTransform tf) { - concatenate(tf); - } - - /** - * Concatenates the given AffineTransform to the current one. - * @param tf the transform to concatenate to the current level transform - */ - public void concatenate(AffineTransform tf) { - getData().concatenate(tf); - } - - /** - * Get the current transform. - * This gets the combination of all transforms in the - * current state. - * - * @return the calculate combined transform for the current state - */ - public AffineTransform getTransform() { - AffineTransform tf; - AffineTransform at = new AffineTransform(); - for (Iterator iter = stateStack.iterator(); iter.hasNext();) { - Data d = (Data)iter.next(); - tf = d.transform; - at.concatenate(tf); - } - at.concatenate(getData().transform); - return at; - } - - /** - * Get a copy of the base transform for the page. Used to translate - * IPP/BPP values into X,Y positions when positioning is "fixed". - * - * @return the base transform, or null if the state stack is empty - */ - public AffineTransform getBaseTransform() { - if (stateStack.size() == 0) { - return null; - } else { - Data baseData = (Data) stateStack.get(0); - return (AffineTransform) baseData.transform.clone(); - } - } - - /** - * Get the graphics state. - * This gets the combination of all graphic states for - * the current context. - * This is the graphic state set with the gs operator not - * the other graphic state changes. - * - * @return the calculated ExtGState in the current context - */ - public PDFGState getGState() { - PDFGState defaultState = PDFGState.DEFAULT; - - PDFGState state; - PDFGState newstate = new PDFGState(); - newstate.addValues(defaultState); - for (Iterator iter = stateStack.iterator(); iter.hasNext();) { - Data d = (Data)iter.next(); - state = d.gstate; - if (state != null) { - newstate.addValues(state); - } - } - if (getData().gstate != null) { - newstate.addValues(getData().gstate); - } - - return newstate; - } - - public class Data implements Cloneable, Serializable { - - public Color color = Color.black; - public Color backcolor = Color.black; - public Paint paint = null; - public Paint backPaint = null; - public int lineCap = 0; - public int lineJoin = 0; - public float lineWidth = 1; - public float miterLimit = 0; - public boolean text = false; - public int dashOffset = 0; - public int[] dashArray = new int[0]; - public AffineTransform transform = new AffineTransform(); - public float fontSize = 0; - public String fontName = ""; - public Shape clip = null; - public PDFGState gstate = null; - - - /** {@inheritDoc} */ - public Object clone() throws CloneNotSupportedException { - Data obj = new Data(); - obj.color = this.color; - obj.backcolor = this.backcolor; - obj.paint = this.paint; - obj.backPaint = this.paint; - obj.lineCap = this.lineCap; - obj.lineJoin = this.lineJoin; - obj.lineWidth = this.lineWidth; - obj.miterLimit = this.miterLimit; - obj.text = this.text; - obj.dashOffset = this.dashOffset; - obj.dashArray = this.dashArray; - obj.transform = new AffineTransform(this.transform); - obj.fontSize = this.fontSize; - obj.fontName = this.fontName; - obj.clip = this.clip; - obj.gstate = this.gstate; - return obj; - } - - /** - * Get the current Transform. - */ - public AffineTransform getTransform() { - return transform; - } - - public void resetTransform() { - transform = new AffineTransform(); - } - - /** - * Concatenate the given AffineTransform with the current thus creating - * a new viewport. Note that all concatenation operations are logged - * so they can be replayed if necessary (ex. for block-containers with - * "fixed" positioning. - * @param at Transformation to perform - */ - public void concatenate(AffineTransform at) { - transform.concatenate(at); - } - - /** {@inheritDoc} */ - public String toString() { - return super.toString() + ", " + this.transform; - } - } -} - diff --git a/src/java/org/apache/fop/pdf/package.html b/src/java/org/apache/fop/pdf/package.html index e86318adc..383f78da1 100644 --- a/src/java/org/apache/fop/pdf/package.html +++ b/src/java/org/apache/fop/pdf/package.html @@ -1,3 +1,20 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> <HTML> <TITLE>org.apache.fop.pdf Package</TITLE> <BODY> diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java index fb62e653d..5c253fe94 100644 --- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java +++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java @@ -21,26 +21,25 @@ package org.apache.fop.render; // Java import java.awt.Dimension; -import java.awt.Graphics2D; import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; import java.io.IOException; -import org.w3c.dom.Document; - import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.dom.AbstractDocument; import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.gvt.GraphicsNode; - -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; -import org.apache.xmlgraphics.util.QName; - +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.events.EventBroadcaster; import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl; import org.apache.fop.render.RendererContext.RendererContextWrapper; +import org.apache.fop.render.afp.AFPGraphics2DAdapter; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.util.QName; +import org.w3c.dom.Document; /** * Generic XML handler for SVG. Uses Apache Batik for SVG processing and simply paints to @@ -54,6 +53,9 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC protected static final QName CONVERSION_MODE = new QName( ExtensionElementMapping.URI, null, "conversion-mode"); + /** "bitmap" value for the "conversion-mode" extension attribute. */ + protected static final String BITMAP = "bitmap"; + /** {@inheritDoc} */ public void handleXML(RendererContext context, Document doc, String ns) throws Exception { @@ -64,65 +66,97 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC } /** - * Render the SVG document. - * @param context the renderer context - * @param doc the SVG document - * @throws IOException In case of an I/O error while painting the image + * Creates a graphics 2D image painter implementation + * + * @param root the batik graphics node root + * @param ctx the batik bridge context + * @param imageSize the image size + * @return a new graphics 2D image painter implementation */ - protected void renderSVGDocument(final RendererContext context, - final Document doc) throws IOException { - updateRendererContext(context); - final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(context); - int x = wrappedContext.getCurrentXPosition(); - int y = wrappedContext.getCurrentYPosition(); + protected Graphics2DImagePainter createGraphics2DImagePainter( + GraphicsNode root, BridgeContext ctx, Dimension imageSize) { + return new Graphics2DImagePainterImpl(root, ctx, imageSize); + } - //Prepare - SVGUserAgent ua = new SVGUserAgent( - context.getUserAgent(), - new AffineTransform()); + /** + * Builds the GVT root + * + * @param rendererContext the renderer context + * @param ctx the batik bridge context + * @param doc the document + * @return a built GVT root tree + */ + protected GraphicsNode buildGraphicsNode( + FOUserAgent userAgent, BridgeContext ctx, Document doc) { GVTBuilder builder = new GVTBuilder(); - final BridgeContext ctx = new BridgeContext(ua); - - //Build the GVT tree final GraphicsNode root; try { root = builder.build(ctx, doc); } catch (Exception e) { - SVGEventProducer eventProducer = SVGEventProducer.Provider.get( - context.getUserAgent().getEventBroadcaster()); - eventProducer.svgNotBuilt(this, e, getDocumentURI(doc)); - return; + EventBroadcaster eventBroadcaster + = userAgent.getEventBroadcaster(); + SVGEventProducer eventProducer = SVGEventProducer.Provider.get(eventBroadcaster); + final String uri = getDocumentURI(doc); + eventProducer.svgNotBuilt(this, e, uri); + return null; } + return root; + } - //Create the painter - Graphics2DImagePainter painter = new Graphics2DImagePainter() { + /** + * Returns the image size + * @param wrappedContext renderer context wrapper + * + * @return the image size + */ + protected Dimension getImageSize(RendererContextWrapper wrappedContext) { + final int width = wrappedContext.getWidth(); + final int height = wrappedContext.getHeight(); + return new Dimension(width, height); + } - public void paint(Graphics2D g2d, Rectangle2D area) { - // If no viewbox is defined in the svg file, a viewbox of 100x100 is - // assumed, as defined in SVGUserAgent.getViewportSize() - float iw = (float) ctx.getDocumentSize().getWidth(); - float ih = (float) ctx.getDocumentSize().getHeight(); - float w = (float) area.getWidth(); - float h = (float) area.getHeight(); - g2d.scale(w / iw, h / ih); + /** + * Render the SVG document. + * + * @param rendererContext the renderer context + * @param doc the SVG document + * @throws IOException In case of an I/O error while painting the image + */ + protected void renderSVGDocument(final RendererContext rendererContext, + final Document doc) throws IOException { + updateRendererContext(rendererContext); - root.paint(g2d); - } + //Prepare + FOUserAgent userAgent = rendererContext.getUserAgent(); + SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new AffineTransform()); + + //Create Batik BridgeContext + final BridgeContext bridgeContext = new BridgeContext(svgUserAgent); + + //Build the GVT tree - public Dimension getImageSize() { - return new Dimension(wrappedContext.getWidth(), wrappedContext.getHeight()); - } + final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc); - }; + // Create Graphics2DImagePainter + final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext( + rendererContext); + Dimension imageSize = getImageSize(wrappedContext); + final Graphics2DImagePainter painter = createGraphics2DImagePainter(root, bridgeContext, imageSize); //Let the painter paint the SVG on the Graphics2D instance - Graphics2DAdapter adapter = context.getRenderer().getGraphics2DAdapter(); - adapter.paintImage(painter, context, - x, y, wrappedContext.getWidth(), wrappedContext.getHeight()); + Graphics2DAdapter g2dAdapter = rendererContext.getRenderer().getGraphics2DAdapter(); + + //Paint the image + final int x = wrappedContext.getCurrentXPosition(); + final int y = wrappedContext.getCurrentYPosition(); + final int width = wrappedContext.getWidth(); + final int height = wrappedContext.getHeight(); + g2dAdapter.paintImage(painter, rendererContext, x, y, width, height); } /** * Gets the document URI from a Document instance if possible. + * * @param doc the Document * @return the URI or null */ @@ -138,6 +172,7 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC /** * Override this method to update the renderer context if it needs special settings for * certain conditions. + * * @param context the renderer context */ protected void updateRendererContext(RendererContext context) { diff --git a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java index 5861fb042..ee18dff0d 100644 --- a/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java @@ -54,8 +54,8 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { protected BufferedImage paintToBufferedImage( org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter, RendererContextWrapper context, int resolution, boolean gray, boolean withAlpha) { - int bmw = (int)Math.ceil(UnitConv.mpt2px(context.getWidth(), resolution)); - int bmh = (int)Math.ceil(UnitConv.mpt2px(context.getHeight(), resolution)); + int bmw = mpt2px(context.getWidth(), resolution); + int bmh = mpt2px(context.getHeight(), resolution); BufferedImage bi; if (gray) { if (withAlpha) { @@ -102,6 +102,17 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter { return bi; } + /** + * Converts millipoints to pixels + * + * @param unit the unit to convert in mpts + * @param resolution the target resolution + * @return the converted unit in pixels + */ + protected int mpt2px(int unit, int resolution) { + return (int)Math.ceil(UnitConv.mpt2px(unit, resolution)); + } + private static BufferedImage createGrayBufferedImageWithAlpha(int width, int height) { BufferedImage bi; boolean alphaPremultiplied = true; diff --git a/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java new file mode 100644 index 000000000..e8001f2fa --- /dev/null +++ b/src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java @@ -0,0 +1,208 @@ +/* + * 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.render; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.util.Service; + +/** + * This class holds references to various image handlers used by the renderers. It also + * supports automatic discovery of additional handlers available through + * the class path. + */ +public abstract class AbstractImageHandlerRegistry { + + /** the logger */ + private static Log log = LogFactory.getLog(AbstractImageHandlerRegistry.class); + + private static final Comparator HANDLER_COMPARATOR = new Comparator() { + public int compare(Object o1, Object o2) { + ImageHandler h1 = (ImageHandler)o1; + ImageHandler h2 = (ImageHandler)o2; + return h1.getPriority() - h2.getPriority(); + } + }; + + /** Map containing image handlers for various MIME types */ + private final Map/*<Class, ImageHandler>*/ handlers + = new java.util.HashMap/*<Class, ImageHandler>*/(); + + /** List containing the same handlers as above but ordered by priority */ + private final List/*<ImageHandler>*/ handlerList + = new java.util.LinkedList/*<ImageHandler>*/(); + + /** Sorted Set of registered handlers */ + private ImageFlavor[] supportedFlavors = new ImageFlavor[0]; + + private int handlerRegistrations; + private int lastSync; + + /** + * Default constructor. + */ + public AbstractImageHandlerRegistry() { + discoverHandlers(); + } + + /** + * Add an ImageHandler. The handler itself is inspected to find out what it supports. + * @param classname the fully qualified class name + */ + public void addHandler(String classname) { + try { + ImageHandler handlerInstance + = (ImageHandler)Class.forName(classname).newInstance(); + addHandler(handlerInstance); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Could not find " + + classname); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Could not instantiate " + + classname); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Could not access " + + classname); + } catch (ClassCastException e) { + throw new IllegalArgumentException(classname + + " is not an " + + getHandlerClass().getName()); + } + } + + /** + * Add an image handler. The handler itself is inspected to find out what it supports. + * @param handler the ImageHandler instance + */ + public synchronized void addHandler(ImageHandler handler) { + this.handlers.put(handler.getSupportedImageClass(), handler); + + //Sorted insert + ListIterator iter = this.handlerList.listIterator(); + while (iter.hasNext()) { + ImageHandler h = (ImageHandler)iter.next(); + if (getHandlerComparator().compare(handler, h) < 0) { + iter.previous(); + break; + } + } + iter.add(handler); + this.handlerRegistrations++; + } + + /** + * Returns an ImageHandler which handles an specific image type given the MIME type + * of the image. + * @param img the Image to be handled + * @return the ImageHandler responsible for handling the image or null if none is available + */ + public ImageHandler getHandler(Image img) { + return getHandler(img.getClass()); + } + + /** + * Returns an ImageHandler which handles an specific image type given the MIME type + * of the image. + * @param imageClass the Image subclass for which to get a handler + * @return the ImageHandler responsible for handling the image or null if none is available + */ + public synchronized ImageHandler getHandler(Class imageClass) { + ImageHandler handler = null; + Class cl = imageClass; + while (cl != null) { + handler = (ImageHandler)handlers.get(cl); + if (handler != null) { + break; + } + cl = cl.getSuperclass(); + } + return handler; + } + + /** + * Returns the ordered array of supported image flavors. + * @return the array of image flavors + */ + public synchronized ImageFlavor[] getSupportedFlavors() { + if (this.lastSync != this.handlerRegistrations) { + //Extract all ImageFlavors into a single array + List flavors = new java.util.ArrayList(); + Iterator iter = this.handlerList.iterator(); + while (iter.hasNext()) { + ImageFlavor[] f = ((ImageHandler)iter.next()).getSupportedImageFlavors(); + for (int i = 0; i < f.length; i++) { + flavors.add(f[i]); + } + } + this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]); + this.lastSync = this.handlerRegistrations; + } + return this.supportedFlavors; + } + + /** + * Discovers ImageHandler implementations through the classpath and dynamically + * registers them. + */ + private void discoverHandlers() { + // add mappings from available services + Class imageHandlerClass = getHandlerClass(); + Iterator providers = Service.providers(imageHandlerClass); + if (providers != null) { + while (providers.hasNext()) { + ImageHandler handler = (ImageHandler)providers.next(); + try { + if (log.isDebugEnabled()) { + log.debug("Dynamically adding ImageHandler: " + + handler.getClass().getName()); + } + addHandler(handler); + } catch (IllegalArgumentException e) { + log.error("Error while adding ImageHandler", e); + } + + } + } + } + + /** + * Returns the ImageHandler comparator + * + * @return the ImageHandler comparator + */ + public Comparator getHandlerComparator() { + return HANDLER_COMPARATOR; + } + + /** + * Returns the ImageHandler implementing class + * + * @return the ImageHandler implementing class + */ + public abstract Class getHandlerClass(); +} diff --git a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java index 65bb450f3..e74a8f319 100644 --- a/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java +++ b/src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java @@ -26,13 +26,7 @@ import java.awt.geom.Rectangle2D; import java.util.List; import java.util.Map; -import org.w3c.dom.Document; - import org.apache.batik.parser.AWTTransformProducer; - -import org.apache.xmlgraphics.image.loader.ImageSize; -import org.apache.xmlgraphics.util.QName; - import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.area.BlockViewport; @@ -48,7 +42,10 @@ import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontMetrics; import org.apache.fop.traits.BorderProps; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.util.QName; import org.apache.xmlgraphics.util.UnitConv; +import org.w3c.dom.Document; /** * Abstract base class for renderers like PDF and PostScript where many painting operations @@ -270,6 +267,11 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); } + private static final int BEFORE = 0; + private static final int END = 1; + private static final int AFTER = 2; + private static final int START = 3; + /** * Draws borders. * @param borderRect the border rectangle @@ -280,45 +282,46 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { */ protected void drawBorders(Rectangle2D.Float borderRect, BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) { + //TODO generalize each of the four conditions into using a parameterized drawBorder() + boolean[] border = new boolean[] { + (bpsBefore != null), (bpsEnd != null), + (bpsAfter != null), (bpsStart != null)}; float startx = borderRect.x; float starty = borderRect.y; float width = borderRect.width; float height = borderRect.height; - boolean[] b = new boolean[] { - (bpsBefore != null), (bpsEnd != null), - (bpsAfter != null), (bpsStart != null)}; - if (!b[0] && !b[1] && !b[2] && !b[3]) { - return; - } - float[] bw = new float[] { - (b[0] ? bpsBefore.width / 1000f : 0.0f), - (b[1] ? bpsEnd.width / 1000f : 0.0f), - (b[2] ? bpsAfter.width / 1000f : 0.0f), - (b[3] ? bpsStart.width / 1000f : 0.0f)}; + float[] borderWidth = new float[] { + (border[BEFORE] ? bpsBefore.width / 1000f : 0.0f), + (border[END] ? bpsEnd.width / 1000f : 0.0f), + (border[AFTER] ? bpsAfter.width / 1000f : 0.0f), + (border[START] ? bpsStart.width / 1000f : 0.0f)}; float[] clipw = new float[] { BorderProps.getClippedWidth(bpsBefore) / 1000f, BorderProps.getClippedWidth(bpsEnd) / 1000f, BorderProps.getClippedWidth(bpsAfter) / 1000f, BorderProps.getClippedWidth(bpsStart) / 1000f}; - starty += clipw[0]; - height -= clipw[0]; - height -= clipw[2]; - startx += clipw[3]; - width -= clipw[3]; - width -= clipw[1]; + starty += clipw[BEFORE]; + height -= clipw[BEFORE]; + height -= clipw[AFTER]; + startx += clipw[START]; + width -= clipw[START]; + width -= clipw[END]; boolean[] slant = new boolean[] { - (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])}; + (border[START] && border[BEFORE]), + (border[BEFORE] && border[END]), + (border[END] && border[AFTER]), + (border[AFTER] && border[START])}; if (bpsBefore != null) { endTextObject(); float sx1 = startx; - float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1); + float sx2 = (slant[BEFORE] ? sx1 + borderWidth[START] - clipw[START] : sx1); float ex1 = startx + width; - float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1); - float outery = starty - clipw[0]; - float clipy = outery + clipw[0]; - float innery = outery + bw[0]; + float ex2 = (slant[END] ? ex1 - borderWidth[END] + clipw[END] : ex1); + float outery = starty - clipw[BEFORE]; + float clipy = outery + clipw[BEFORE]; + float innery = outery + borderWidth[BEFORE]; saveGraphicsState(); moveTo(sx1, clipy); @@ -326,10 +329,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { float ex1a = ex1; if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { - sx1a -= clipw[3]; + sx1a -= clipw[START]; } if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { - ex1a += clipw[1]; + ex1a += clipw[END]; } lineTo(sx1a, outery); lineTo(ex1a, outery); @@ -347,12 +350,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { endTextObject(); float sy1 = starty; - float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1); + float sy2 = (slant[END] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1); float ey1 = starty + height; - float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1); - float outerx = startx + width + clipw[1]; - float clipx = outerx - clipw[1]; - float innerx = outerx - bw[1]; + float ey2 = (slant[AFTER] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1); + float outerx = startx + width + clipw[END]; + float clipx = outerx - clipw[END]; + float innerx = outerx - borderWidth[END]; saveGraphicsState(); moveTo(clipx, sy1); @@ -360,10 +363,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { float ey1a = ey1; if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { - sy1a -= clipw[0]; + sy1a -= clipw[BEFORE]; } if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { - ey1a += clipw[2]; + ey1a += clipw[AFTER]; } lineTo(outerx, sy1a); lineTo(outerx, ey1a); @@ -380,12 +383,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { endTextObject(); float sx1 = startx; - float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1); + float sx2 = (slant[START] ? sx1 + borderWidth[AFTER] - clipw[AFTER] : sx1); float ex1 = startx + width; - float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1); - float outery = starty + height + clipw[2]; - float clipy = outery - clipw[2]; - float innery = outery - bw[2]; + float ex2 = (slant[AFTER] ? ex1 - borderWidth[END] + clipw[END] : ex1); + float outery = starty + height + clipw[AFTER]; + float clipy = outery - clipw[AFTER]; + float innery = outery - borderWidth[AFTER]; saveGraphicsState(); moveTo(ex1, clipy); @@ -393,10 +396,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { float ex1a = ex1; if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { - sx1a -= clipw[3]; + sx1a -= clipw[START]; } if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { - ex1a += clipw[1]; + ex1a += clipw[END]; } lineTo(ex1a, outery); lineTo(sx1a, outery); @@ -413,12 +416,12 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { endTextObject(); float sy1 = starty; - float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1); + float sy2 = (slant[BEFORE] ? sy1 + borderWidth[BEFORE] - clipw[BEFORE] : sy1); float ey1 = sy1 + height; - float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1); - float outerx = startx - clipw[3]; - float clipx = outerx + clipw[3]; - float innerx = outerx + bw[3]; + float ey2 = (slant[START] ? ey1 - borderWidth[AFTER] + clipw[AFTER] : ey1); + float outerx = startx - clipw[START]; + float clipx = outerx + clipw[START]; + float innerx = outerx + borderWidth[START]; saveGraphicsState(); moveTo(clipx, ey1); @@ -426,10 +429,10 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { float ey1a = ey1; if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) { if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { - sy1a -= clipw[0]; + sy1a -= clipw[BEFORE]; } if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { - ey1a += clipw[2]; + ey1a += clipw[AFTER]; } lineTo(outerx, ey1a); lineTo(outerx, sy1a); @@ -451,10 +454,6 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { * rendered */ protected void renderInlineAreaBackAndBorders(InlineArea area) { - float x = currentIPPosition / 1000f; - float y = (currentBPPosition + area.getOffset()) / 1000f; - float width = area.getIPD() / 1000f; - float height = area.getBPD() / 1000f; float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f; float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f; float bpwidth = borderPaddingStart @@ -462,12 +461,15 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { float bpheight = borderPaddingBefore + (area.getBorderAndPaddingWidthAfter() / 1000f); + float height = area.getBPD() / 1000f; if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) { + float x = currentIPPosition / 1000f; + float y = (currentBPPosition + area.getOffset()) / 1000f; + float width = area.getIPD() / 1000f; drawBackAndBorders(area, x, y - borderPaddingBefore , width + bpwidth , height + bpheight); } - } private static final QName FOX_TRANSFORM @@ -482,26 +484,24 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { int saveBP = currentBPPosition; CTM ctm = bv.getCTM(); - int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - //This is the content-rect - float width = bv.getIPD() / 1000f; - float height = bv.getBPD() / 1000f; - if (bv.getPositioning() == Block.ABSOLUTE - || bv.getPositioning() == Block.FIXED) { + int positioning = bv.getPositioning(); + if (positioning == Block.ABSOLUTE || positioning == Block.FIXED) { //For FIXED, we need to break out of the current viewports to the //one established by the page. We save the state stack for restoration //after the block-container has been painted. See below. List breakOutList = null; - if (bv.getPositioning() == Block.FIXED) { + if (positioning == Block.FIXED) { breakOutList = breakOutOfStateStack(); } AffineTransform positionTransform = new AffineTransform(); positionTransform.translate(bv.getXOffset(), bv.getYOffset()); + int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); + //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); @@ -513,39 +513,62 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { positionTransform.concatenate(freeTransform); } - saveGraphicsState(); //Viewport position - concatenateTransformationMatrix(UnitConv.mptToPt(positionTransform)); + if (!positionTransform.isIdentity()) { + establishTransformationMatrix(positionTransform); + } + + //This is the content-rect + float width = bv.getIPD() / 1000f; + float height = bv.getBPD() / 1000f; //Background and borders - float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; - float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; - drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); + float borderPaddingWidth + = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; + float borderPaddingHeight + = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; + drawBackAndBorders(bv, 0, 0, width + borderPaddingWidth, height + borderPaddingHeight); //Shift to content rectangle after border painting AffineTransform contentRectTransform = new AffineTransform(); contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); - concatenateTransformationMatrix(UnitConv.mptToPt(contentRectTransform)); + + if (!contentRectTransform.isIdentity()) { + establishTransformationMatrix(contentRectTransform); + } //Clipping if (bv.getClip()) { clipRect(0f, 0f, width, height); } - saveGraphicsState(); //Set up coordinate system for content rectangle AffineTransform contentTransform = ctm.toAffineTransform(); - concatenateTransformationMatrix(UnitConv.mptToPt(contentTransform)); + if (!contentTransform.isIdentity()) { + establishTransformationMatrix(contentTransform); + } currentIPPosition = 0; currentBPPosition = 0; renderBlocks(bv, children); - restoreGraphicsState(); - restoreGraphicsState(); + if (!contentTransform.isIdentity()) { + restoreGraphicsState(); + } + + if (!contentRectTransform.isIdentity()) { + restoreGraphicsState(); + } + + if (!positionTransform.isIdentity()) { + restoreGraphicsState(); + } - if (breakOutList != null) { - restoreStateStackAfterBreakOut(breakOutList); + //For FIXED, we need to restore break out now we are done + if (positioning == Block.FIXED) { + if (breakOutList != null) { + restoreStateStackAfterBreakOut(breakOutList); + } } currentIPPosition = saveIP; @@ -598,8 +621,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { at.translate(0, block.getSpaceBefore()); if (!at.isIdentity()) { - saveGraphicsState(); - concatenateTransformationMatrix(UnitConv.mptToPt(at)); + establishTransformationMatrix(at); } currentIPPosition = 0; @@ -631,8 +653,7 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { at.translate(currentIPPosition, currentBPPosition); if (!at.isIdentity()) { - saveGraphicsState(); - concatenateTransformationMatrix(UnitConv.mptToPt(at)); + establishTransformationMatrix(at); } currentIPPosition = 0; @@ -844,4 +865,16 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer { renderDocument(doc, ns, pos, fo.getForeignAttributes()); } + /** + * Establishes a new coordinate system with the given transformation matrix. + * The current graphics state is saved and the new coordinate system is concatenated. + * @param block + * + * @param at the transformation matrix + */ + protected void establishTransformationMatrix(AffineTransform at) { + saveGraphicsState(); + concatenateTransformationMatrix(UnitConv.mptToPt(at)); + } + } diff --git a/src/java/org/apache/fop/render/AbstractRenderer.java b/src/java/org/apache/fop/render/AbstractRenderer.java index c29dbea15..9e977cd80 100644 --- a/src/java/org/apache/fop/render/AbstractRenderer.java +++ b/src/java/org/apache/fop/render/AbstractRenderer.java @@ -28,11 +28,8 @@ import java.util.Iterator; import java.util.List; import java.util.Set; -import org.w3c.dom.Document; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.area.Area; @@ -68,6 +65,7 @@ import org.apache.fop.area.inline.WordArea; import org.apache.fop.events.ResourceEventProducer; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; +import org.w3c.dom.Document; /** * Abstract base class for all renderers. The Abstract renderer does all the @@ -504,7 +502,7 @@ public abstract class AbstractRenderer */ protected void renderBlocks(Block parent, List blocks) { int saveIP = currentIPPosition; - int saveBP = currentBPPosition; +// int saveBP = currentBPPosition; // Calculate the position of the content rectangle. if (parent != null && !parent.getTraitAsBoolean(Trait.IS_VIEWPORT_AREA)) { diff --git a/src/java/org/apache/fop/render/ImageHandler.java b/src/java/org/apache/fop/render/ImageHandler.java new file mode 100644 index 000000000..6a44c01a9 --- /dev/null +++ b/src/java/org/apache/fop/render/ImageHandler.java @@ -0,0 +1,45 @@ +/* + * 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.render; + +import org.apache.xmlgraphics.image.loader.ImageFlavor; + +public interface ImageHandler { + + /** + * Returns the priority for this image handler. A lower value means higher priority. This + * information is used to build the ordered/prioritized list of supported ImageFlavors. + * The built-in handlers use priorities between 100 and 999. + * @return a positive integer (>0) indicating the priority + */ + int getPriority(); + + /** + * Returns the {@link ImageFlavor}s supported by this instance + * @return the supported image flavors + */ + ImageFlavor[] getSupportedImageFlavors(); + + /** + * Returns the {@link Class} subclass supported by this instance. + * @return the image Class type + */ + Class getSupportedImageClass(); +} diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java index 56504ff53..e4ec41e0b 100644 --- a/src/java/org/apache/fop/render/PrintRenderer.java +++ b/src/java/org/apache/fop/render/PrintRenderer.java @@ -24,8 +24,6 @@ import java.awt.geom.Rectangle2D; import java.util.List; import java.util.Map; -import org.w3c.dom.Document; - import org.apache.fop.area.Area; import org.apache.fop.area.Trait; import org.apache.fop.fonts.CustomFontCollection; @@ -36,6 +34,7 @@ import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.base14.Base14FontCollection; +import org.w3c.dom.Document; /** Abstract base class of "Print" type renderers. */ public abstract class PrintRenderer extends AbstractRenderer { @@ -112,6 +111,14 @@ public abstract class PrintRenderer extends AbstractRenderer { } /** + * Instantiates a RendererContext for an image + * @return a newly created RendererContext. + */ + protected RendererContext instantiateRendererContext() { + return new RendererContext(this, getMimeType()); + } + + /** * Creates a RendererContext for an image. * @param x the x coordinate (in millipoints) * @param y the y coordinate (in millipoints) @@ -122,8 +129,7 @@ public abstract class PrintRenderer extends AbstractRenderer { */ protected RendererContext createRendererContext(int x, int y, int width, int height, Map foreignAttributes) { - RendererContext context; - context = new RendererContext(this, getMimeType()); + RendererContext context = instantiateRendererContext(); context.setUserAgent(userAgent); context.setProperty(RendererContextConstants.WIDTH, diff --git a/src/java/org/apache/fop/render/RendererContext.java b/src/java/org/apache/fop/render/RendererContext.java index 08ca76957..ac885a44b 100644 --- a/src/java/org/apache/fop/render/RendererContext.java +++ b/src/java/org/apache/fop/render/RendererContext.java @@ -20,10 +20,12 @@ package org.apache.fop.render; //Java +import java.util.Iterator; import java.util.Map; -//FOP import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.xmlgraphics.util.QName; /** * The Render Context for external handlers. This provides a rendering context @@ -31,21 +33,28 @@ import org.apache.fop.apps.FOUserAgent; * render target. */ public class RendererContext { + /** conversion-mode extension attribute */ + protected static final QName CONVERSION_MODE = new QName( + ExtensionElementMapping.URI, null, "conversion-mode"); - private String mime; - private AbstractRenderer renderer; + /** "bitmap" value for the "conversion-mode" extension attribute. */ + protected static final String BITMAP = "bitmap"; + + private final String mime; + private final AbstractRenderer renderer; private FOUserAgent userAgent; - private Map props = new java.util.HashMap(); + + private final Map/*<String,Object>*/ props = new java.util.HashMap/*<String,Object>*/(); /** - * Contructor for this class. It takes a MIME type as parameter. + * Constructor for this class. It takes a MIME type as parameter. * - * @param renderer The current renderer - * @param m The MIME type of the output that's generated. + * @param renderer the current renderer + * @param mime the MIME type of the output that's generated. */ - public RendererContext(AbstractRenderer renderer, String m) { + public RendererContext(AbstractRenderer renderer, String mime) { this.renderer = renderer; - this.mime = m; + this.mime = mime; } /** @@ -113,6 +122,19 @@ public class RendererContext { return wrapper; } + /** {@inheritDoc} **/ + public String toString() { + StringBuffer stringBuffer = new StringBuffer("RendererContext{\n"); + Iterator it = props.keySet().iterator(); + while (it.hasNext()) { + String key = (String)it.next(); + Object value = props.get(key); + stringBuffer.append("\t" + key + "=" + value + "\n"); + } + stringBuffer.append("}"); + return stringBuffer.toString(); + } + /** * Base class for a wrapper around RendererContext to access its properties in a type-safe, * renderer-specific way. @@ -159,6 +181,19 @@ public class RendererContext { public Map getForeignAttributes() { return (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); } + + /** {@inheritDoc} */ + public String toString() { + return "RendererContextWrapper{" + + "userAgent=" + getUserAgent() + + "x=" + getCurrentXPosition() + + "y=" + getCurrentYPosition() + + "width=" + getWidth() + + "height=" + getHeight() + + "foreignAttributes=" + getForeignAttributes() + + "}"; + + } } } diff --git a/src/java/org/apache/fop/render/afp/AFPEventProducer.xml b/src/java/org/apache/fop/render/afp/AFPEventProducer.xml deleted file mode 100644 index 8eec9b656..000000000 --- a/src/java/org/apache/fop/render/afp/AFPEventProducer.xml +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<catalogue xml:lang="en"> - <message key="org.apache.fop.render.afp.AFPEventProducer.warnDefaultFontSetup">No AFP fonts configured. Using default setup.</message> -</catalogue> diff --git a/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java new file mode 100644 index 000000000..2b5077fe9 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java @@ -0,0 +1,128 @@ +/* + * 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.render.afp; + +import java.io.File; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceLevel; +import org.apache.fop.render.afp.extensions.AFPElementMapping; +import org.apache.xmlgraphics.util.QName; + +/** + * Parses any AFP foreign attributes + */ +public class AFPForeignAttributeReader { + private static final Log log = LogFactory.getLog("org.apache.xmlgraphics.afp"); + + /** the resource-name attribute */ + public static final String RESOURCE_NAME = "afp:resource-name"; + + /** the resource-level attribute */ + public static final String RESOURCE_LEVEL = "afp:resource-level"; + + /** the resource-group-file attribute */ + public static final String RESOURCE_GROUP_FILE = "afp:resource-group-file"; + + /** + * Main constructor + */ + public AFPForeignAttributeReader() { + } + + /** + * Returns the resource information + * + * @param foreignAttributes the foreign attributes + * @return the resource information + */ + public AFPResourceInfo getResourceInfo(Map/*<QName, String>*/ foreignAttributes) { + AFPResourceInfo resourceInfo = new AFPResourceInfo(); + if (foreignAttributes != null && !foreignAttributes.isEmpty()) { + QName resourceNameKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_NAME); + String resourceName = (String)foreignAttributes.get(resourceNameKey); + if (resourceName != null) { + resourceInfo.setName(resourceName); + } + AFPResourceLevel level = getResourceLevel(foreignAttributes); + if (level != null) { + resourceInfo.setLevel(level); + } + } + return resourceInfo; + } + + /** + * Returns the resource level + * + * @param foreignAttributes the foreign attributes + * @return the resource level + */ + public AFPResourceLevel getResourceLevel(Map/*<QName, String>*/ foreignAttributes) { + AFPResourceLevel resourceLevel = null; + if (foreignAttributes != null && !foreignAttributes.isEmpty()) { + QName resourceLevelKey = new QName(AFPElementMapping.NAMESPACE, RESOURCE_LEVEL); + if (foreignAttributes.containsKey(resourceLevelKey)) { + String levelString = (String)foreignAttributes.get(resourceLevelKey); + resourceLevel = AFPResourceLevel.valueOf(levelString); + // if external get resource group file attributes + if (resourceLevel != null && resourceLevel.isExternal()) { + QName resourceGroupFileKey = new QName(AFPElementMapping.NAMESPACE, + RESOURCE_GROUP_FILE); + String resourceGroupFile + = (String)foreignAttributes.get(resourceGroupFileKey); + if (resourceGroupFile == null) { + String msg = RESOURCE_GROUP_FILE + " not specified"; + log.error(msg); + throw new UnsupportedOperationException(msg); + } + File resourceExternalGroupFile = new File(resourceGroupFile); + SecurityManager security = System.getSecurityManager(); + try { + if (security != null) { + security.checkWrite(resourceExternalGroupFile.getPath()); + } + } catch (SecurityException ex) { + String msg = "unable to gain write access to external resource file: " + + resourceGroupFile; + log.error(msg); + } + + try { + boolean exists = resourceExternalGroupFile.exists(); + if (exists) { + log.warn("overwriting external resource file: " + + resourceGroupFile); + } + resourceLevel.setExternalFilePath(resourceGroupFile); + } catch (SecurityException ex) { + String msg = "unable to gain read access to external resource file: " + + resourceGroupFile; + log.error(msg); + } + } + } + } + return resourceLevel; + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java index 18ac4dbb6..becafda23 100644 --- a/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java @@ -19,40 +19,87 @@ package org.apache.fop.render.afp; +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; -import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; - +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.afp.AFPGraphicsObjectInfo; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPResourceManager; import org.apache.fop.render.AbstractGraphics2DAdapter; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContext.RendererContextWrapper; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; /** * Graphics2DAdapter implementation for AFP. */ public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter { + private final AFPPaintingState paintingState; + /** * Main constructor + * + * @param paintingState the AFP painting state */ - public AFPGraphics2DAdapter() { + public AFPGraphics2DAdapter(AFPPaintingState paintingState) { + this.paintingState = paintingState; } /** {@inheritDoc} */ public void paintImage(Graphics2DImagePainter painter, - RendererContext context, + RendererContext rendererContext, int x, int y, int width, int height) throws IOException { - RendererContext.RendererContextWrapper wrappedContext - = new RendererContext.RendererContextWrapper(context); - AFPRenderer afp = (AFPRenderer)context.getRenderer(); - Boolean grayObj = (Boolean)context.getProperty(AFPRendererContextConstants.AFP_GRAYSCALE); - boolean gray = (grayObj != null ? grayObj.booleanValue() : false); - //Paint to a BufferedImage - int resolution = (int)Math.round(context.getUserAgent().getTargetResolution()); - BufferedImage bi = paintToBufferedImage(painter, wrappedContext, resolution, gray, false); + AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext; + AFPInfo afpInfo = afpRendererContext.getInfo(); + + final boolean textAsShapes = false; + AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes); + + paintingState.save(); + + //Fallback solution: Paint to a BufferedImage + if (afpInfo.paintAsBitmap()) { - afp.drawBufferedImage(bi, resolution, x, y, width, height); + // paint image + RendererContextWrapper rendererContextWrapper + = RendererContext.wrapRendererContext(rendererContext); + float targetResolution = rendererContext.getUserAgent().getTargetResolution(); + int resolution = Math.round(targetResolution); + boolean colorImages = afpInfo.isColorSupported(); + BufferedImage bufferedImage = paintToBufferedImage( + painter, rendererContextWrapper, resolution, !colorImages, false); + + // draw image + AffineTransform at = paintingState.getData().getTransform(); + at.translate(x, y); + g2d.drawImage(bufferedImage, at, null); + } else { + AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo(); + graphicsObjectInfo.setPainter(painter); + graphicsObjectInfo.setGraphics2D(g2d); + + // get the 'width' and 'height' attributes of the SVG document + Dimension imageSize = painter.getImageSize(); + float imw = (float)imageSize.getWidth() / 1000f; + float imh = (float)imageSize.getHeight() / 1000f; + + Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); + graphicsObjectInfo.setArea(area); + AFPResourceManager resourceManager = afpInfo.getResourceManager(); + resourceManager.createObject(graphicsObjectInfo); + } + + paintingState.restore(); } + /** {@inheritDoc} */ + protected int mpt2px(int unit, int resolution) { + return Math.round(paintingState.getUnitConverter().mpt2units(unit)); + } } diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandler.java b/src/java/org/apache/fop/render/afp/AFPImageHandler.java new file mode 100644 index 000000000..3ec3ea0b1 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandler.java @@ -0,0 +1,104 @@ +/* + * 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.render.afp; + +import java.awt.Point; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.util.Map; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPUnitConverter; +import org.apache.fop.render.ImageHandler; + +/** + * A base abstract AFP image handler + */ +public abstract class AFPImageHandler implements ImageHandler { + private static final int X = 0; + private static final int Y = 1; + + /** foreign attribute reader */ + private final AFPForeignAttributeReader foreignAttributeReader + = new AFPForeignAttributeReader(); + + /** + * Generates an intermediate AFPDataObjectInfo that is later used to construct + * the appropriate data object in the AFP DataStream. + * + * @param rendererImageInfo the renderer image info + * @return a data object info object + * @throws IOException thrown if an I/O exception of some sort has occurred. + */ + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { + AFPDataObjectInfo dataObjectInfo = createDataObjectInfo(); + + // set resource information + Map foreignAttributes = rendererImageInfo.getForeignAttributes(); + AFPResourceInfo resourceInfo + = foreignAttributeReader.getResourceInfo(foreignAttributes); + resourceInfo.setUri(rendererImageInfo.getURI()); + dataObjectInfo.setResourceInfo(resourceInfo); + + // set object area + AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); + + Point origin = rendererImageInfo.getOrigin(); + Rectangle2D position = rendererImageInfo.getPosition(); + float srcX = origin.x + (float)position.getX(); + float srcY = origin.y + (float)position.getY(); + + AFPRendererContext rendererContext + = (AFPRendererContext)rendererImageInfo.getRendererContext(); + AFPInfo afpInfo = rendererContext.getInfo(); + AFPPaintingState paintingState = afpInfo.getPaintingState(); + AFPUnitConverter unitConv = paintingState.getUnitConverter(); + int[] coords = unitConv.mpts2units(new float[] {srcX, srcY}); + objectAreaInfo.setX(coords[X]); + objectAreaInfo.setY(coords[Y]); + + int width = Math.round(unitConv.mpt2units((float)position.getWidth())); + objectAreaInfo.setWidth(width); + + int height = Math.round(unitConv.mpt2units((float)position.getHeight())); + objectAreaInfo.setHeight(height); + + int resolution = paintingState.getResolution(); + objectAreaInfo.setHeightRes(resolution); + objectAreaInfo.setWidthRes(resolution); + + objectAreaInfo.setRotation(paintingState.getRotation()); + + dataObjectInfo.setObjectAreaInfo(objectAreaInfo); + + return dataObjectInfo; + } + + /** + * Creates the data object information object + * + * @return the data object information object + */ + protected abstract AFPDataObjectInfo createDataObjectInfo(); +} diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java new file mode 100644 index 000000000..0780e8a59 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java @@ -0,0 +1,110 @@ +/* + * 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.render.afp; + +import java.io.IOException; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.afp.AFPGraphicsObjectInfo; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceLevel; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * PDFImageHandler implementation which handles Graphics2D images. + */ +public class AFPImageHandlerGraphics2D extends AFPImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.GRAPHICS2D + }; + + /** {@inheritDoc} */ + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { + + AFPRendererContext rendererContext + = (AFPRendererContext)rendererImageInfo.getRendererContext(); + AFPInfo afpInfo = rendererContext.getInfo(); + ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage(); + Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter(); + + if (afpInfo.paintAsBitmap()) { + int x = afpInfo.getX(); + int y = afpInfo.getY(); + int width = afpInfo.getWidth(); + int height = afpInfo.getHeight(); + AFPPaintingState paintingState = afpInfo.getPaintingState(); + AFPGraphics2DAdapter g2dAdapter = new AFPGraphics2DAdapter(paintingState); + g2dAdapter.paintImage(painter, rendererContext, x, y, width, height); + return null; + } else { + AFPGraphicsObjectInfo graphicsObjectInfo + = (AFPGraphicsObjectInfo)super.generateDataObjectInfo(rendererImageInfo); + + AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo(); + //level not explicitly set/changed so default to inline for GOCA graphic objects + // (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07), hard copy works just fine) + if (!resourceInfo.levelChanged()) { + resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE)); + } + + // set mime type (unsupported by MOD:CA registry) + graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA); + + // set g2d + boolean textAsShapes = false; + + AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes); + + graphicsObjectInfo.setGraphics2D(g2d); + + // set painter + graphicsObjectInfo.setPainter(painter); + + return graphicsObjectInfo; + } + } + + /** {@inheritDoc} */ + public int getPriority() { + return 200; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageGraphics2D.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + + /** {@inheritDoc} */ + protected AFPDataObjectInfo createDataObjectInfo() { + return new AFPGraphicsObjectInfo(); + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java new file mode 100644 index 000000000..3ac1d5696 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java @@ -0,0 +1,72 @@ +/* + * 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.render.afp; + +import java.io.IOException; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPImageObjectInfo; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; + +/** + * AFPImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4). + */ +public class AFPImageHandlerRawCCITTFax extends AbstractAFPImageHandlerRawStream { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.RAW_CCITTFAX, + }; + + /** {@inheritDoc} */ + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { + AFPImageObjectInfo imageObjectInfo + = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo); + + ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.getImage(); + int compression = ccitt.getCompression(); + imageObjectInfo.setCompression(compression); + + imageObjectInfo.setBitsPerPixel(1); + return imageObjectInfo; + } + + /** {@inheritDoc} */ + protected AFPDataObjectInfo createDataObjectInfo() { + return new AFPImageObjectInfo(); + } + + /** {@inheritDoc} */ + public int getPriority() { + return 400; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageRawCCITTFax.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java new file mode 100644 index 000000000..ded9ec9d5 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java @@ -0,0 +1,55 @@ +/* + * 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.render.afp; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; + +/** + * AFPImageHandler implementation which handles raw stream images. + */ +public class AFPImageHandlerRawStream extends AbstractAFPImageHandlerRawStream { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.RAW_JPEG, + ImageFlavor.RAW_EPS, + }; + + /** {@inheritDoc} */ + public int getPriority() { + return 200; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageRawStream.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + + /** {@inheritDoc} */ + protected AFPDataObjectInfo createDataObjectInfo() { + return new AFPDataObjectInfo(); + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java new file mode 100644 index 000000000..59ca6cf38 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java @@ -0,0 +1,42 @@ +/* + * 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.render.afp; + +import org.apache.fop.render.AbstractImageHandlerRegistry; + +/** + * This class holds references to various image handlers used by the AFP renderer. It also + * supports automatic discovery of additional handlers available through + * the class path. + */ +public class AFPImageHandlerRegistry extends AbstractImageHandlerRegistry { + + /** + * Main constructor + */ + public AFPImageHandlerRegistry() { + } + + /** {@inheritDoc} */ + public Class getHandlerClass() { + return AFPImageHandler.class; + } + +} diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java new file mode 100644 index 000000000..28c942a08 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java @@ -0,0 +1,116 @@ +/* + * 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.render.afp; + +import java.awt.image.RenderedImage; +import java.io.IOException; + +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPImageObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; +import org.apache.xmlgraphics.util.MimeConstants; + +/** + * PDFImageHandler implementation which handles RenderedImage instances. + */ +public class AFPImageHandlerRenderedImage extends AFPImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE + }; + + /** {@inheritDoc} */ + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { + AFPImageObjectInfo imageObjectInfo + = (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo); + + AFPRendererContext rendererContext + = (AFPRendererContext)rendererImageInfo.getRendererContext(); + AFPInfo afpInfo = rendererContext.getInfo(); + AFPPaintingState paintingState = afpInfo.getPaintingState(); + int resolution = paintingState.getResolution(); + + imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45); + imageObjectInfo.setDataHeightRes(resolution); + imageObjectInfo.setDataWidthRes(resolution); + + ImageRendered imageRendered = (ImageRendered) rendererImageInfo.img; + RenderedImage renderedImage = imageRendered.getRenderedImage(); + + int dataHeight = renderedImage.getHeight(); + imageObjectInfo.setDataHeight(dataHeight); + + int dataWidth = renderedImage.getWidth(); + imageObjectInfo.setDataWidth(dataWidth); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos); + byte[] imageData = baos.toByteArray(); + + boolean colorImages = paintingState.isColorImages(); + imageObjectInfo.setColor(colorImages); + + // convert to grayscale + if (!colorImages) { + baos.reset(); + int bitsPerPixel = paintingState.getBitsPerPixel(); + imageObjectInfo.setBitsPerPixel(bitsPerPixel); + ImageEncodingHelper.encodeRGBAsGrayScale( + imageData, dataWidth, dataHeight, bitsPerPixel, baos); + imageData = baos.toByteArray(); + } + imageObjectInfo.setData(imageData); + + // set object area info + AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo(); + objectAreaInfo.setWidthRes(resolution); + objectAreaInfo.setHeightRes(resolution); + + return imageObjectInfo; + } + + /** {@inheritDoc} */ + protected AFPDataObjectInfo createDataObjectInfo() { + return new AFPImageObjectInfo(); + } + + /** {@inheritDoc} */ + public int getPriority() { + return 300; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageRendered.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + +} diff --git a/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java b/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java new file mode 100644 index 000000000..7ea1a7a10 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java @@ -0,0 +1,77 @@ +/* + * 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.render.afp; + +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.util.Map; + +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContextConstants; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.w3c.dom.Document; + +/** + * PDFImageHandler implementation which handles XML-based images. + */ +public class AFPImageHandlerXML extends AFPImageHandler { + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.XML_DOM, + }; + + /** {@inheritDoc} */ + public AFPDataObjectInfo generateDataObjectInfo(AFPRendererImageInfo rendererImageInfo) + throws IOException { + RendererContext rendererContext = rendererImageInfo.getRendererContext(); + AFPRenderer renderer = (AFPRenderer)rendererContext.getRenderer(); + ImageXMLDOM imgXML = (ImageXMLDOM)rendererImageInfo.getImage(); + Document doc = imgXML.getDocument(); + String ns = imgXML.getRootNamespace(); + Map foreignAttributes = (Map)rendererContext.getProperty( + RendererContextConstants.FOREIGN_ATTRIBUTES); + Rectangle2D pos = rendererImageInfo.getPosition(); + renderer.renderDocument(doc, ns, pos, foreignAttributes); + return null; + } + + /** {@inheritDoc} */ + public int getPriority() { + return 400; + } + + /** {@inheritDoc} */ + public Class getSupportedImageClass() { + return ImageXMLDOM.class; + } + + /** {@inheritDoc} */ + public ImageFlavor[] getSupportedImageFlavors() { + return FLAVORS; + } + + /** {@inheritDoc} */ + protected AFPDataObjectInfo createDataObjectInfo() { + return null; + } + +} diff --git a/src/java/org/apache/fop/render/afp/AFPInfo.java b/src/java/org/apache/fop/render/afp/AFPInfo.java new file mode 100644 index 000000000..fb1ec87a8 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPInfo.java @@ -0,0 +1,310 @@ +/* + * 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.render.afp; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceManager; +import org.apache.fop.fonts.FontInfo; + +/** + * AFP information structure for drawing the XML document. + */ +public final class AFPInfo { + /** see WIDTH */ + private int width; + + /** see HEIGHT */ + private int height; + + /** see XPOS */ + private int x; + + /** see YPOS */ + private int y; + + /** see HANDLER_CONFIGURATION */ + private Configuration handlerConfiguration; + + /** see AFP_FONT_INFO */ + private FontInfo fontInfo; + + /** See AFP_PAINTING_STATE */ + private AFPPaintingState paintingState; + + /** See AFP_RESOURCE_MANAGER */ + private AFPResourceManager resourceManager; + + /** See AFP_RESOURCE_INFO */ + private AFPResourceInfo resourceInfo; + + /** true if SVG should be rendered as a bitmap instead of natively */ + private boolean paintAsBitmap; + + /** + * Returns the width. + * + * @return the width + */ + public int getWidth() { + return width; + } + + /** + * Sets the width. + * + * @param width The pageWidth to set + */ + public void setWidth(int width) { + this.width = width; + } + + /** + * Returns the height. + * + * @return the height + */ + public int getHeight() { + return height; + } + + /** + * Sets the height. + * + * @param height The height to set + */ + public void setHeight(int height) { + this.height = height; + } + + /** + * Returns the handler configuration + * + * @return the handler configuration + */ + public Configuration getHandlerConfiguration() { + return this.handlerConfiguration; + } + + /** + * Sets the handler configuration + * + * @param cfg the handler configuration + */ + public void setHandlerConfiguration(Configuration cfg) { + this.handlerConfiguration = cfg; + } + + /** + * Return the font info + * + * @return the font info + */ + public FontInfo getFontInfo() { + return this.fontInfo; + } + + /** + * Returns the current AFP state + * + * @return the current AFP state + */ + public AFPPaintingState getPaintingState() { + return this.paintingState; + } + + /** + * Returns the AFPResourceManager + * + * @return the AFPResourceManager + */ + public AFPResourceManager getResourceManager() { + return this.resourceManager; + } + + /** + * Returns true if supports color + * + * @return true if supports color + */ + public boolean isColorSupported() { + return getPaintingState().isColorImages(); + } + + /** + * Returns the current x position coordinate + * + * @return the current x position coordinate + */ + protected int getX() { + return x; + } + + /** + * Returns the current y position coordinate + * + * @return the current y position coordinate + */ + protected int getY() { + return y; + } + + /** + * Returns the resolution + * + * @return the resolution + */ + protected int getResolution() { + return getPaintingState().getResolution(); + } + + /** + * Returns the number of bits per pixel to use + * @return the number of bits per pixel to use + */ + protected int getBitsPerPixel() { + return getPaintingState().getBitsPerPixel(); + } + + /** + * Sets the current x position coordinate + * + * @param x the current x position coordinate + */ + protected void setX(int x) { + this.x = x; + } + + /** + * Sets the current y position coordinate + * + * @param y the current y position coordinate + */ + protected void setY(int y) { + this.y = y; + } + + /** + * Sets the current font info + * + * @param fontInfo the current font info + */ + protected void setFontInfo(FontInfo fontInfo) { + this.fontInfo = fontInfo; + } + + /** + * Sets the AFP state + * + * @param paintingState the AFP state + */ + public void setPaintingState(AFPPaintingState paintingState) { + this.paintingState = paintingState; + } + + /** + * Sets the AFPResourceManager + * + * @param resourceManager the AFPResourceManager + */ + public void setResourceManager(AFPResourceManager resourceManager) { + this.resourceManager = resourceManager; + } + + /** + * Sets true if SVG should be rendered as a bitmap instead of natively + * + * @param b boolean value + */ + public void setPaintAsBitmap(boolean b) { + this.paintAsBitmap = b; + } + + /** + * Returns true if SVG should be rendered as a bitmap instead of natively + * + * @return true if SVG should be rendered as a bitmap instead of natively + */ + public boolean paintAsBitmap() { + return this.paintAsBitmap; + } + + /** + * Returns true if text should be stroked when painted + * + * @return true if text should be stroked when painted + */ + public boolean strokeText() { + boolean strokeText = false; + if (handlerConfiguration != null) { + strokeText = handlerConfiguration.getChild("stroke-text", true).getValueAsBoolean(strokeText); + } + return strokeText; + } + + /** + * Sets the resource information + * + * @param resourceInfo the resource information + */ + public void setResourceInfo(AFPResourceInfo resourceInfo) { + this.resourceInfo = resourceInfo; + } + + /** + * Returns the resource information + * + * @return the resource information + */ + public AFPResourceInfo getResourceInfo() { + return resourceInfo; + } + + /** + * Creates an AFPGraphics2D implementation + * + * @param textAsShapes true when text is painted as shapes + * @return a newly created AFPGraphics2D + */ + public AFPGraphics2D createGraphics2D(boolean textAsShapes) { + AFPGraphics2D g2d = new AFPGraphics2D( + textAsShapes, paintingState, resourceManager, resourceInfo, fontInfo); + g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); + return g2d; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPInfo{width=" + width + + ", height=" + height + + ", x=" + x + + ", y=" + y + + ", cfg=" + handlerConfiguration + + ", fontInfo=" + fontInfo + + ", resourceManager=" + resourceManager + + ", paintingState=" + paintingState + + ", paintAsBitmap=" + paintAsBitmap + + ", resourceInfo=" + resourceInfo + + "}"; + } + +}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java index d5129f167..8035a9490 100644 --- a/src/java/org/apache/fop/render/afp/AFPRenderer.java +++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java @@ -23,56 +23,46 @@ import java.awt.Color; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.RenderedImage; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.ByteArrayOutputStream; - -import org.apache.xmlgraphics.image.codec.tiff.TIFFImage; -import org.apache.xmlgraphics.image.loader.ImageException; -import org.apache.xmlgraphics.image.loader.ImageFlavor; -import org.apache.xmlgraphics.image.loader.ImageInfo; -import org.apache.xmlgraphics.image.loader.ImageManager; -import org.apache.xmlgraphics.image.loader.ImageSessionContext; -import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; -import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; -import org.apache.xmlgraphics.image.loader.impl.ImageRendered; -import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; -import org.apache.xmlgraphics.image.loader.util.ImageUtil; -import org.apache.xmlgraphics.ps.ImageEncodingHelper; - +import org.apache.fop.afp.AFPBorderPainter; +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPEventProducer; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPRectanglePainter; +import org.apache.fop.afp.AFPResourceManager; +import org.apache.fop.afp.AFPTextDataInfo; +import org.apache.fop.afp.AFPUnitConverter; +import org.apache.fop.afp.BorderPaintingInfo; +import org.apache.fop.afp.DataStream; +import org.apache.fop.afp.RectanglePaintingInfo; +import org.apache.fop.afp.fonts.AFPFont; +import org.apache.fop.afp.fonts.AFPFontAttributes; +import org.apache.fop.afp.fonts.AFPFontCollection; +import org.apache.fop.afp.fonts.AFPPageFonts; +import org.apache.fop.afp.fonts.CharacterSet; +import org.apache.fop.afp.modca.PageObject; +import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; -import org.apache.fop.area.Block; -import org.apache.fop.area.BlockViewport; -import org.apache.fop.area.BodyRegion; import org.apache.fop.area.CTM; -import org.apache.fop.area.NormalFlow; +import org.apache.fop.area.LineArea; import org.apache.fop.area.OffDocumentItem; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.RegionReference; -import org.apache.fop.area.RegionViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.Image; import org.apache.fop.area.inline.Leader; -import org.apache.fop.area.inline.SpaceArea; import org.apache.fop.area.inline.TextArea; -import org.apache.fop.area.inline.WordArea; import org.apache.fop.datatypes.URISpecification; import org.apache.fop.events.ResourceEventProducer; -import org.apache.fop.fo.Constants; import org.apache.fop.fo.extensions.ExtensionAttachment; import org.apache.fop.fonts.FontCollection; import org.apache.fop.fonts.FontInfo; @@ -82,13 +72,13 @@ import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; import org.apache.fop.render.afp.extensions.AFPElementMapping; import org.apache.fop.render.afp.extensions.AFPPageSetup; -import org.apache.fop.render.afp.fonts.AFPFont; -import org.apache.fop.render.afp.fonts.AFPFontCollection; -import org.apache.fop.render.afp.modca.AFPConstants; -import org.apache.fop.render.afp.modca.AFPDataStream; -import org.apache.fop.render.afp.modca.ImageObject; -import org.apache.fop.render.afp.modca.PageObject; -import org.apache.fop.util.ColorUtil; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; +import org.apache.xmlgraphics.ps.ImageEncodingHelper; /** * This is an implementation of a FOP Renderer that renders areas to AFP. @@ -139,140 +129,55 @@ import org.apache.fop.util.ColorUtil; * rectangles. * </p> * - * Note: There are specific extensions that have been added to the - * FO. They are specific to their location within the FO and have to be - * processed accordingly (ie. at the start or end of the page). + * Note: There are specific extensions that have been added to the FO. They are + * specific to their location within the FO and have to be processed accordingly + * (ie. at the start or end of the page). * */ public class AFPRenderer extends AbstractPathOrientedRenderer { - /** - * The default afp renderer output resolution - */ - private static final int DEFAULT_DPI_RESOLUTION = 240; - - /** - * The afp factor for calculating resolutions (e.g. 72000/240 = 300) - */ - private static final int DPI_CONVERSION_FACTOR = 72000; - - /** - * The afp data stream object responsible for generating afp data - */ - private AFPDataStream afpDataStream = null; + private static final int X = 0; + private static final int Y = 1; - /** - * The map of afp root extensions - */ - // UNUSED - // private HashMap rootExtensionMap = null; - /** - * The map of page segments - */ - private HashMap pageSegmentsMap = null; + /** the resource manager */ + private AFPResourceManager resourceManager; - /** - * The fonts on the current page - */ - private HashMap currentPageFonts = null; + /** the painting state */ + private final AFPPaintingState paintingState; - /** - * The current color object - */ - private Color currentColor = null; + /** unit converter */ + private final AFPUnitConverter unitConv; - /** - * The page font number counter, used to determine the next font reference - */ - private int pageFontCounter = 0; + /** the line painter */ + private AFPBorderPainter borderPainter; - /** - * The current font family - */ - // UNUSED - // private String currentFontFamily = ""; - /** - * The current font size - */ - private int currentFontSize = 0; + /** the map of page segments */ + private final Map/*<String,String>*/pageSegmentMap + = new java.util.HashMap/*<String,String>*/(); - /** - * The Options to be set on the AFPRenderer - */ - // UNUSED - // private Map afpOptions = null; - /** - * The page width - */ - private int pageWidth = 0; + /** the map of saved incomplete pages */ + private final Map pages = new java.util.HashMap/*<PageViewport,PageObject>*/(); - /** - * The page height - */ - private int pageHeight = 0; + /** the AFP datastream */ + private DataStream dataStream; - /** - * The current page sequence id - */ - // UNUSED - // private String pageSequenceId = null; - /** - * The portrait rotation - */ - private int portraitRotation = 0; + /** the image handler registry */ + private final AFPImageHandlerRegistry imageHandlerRegistry; - /** - * The landscape rotation - */ - private int landscapeRotation = 270; - - /** - * The line cache, avoids drawing duplicate lines in tables. - */ - // UNUSED - // private HashSet lineCache = null; - /** - * The current x position for line drawing - */ - // UNUSED - // private float x; - /** - * The current y position for line drawing - */ - // UNUSED - // private float y; - /** - * The map of saved incomplete pages - */ - private Map pages = null; - - /** - * Flag to the set the output object type for images - */ - private boolean colorImages = false; - - /** - * Default value for image depth - */ - private int bitsPerPixel = 8; - - /** - * The output resolution - */ - private int resolution = DEFAULT_DPI_RESOLUTION; + private AFPRectanglePainter rectanglePainter; /** * Constructor for AFPRenderer. */ public AFPRenderer() { super(); + this.imageHandlerRegistry = new AFPImageHandlerRegistry(); + this.resourceManager = new AFPResourceManager(); + this.paintingState = new AFPPaintingState(); + this.unitConv = paintingState.getUnitConverter(); } - /** - * Set up the font info - * - * @param inFontInfo font info to set up - */ + /** {@inheritDoc} */ public void setupFontInfo(FontInfo inFontInfo) { this.fontInfo = inFontInfo; FontManager fontManager = userAgent.getFactory().getFontManager(); @@ -282,885 +187,272 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { fontManager.setup(getFontInfo(), fontCollections); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setUserAgent(FOUserAgent agent) { super.setUserAgent(agent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startRenderer(OutputStream outputStream) throws IOException { - currentPageFonts = new HashMap(); - currentColor = new Color(255, 255, 255); - afpDataStream = new AFPDataStream(); - afpDataStream.setPortraitRotation(portraitRotation); - afpDataStream.setLandscapeRotation(landscapeRotation); - afpDataStream.startDocument(outputStream); + paintingState.setColor(Color.WHITE); + + this.dataStream = resourceManager.createDataStream(paintingState, outputStream); + this.borderPainter = new AFPBorderPainter(paintingState, dataStream); + this.rectanglePainter = new AFPRectanglePainter(paintingState, dataStream); + + dataStream.startDocument(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void stopRenderer() throws IOException { - afpDataStream.endDocument(); + dataStream.endDocument(); + resourceManager.writeToStream(); + resourceManager = null; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ + public void startPageSequence(LineArea seqTitle) { + try { + dataStream.startPageGroup(); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + /** {@inheritDoc} */ public boolean supportsOutOfOrder() { - //return false; - return true; + return false; } - /** - * Prepare a page for rendering. This is called if the renderer supports - * out of order rendering. The renderer should prepare the page so that a - * page further on in the set of pages can be rendered. The body of the - * page should not be rendered. The page will be rendered at a later time - * by the call to render page. - * - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void preparePage(PageViewport page) { - // initializeRootExtensions(page); - - // this.currentFontFamily = ""; - this.currentFontSize = 0; - this.pageFontCounter = 0; - this.currentPageFonts.clear(); - // this.lineCache = new HashSet(); - - Rectangle2D bounds = page.getViewArea(); - - this.pageWidth = mpts2units(bounds.getWidth()); - this.pageHeight = mpts2units(bounds.getHeight()); - - // renderPageGroupExtensions(page); - - final int pageRotation = 0; - this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, - getResolution(), getResolution()); + int pageRotation = paintingState.getPageRotation(); + int pageWidth = paintingState.getPageWidth(); + int pageHeight = paintingState.getPageHeight(); + int resolution = paintingState.getResolution(); + dataStream.startPage(pageWidth, pageHeight, pageRotation, + resolution, resolution); renderPageObjectExtensions(page); - if (this.pages == null) { - this.pages = new HashMap(); - } - this.pages.put(page, afpDataStream.savePage()); - + PageObject currentPage = dataStream.savePage(); + pages.put(page, currentPage); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void processOffDocumentItem(OffDocumentItem odi) { // TODO + log.debug("NYI processOffDocumentItem(" + odi + ")"); } /** {@inheritDoc} */ public Graphics2DAdapter getGraphics2DAdapter() { - return new AFPGraphics2DAdapter(); + return new AFPGraphics2DAdapter(paintingState); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void startVParea(CTM ctm, Rectangle2D clippingRect) { - // dummy not used - } - - /** - * {@inheritDoc} - */ - public void endVParea() { - // dummy not used - } - - /** - * Renders a region viewport. <p> - * - * The region may clip the area and it establishes a position from where - * the region is placed.</p> - * - * @param port The region viewport to be rendered - */ - public void renderRegionViewport(RegionViewport port) { - if (port != null) { - Rectangle2D view = port.getViewArea(); - // The CTM will transform coordinates relative to - // this region-reference area into page coords, so - // set origin for the region to 0,0. - currentBPPosition = 0; - currentIPPosition = 0; - - RegionReference regionReference = port.getRegionReference(); - handleRegionTraits(port); - - /* - _afpDataStream.startOverlay(mpts2units(view.getX()) - , mpts2units(view.getY()) - , mpts2units(view.getWidth()) - , mpts2units(view.getHeight()) - , rotation); - */ - - pushViewPortPos(new ViewPortPos(view, regionReference.getCTM())); - - if (regionReference.getRegionClass() == FO_REGION_BODY) { - renderBodyRegion((BodyRegion) regionReference); - } else { - renderRegion(regionReference); - } - /* - _afpDataStream.endOverlay(); - */ - popViewPortPos(); + saveGraphicsState(); + if (ctm != null) { + AffineTransform at = ctm.toAffineTransform(); + concatenateTransformationMatrix(at); } - } - - /** {@inheritDoc} */ - protected void renderBlockViewport(BlockViewport bv, List children) { - // clip and position viewport if necessary - - // save positions - int saveIP = currentIPPosition; - int saveBP = currentBPPosition; - - CTM ctm = bv.getCTM(); - int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); - int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); - //This is the content-rect - float width = (float)bv.getIPD() / 1000f; - float height = (float)bv.getBPD() / 1000f; - - if (bv.getPositioning() == Block.ABSOLUTE - || bv.getPositioning() == Block.FIXED) { - - //For FIXED, we need to break out of the current viewports to the - //one established by the page. We save the state stack for restoration - //after the block-container has been painted. See below. - List breakOutList = null; - if (bv.getPositioning() == Block.FIXED) { - breakOutList = breakOutOfStateStack(); - } - - AffineTransform positionTransform = new AffineTransform(); - positionTransform.translate(bv.getXOffset(), bv.getYOffset()); - - //"left/"top" (bv.getX/YOffset()) specify the position of the content rectangle - positionTransform.translate(-borderPaddingStart, -borderPaddingBefore); - - //skipping fox:transform here - - //saveGraphicsState(); - //Viewport position - //concatenateTransformationMatrix(mptToPt(positionTransform)); - - //Background and borders - float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; - float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; - Point2D ptSrc = new Point(0, 0); - Point2D ptDst = positionTransform.transform(ptSrc, null); - Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), - 1000 * (width + bpwidth), 1000 * (height + bpheight)); - pushViewPortPos(new ViewPortPos(borderRect, new CTM(positionTransform))); - drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight); - - //Shift to content rectangle after border painting - AffineTransform contentRectTransform = new AffineTransform(); - contentRectTransform.translate(borderPaddingStart, borderPaddingBefore); - //concatenateTransformationMatrix(mptToPt(contentRectTransform)); - ptSrc = new Point(0, 0); - ptDst = contentRectTransform.transform(ptSrc, null); - Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(), ptDst.getY(), - 1000 * width, 1000 * height); - pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentRectTransform))); - - //Clipping is not supported, yet - //Rectangle2D clippingRect = null; - //clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD()); - - //saveGraphicsState(); - //Set up coordinate system for content rectangle - AffineTransform contentTransform = ctm.toAffineTransform(); - //concatenateTransformationMatrix(mptToPt(contentTransform)); - contentRect = new Rectangle2D.Double(0, 0, 1000 * width, 1000 * height); - pushViewPortPos(new ViewPortPos(contentRect, new CTM(contentTransform))); - - currentIPPosition = 0; - currentBPPosition = 0; - renderBlocks(bv, children); - - popViewPortPos(); - popViewPortPos(); - //restoreGraphicsState(); - popViewPortPos(); - //restoreGraphicsState(); - - if (breakOutList != null) { - restoreStateStackAfterBreakOut(breakOutList); - } - - currentIPPosition = saveIP; - currentBPPosition = saveBP; - } else { - - currentBPPosition += bv.getSpaceBefore(); - - //borders and background in the old coordinate system - handleBlockTraits(bv); - - //Advance to start of content area - currentIPPosition += bv.getStartIndent(); - - CTM tempctm = new CTM(containingIPPosition, currentBPPosition); - ctm = tempctm.multiply(ctm); - - //Now adjust for border/padding - currentBPPosition += borderPaddingBefore; - - Rectangle2D clippingRect = null; - clippingRect = new Rectangle(currentIPPosition, currentBPPosition, - bv.getIPD(), bv.getBPD()); - - //startVParea(ctm, clippingRect); - pushViewPortPos(new ViewPortPos(clippingRect, ctm)); - - currentIPPosition = 0; - currentBPPosition = 0; - renderBlocks(bv, children); - //endVParea(); - popViewPortPos(); - - currentIPPosition = saveIP; - currentBPPosition = saveBP; - - currentBPPosition += (int)(bv.getAllocBPD()); + if (clippingRect != null) { + clipRect((float)clippingRect.getX() / 1000f, + (float)clippingRect.getY() / 1000f, + (float)clippingRect.getWidth() / 1000f, + (float)clippingRect.getHeight() / 1000f); } } /** {@inheritDoc} */ - protected void renderReferenceArea(Block block) { - //TODO Remove this method once concatenateTransformationMatrix() is implemented - - // save position and offset - int saveIP = currentIPPosition; - int saveBP = currentBPPosition; - - //Establish a new coordinate system - AffineTransform at = new AffineTransform(); - at.translate(currentIPPosition, currentBPPosition); - at.translate(block.getXOffset(), block.getYOffset()); - at.translate(0, block.getSpaceBefore()); - - if (!at.isIdentity()) { - Rectangle2D contentRect - = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(), - block.getAllocIPD(), block.getAllocBPD()); - pushViewPortPos(new ViewPortPos(contentRect, new CTM(at))); - } - - currentIPPosition = 0; - currentBPPosition = 0; - handleBlockTraits(block); - - List children = block.getChildAreas(); - if (children != null) { - renderBlocks(block, children); - } - - if (!at.isIdentity()) { - popViewPortPos(); - } - - // stacked and relative blocks effect stacking - currentIPPosition = saveIP; - currentBPPosition = saveBP; + public void endVParea() { + restoreGraphicsState(); } /** {@inheritDoc} */ - protected void renderFlow(NormalFlow flow) { - // save position and offset - int saveIP = currentIPPosition; - int saveBP = currentBPPosition; - - //Establish a new coordinate system - AffineTransform at = new AffineTransform(); - at.translate(currentIPPosition, currentBPPosition); - - if (!at.isIdentity()) { - Rectangle2D contentRect - = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(), - flow.getAllocIPD(), flow.getAllocBPD()); - pushViewPortPos(new ViewPortPos(contentRect, new CTM(at))); - } - - currentIPPosition = 0; - currentBPPosition = 0; - super.renderFlow(flow); - + protected void concatenateTransformationMatrix(AffineTransform at) { if (!at.isIdentity()) { - popViewPortPos(); + paintingState.concatenate(at); } - - // stacked and relative blocks effect stacking - currentIPPosition = saveIP; - currentBPPosition = saveBP; - } - - - /** {@inheritDoc} */ - protected void concatenateTransformationMatrix(AffineTransform at) { - //Not used here since AFPRenderer defines its own renderBlockViewport() method. - throw new UnsupportedOperationException("NYI"); } /** - * {@inheritDoc} + * Returns the base AFP transform + * + * @return the base AFP transform */ - public void renderPage(PageViewport pageViewport) { - - // initializeRootExtensions(page); + private AffineTransform getBaseTransform() { + AffineTransform baseTransform = new AffineTransform(); + double scale = unitConv.mpt2units(1); + baseTransform.scale(scale, scale); + return baseTransform; + } - // this.currentFontFamily = ""; - this.currentFontSize = 0; - this.pageFontCounter = 0; - this.currentPageFonts.clear(); - // this.lineCache = new HashSet(); + /** {@inheritDoc} */ + public void renderPage(PageViewport pageViewport) throws IOException, FOPException { + paintingState.clear(); Rectangle2D bounds = pageViewport.getViewArea(); - this.pageWidth = mpts2units(bounds.getWidth()); - this.pageHeight = mpts2units(bounds.getHeight()); - - if (pages != null && pages.containsKey(pageViewport)) { - - this.afpDataStream.restorePage((PageObject) pages.remove(pageViewport)); + AffineTransform baseTransform = getBaseTransform(); + paintingState.concatenate(baseTransform); + if (pages.containsKey(pageViewport)) { + dataStream.restorePage( + (PageObject)pages.remove(pageViewport)); } else { - // renderPageGroupExtensions(page); - - final int pageRotation = 0; - this.afpDataStream.startPage(pageWidth, pageHeight, pageRotation, - getResolution(), getResolution()); - - renderPageObjectExtensions(pageViewport); - - } - - pushViewPortPos(new ViewPortPos()); + int pageWidth + = Math.round(unitConv.mpt2units((float)bounds.getWidth())); + paintingState.setPageWidth(pageWidth); - renderPageAreas(pageViewport.getPage()); + int pageHeight + = Math.round(unitConv.mpt2units((float)bounds.getHeight())); + paintingState.setPageHeight(pageHeight); - Iterator i = currentPageFonts.values().iterator(); - while (i.hasNext()) { - AFPFontAttributes afpFontAttributes = (AFPFontAttributes) i.next(); + int pageRotation = paintingState.getPageRotation(); - afpDataStream.createFont( - (byte)afpFontAttributes.getFontReference(), - afpFontAttributes.getFont(), - afpFontAttributes.getPointSize()); + int resolution = paintingState.getResolution(); - } + dataStream.startPage(pageWidth, pageHeight, pageRotation, + resolution, resolution); - try { - afpDataStream.endPage(); - } catch (IOException ioex) { - // TODO What shall we do? + renderPageObjectExtensions(pageViewport); } - popViewPortPos(); - - } - - /** - * {@inheritDoc} - */ - public void clip() { - // TODO - } + super.renderPage(pageViewport); - /** - * {@inheritDoc} - */ - public void clipRect(float x, float y, float width, float height) { - // TODO - } + AFPPageFonts pageFonts = paintingState.getPageFonts(); + if (pageFonts != null && !pageFonts.isEmpty()) { + dataStream.addFontsToCurrentPage(pageFonts); + } - /** - * {@inheritDoc} - */ - public void moveTo(float x, float y) { - // TODO + dataStream.endPage(); } - /** - * {@inheritDoc} - */ - public void lineTo(float x, float y) { - // TODO - } - - /** - * {@inheritDoc} - */ - public void closePath() { - // TODO + /** {@inheritDoc} */ + public void drawBorderLine(float x1, float y1, float x2, float y2, + boolean horz, boolean startOrBefore, int style, Color col) { + BorderPaintingInfo borderPaintInfo = new BorderPaintingInfo(x1, y1, x2, y2, horz, style, col); + borderPainter.paint(borderPaintInfo); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void fillRect(float x, float y, float width, float height) { - /* - afpDataStream.createShading( - pts2units(x), - pts2units(y), - pts2units(width), - pts2units(height), - currentColor.getRed(), - currentColor.getGreen(), - currentColor.getBlue()); - */ - afpDataStream.createLine( - pts2units(x), - pts2units(y), - pts2units(x + width), - pts2units(y), - pts2units(height), - currentColor); + RectanglePaintingInfo rectanglePaintInfo = new RectanglePaintingInfo(x, y, width, height); + rectanglePainter.paint(rectanglePaintInfo); } - /** - * {@inheritDoc} - */ - public void drawBorderLine(float x1, float y1, float x2, float y2, - boolean horz, boolean startOrBefore, int style, Color col) { - float w = x2 - x1; - float h = y2 - y1; - if ((w < 0) || (h < 0)) { - log.error("Negative extent received. Border won't be painted."); - return; - } - switch (style) { - case Constants.EN_DOUBLE: - if (horz) { - float h3 = h / 3; - float ym1 = y1; - float ym2 = ym1 + h3 + h3; - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1), - pts2units(x2), - pts2units(ym1), - pts2units(h3), - col - ); - afpDataStream.createLine( - pts2units(x1), - pts2units(ym2), - pts2units(x2), - pts2units(ym2), - pts2units(h3), - col - ); - } else { - float w3 = w / 3; - float xm1 = x1; - float xm2 = xm1 + w3 + w3; - afpDataStream.createLine( - pts2units(xm1), - pts2units(y1), - pts2units(xm1), - pts2units(y2), - pts2units(w3), - col - ); - afpDataStream.createLine( - pts2units(xm2), - pts2units(y1), - pts2units(xm2), - pts2units(y2), - pts2units(w3), - col - ); - } - break; - case Constants.EN_DASHED: - if (horz) { - float w2 = 2 * h; - while (x1 + w2 < x2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1 + w2), - pts2units(y1), - pts2units(h), - col - ); - x1 += 2 * w2; - } - } else { - float h2 = 2 * w; - while (y1 + h2 < y2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1), - pts2units(y1 + h2), - pts2units(w), - col - ); - y1 += 2 * h2; - } - } - break; - case Constants.EN_DOTTED: - if (horz) { - while (x1 + h < x2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1 + h), - pts2units(y1), - pts2units(h), - col - ); - x1 += 2 * h; - } - } else { - while (y1 + w < y2) { - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(x1), - pts2units(y1 + w), - pts2units(w), - col - ); - y1 += 2 * w; - } - } - break; - case Constants.EN_GROOVE: - case Constants.EN_RIDGE: - { - float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); - if (horz) { - Color uppercol = ColorUtil.lightenColor(col, -colFactor); - Color lowercol = ColorUtil.lightenColor(col, colFactor); - float h3 = h / 3; - float ym1 = y1; - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1), - pts2units(x2), - pts2units(ym1), - pts2units(h3), - uppercol - ); - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1 + h3), - pts2units(x2), - pts2units(ym1 + h3), - pts2units(h3), - col - ); - afpDataStream.createLine( - pts2units(x1), - pts2units(ym1 + h3 + h3), - pts2units(x2), - pts2units(ym1 + h3 + h3), - pts2units(h3), - lowercol - ); - } else { - Color leftcol = ColorUtil.lightenColor(col, -colFactor); - Color rightcol = ColorUtil.lightenColor(col, colFactor); - float w3 = w / 3; - float xm1 = x1 + (w3 / 2); - afpDataStream.createLine( - pts2units(xm1), - pts2units(y1), - pts2units(xm1), - pts2units(y2), - pts2units(w3), - leftcol - ); - afpDataStream.createLine( - pts2units(xm1 + w3), - pts2units(y1), - pts2units(xm1 + w3), - pts2units(y2), - pts2units(w3), - col - ); - afpDataStream.createLine( - pts2units(xm1 + w3 + w3), - pts2units(y1), - pts2units(xm1 + w3 + w3), - pts2units(y2), - pts2units(w3), - rightcol - ); - } - break; - } - case Constants.EN_HIDDEN: - break; - case Constants.EN_INSET: - case Constants.EN_OUTSET: - default: - afpDataStream.createLine( - pts2units(x1), - pts2units(y1), - pts2units(horz ? x2 : x1), - pts2units(horz ? y1 : y2), - pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), - col - ); - } + /** {@inheritDoc} */ + protected RendererContext instantiateRendererContext() { + return new AFPRendererContext(this, getMimeType()); } - /** - * {@inheritDoc} - */ - protected RendererContext createRendererContext(int x, int y, int width, int height, - Map foreignAttributes) { + /** {@inheritDoc} */ + protected RendererContext createRendererContext(int x, int y, int width, + int height, Map foreignAttributes) { RendererContext context; - context = super.createRendererContext(x, y, width, height, foreignAttributes); - context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, - Boolean.valueOf(!this.colorImages)); + context = super.createRendererContext(x, y, width, height, + foreignAttributes); + context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO, + this.fontInfo); + context.setProperty(AFPRendererContextConstants.AFP_RESOURCE_MANAGER, + this.resourceManager); + context.setProperty(AFPRendererContextConstants.AFP_PAINTING_STATE, paintingState); return context; } - private static final ImageFlavor[] FLAVORS = new ImageFlavor[] - {ImageFlavor.RAW_CCITTFAX, - ImageFlavor.GRAPHICS2D, - ImageFlavor.BUFFERED_IMAGE, - ImageFlavor.RENDERED_IMAGE, - ImageFlavor.XML_DOM}; + private static final ImageFlavor[] NATIVE_FLAVORS = new ImageFlavor[] { + ImageFlavor.XML_DOM, + /*ImageFlavor.RAW_PNG, */ // PNG not natively supported in AFP + ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS, + ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE }; + + private static final ImageFlavor[] FLAVORS = new ImageFlavor[] { + ImageFlavor.XML_DOM, + ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE }; /** {@inheritDoc} */ public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { uri = URISpecification.getURL(uri); - Rectangle posInt = new Rectangle( - (int)pos.getX(), - (int)pos.getY(), - (int)pos.getWidth(), - (int)pos.getHeight()); + paintingState.setImageUri(uri); + Point origin = new Point(currentIPPosition, currentBPPosition); + Rectangle posInt = new Rectangle( + (int)Math.round(pos.getX()), + (int)Math.round(pos.getY()), + (int)Math.round(pos.getWidth()), + (int)Math.round(pos.getHeight()) + ); int x = origin.x + posInt.x; int y = origin.y + posInt.y; - String name = null; - if (pageSegmentsMap != null) { - name = (String) pageSegmentsMap.get(uri); - } + String name = (String)pageSegmentMap.get(uri); if (name != null) { - afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y)); + float[] srcPts = {x, y}; + int[] coords = unitConv.mpts2units(srcPts); + dataStream.createIncludePageSegment(name, coords[X], coords[Y]); } else { - ImageManager manager = getUserAgent().getFactory().getImageManager(); + ImageManager manager = userAgent.getFactory().getImageManager(); ImageInfo info = null; try { - ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); + ImageSessionContext sessionContext = userAgent + .getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - //Only now fully load/prepare the image + // Only now fully load/prepare the image Map hints = ImageUtil.getDefaultHints(sessionContext); + + boolean nativeImagesSupported = paintingState.isNativeImagesSupported(); + ImageFlavor[] flavors = nativeImagesSupported ? NATIVE_FLAVORS : FLAVORS; + + // Load image org.apache.xmlgraphics.image.loader.Image img = manager.getImage( - info, FLAVORS, hints, sessionContext); - - //...and process the image - if (img instanceof ImageGraphics2D) { - ImageGraphics2D imageG2D = (ImageGraphics2D)img; - RendererContext context = createRendererContext( - posInt.x, posInt.y, - posInt.width, posInt.height, foreignAttributes); - getGraphics2DAdapter().paintImage(imageG2D.getGraphics2DImagePainter(), - context, - origin.x + posInt.x, origin.y + posInt.y, - posInt.width, posInt.height); - } else if (img instanceof ImageRendered) { - ImageRendered imgRend = (ImageRendered)img; - RenderedImage ri = imgRend.getRenderedImage(); - - drawBufferedImage(ri, getResolution(), - posInt.x + currentIPPosition, - posInt.y + currentBPPosition, - posInt.width, - posInt.height); - } else if (img instanceof ImageRawCCITTFax) { - ImageRawCCITTFax ccitt = (ImageRawCCITTFax)img; - int afpx = mpts2units(posInt.x + currentIPPosition); - int afpy = mpts2units(posInt.y + currentBPPosition); - int afpw = mpts2units(posInt.getWidth()); - int afph = mpts2units(posInt.getHeight()); - int afpres = getResolution(); - ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, afph, - afpres, afpres); - io.setImageParameters( - (int) (ccitt.getSize().getDpiHorizontal() * 10), - (int) (ccitt.getSize().getDpiVertical() * 10), - ccitt.getSize().getWidthPx(), - ccitt.getSize().getHeightPx()); - int compression = ccitt.getCompression(); - switch (compression) { - case TIFFImage.COMP_FAX_G3_1D : - io.setImageEncoding((byte) 0x80); - break; - case TIFFImage.COMP_FAX_G3_2D : - io.setImageEncoding((byte) 0x81); - break; - case TIFFImage.COMP_FAX_G4_2D : - io.setImageEncoding((byte) 0x82); - break; - default: - throw new IllegalStateException( - "Invalid compression scheme: " + compression); - } - InputStream in = ccitt.createInputStream(); + info, flavors, hints, sessionContext); + + // Handle image + AFPImageHandler imageHandler + = (AFPImageHandler)imageHandlerRegistry.getHandler(img); + if (imageHandler != null) { + RendererContext rendererContext = createRendererContext( + x, y, posInt.width, posInt.height, foreignAttributes); + AFPRendererImageInfo rendererImageInfo = new AFPRendererImageInfo( + uri, pos, origin, info, img, rendererContext, foreignAttributes); + AFPDataObjectInfo dataObjectInfo = null; try { - byte[] buf = IOUtils.toByteArray(in); - io.setImageData(buf); - } finally { - IOUtils.closeQuietly(in); + dataObjectInfo = imageHandler.generateDataObjectInfo(rendererImageInfo); + // Create image + if (dataObjectInfo != null) { + resourceManager.createObject(dataObjectInfo); + } + } catch (IOException ioe) { + ResourceEventProducer eventProducer + = ResourceEventProducer.Provider.get(userAgent.getEventBroadcaster()); + eventProducer.imageWritingError(this, ioe); + throw ioe; } - } else if (img instanceof ImageXMLDOM) { - ImageXMLDOM imgXML = (ImageXMLDOM)img; - renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(), - pos, foreignAttributes); } else { - throw new UnsupportedOperationException("Unsupported image type: " + img); + throw new UnsupportedOperationException( + "No AFPImageHandler available for image: " + + info + " (" + img.getClass().getName() + ")"); } } catch (ImageException ie) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.imageError(this, (info != null ? info.toString() : uri), ie, null); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider + .get(userAgent.getEventBroadcaster()); + eventProducer.imageError(this, (info != null ? info.toString() + : uri), ie, null); } catch (FileNotFoundException fe) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.imageNotFound(this, (info != null ? info.toString() : uri), fe, null); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider + .get(userAgent.getEventBroadcaster()); + eventProducer.imageNotFound(this, (info != null ? info.toString() + : uri), fe, null); } catch (IOException ioe) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.imageIOError(this, (info != null ? info.toString() : uri), ioe, null); + ResourceEventProducer eventProducer = ResourceEventProducer.Provider + .get(userAgent.getEventBroadcaster()); + eventProducer.imageIOError(this, (info != null ? info.toString() + : uri), ioe, null); } - - /* - ImageFactory fact = userAgent.getFactory().getImageFactory(); - FopImage fopimage = fact.getImage(url, userAgent); - if (fopimage == null) { - return; - } - if (!fopimage.load(FopImage.DIMENSIONS)) { - return; - } - String mime = fopimage.getMimeType(); - if ("text/xml".equals(mime) || MimeConstants.MIME_SVG.equals(mime)) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - Document doc = ((XMLImage) fopimage).getDocument(); - String ns = ((XMLImage) fopimage).getNameSpace(); - - renderDocument(doc, ns, pos, foreignAttributes); - } else if (MimeConstants.MIME_EPS.equals(mime)) { - log.warn("EPS images are not supported by this renderer"); - */ - /* - * } else if (MimeConstants.MIME_JPEG.equals(mime)) { if - * (!fopimage.load(FopImage.ORIGINAL_DATA)) { return; } - * fact.releaseImage(url, userAgent); - * - * int x = mpts2units(pos.getX() + currentIPPosition); int y = - * mpts2units(pos.getY() + currentBPPosition); int w = - * mpts2units(pos.getWidth()); int h = - * mpts2units(pos.getHeight()); ImageObject io = - * _afpDataStream.getImageObject(); io.setImageViewport(x, y, w, - * h); io.setImageParameters( - * (int)(fopimage.getHorizontalResolution() * 10), - * (int)(fopimage.getVerticalResolution() * 10), - * fopimage.getWidth(), fopimage.getHeight() ); - * io.setImageIDESize((byte)fopimage.getBitsPerPixel()); - * io.setImageEncoding((byte)0x83); - * io.setImageData(fopimage.getRessourceBytes()); - *//* - } else if (MimeConstants.MIME_TIFF.equals(mime) - && fopimage instanceof TIFFImage) { - TIFFImage tiffImage = (TIFFImage) fopimage; - int x = mpts2units(pos.getX() + currentIPPosition); - int y = mpts2units(pos.getY() + currentBPPosition); - int w = mpts2units(pos.getWidth()); - int h = mpts2units(pos.getHeight()); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, - getResolution(), getResolution()); - io.setImageParameters( - (int)(fopimage.getHorizontalResolution() * 10), - (int)(fopimage.getVerticalResolution() * 10), - fopimage.getWidth(), - fopimage.getHeight() - ); - if (tiffImage.getStripCount() == 1) { - int comp = tiffImage.getCompression(); - if (comp == 3) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - io.setImageEncoding((byte)0x81); - io.setImageData(fopimage.getRessourceBytes()); - } else if (comp == 4) { - if (!fopimage.load(FopImage.ORIGINAL_DATA)) { - return; - } - io.setImageEncoding((byte)0x82); - io.setImageData(fopimage.getRessourceBytes()); - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; - } - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight()); - } - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; - } - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight()); - } - } else { - if (!fopimage.load(FopImage.BITMAP)) { - return; - } - fact.releaseImage(url, userAgent); - - int x = mpts2units(pos.getX() + currentIPPosition); - int y = mpts2units(pos.getY() + currentBPPosition); - int w = mpts2units(pos.getWidth()); - int h = mpts2units(pos.getHeight()); - ImageObject io = afpDataStream.getImageObject(x, y, w, h, - getResolution(), getResolution()); - io.setImageParameters( - (int)(fopimage.getHorizontalResolution() * 10), - (int)(fopimage.getVerticalResolution() * 10), - fopimage.getWidth(), - fopimage.getHeight() - ); - if (colorImages) { - io.setImageIDESize((byte)24); - io.setImageData(fopimage.getBitmaps()); - } else { - convertToGrayScaleImage(io, fopimage.getBitmaps(), - fopimage.getWidth(), fopimage.getHeight()); - } - }*/ } } @@ -1173,364 +465,155 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * the OutputStream * @throws IOException * In case of an I/O error. + * @deprecated use ImageEncodingHelper.encodeRenderedImageAsRGB(image, out) + * directly instead */ public static void writeImage(RenderedImage image, OutputStream out) throws IOException { ImageEncodingHelper.encodeRenderedImageAsRGB(image, out); } - /** - * Draws a BufferedImage to AFP. - * - * @param image - * the RenderedImage - * @param imageResolution - * the resolution of the BufferedImage - * @param x - * the x coordinate (in mpt) - * @param y - * the y coordinate (in mpt) - * @param w - * the width of the viewport (in mpt) - * @param h - * the height of the viewport (in mpt) - */ - public void drawBufferedImage(RenderedImage image, int imageResolution, int x, - int y, int w, int h) { - int afpx = mpts2units(x); - int afpy = mpts2units(y); - int afpw = mpts2units(w); - int afph = mpts2units(h); - int afpres = getResolution(); - ByteArrayOutputStream baout = new ByteArrayOutputStream(); - try { - // Serialize image - //TODO Eventually, this should be changed not to buffer as this increases the - //memory consumption (see PostScript output) - writeImage(image, baout); - byte[] buf = baout.toByteArray(); - - // Generate image - ImageObject io = afpDataStream.getImageObject(afpx, afpy, afpw, - afph, afpres, afpres); - io.setImageParameters(imageResolution, imageResolution, - image.getWidth(), image.getHeight()); - if (colorImages) { - io.setImageIDESize((byte)24); - io.setImageData(buf); - } else { - // TODO Teach it how to handle grayscale BufferedImages directly - // because this is pretty inefficient - convertToGrayScaleImage(io, buf, - image.getWidth(), image.getHeight(), this.bitsPerPixel); - } - } catch (IOException ioe) { - ResourceEventProducer eventProducer = ResourceEventProducer.Provider.get( - getUserAgent().getEventBroadcaster()); - eventProducer.imageWritingError(this, ioe); - } - } - - /** - * Establishes a new foreground or fill color. - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void updateColor(Color col, boolean fill) { if (fill) { - currentColor = col; + paintingState.setColor(col); } } /** {@inheritDoc} */ - public List breakOutOfStateStack() { - log.debug("Block.FIXED --> break out"); - List breakOutList = new java.util.ArrayList(); - //Don't pop the last ViewPortPos (created by renderPage()) - while (this.viewPortPositions.size() > 1) { - breakOutList.add(0, popViewPortPos()); - } - return breakOutList; + public void restoreStateStackAfterBreakOut(List breakOutList) { + log.debug("Block.FIXED --> restoring context after break-out"); + paintingState.saveAll(breakOutList); } /** {@inheritDoc} */ - public void restoreStateStackAfterBreakOut(List breakOutList) { - log.debug("Block.FIXED --> restoring context after break-out"); - for (int i = 0, c = breakOutList.size(); i < c; i++) { - ViewPortPos vps = (ViewPortPos)breakOutList.get(i); - pushViewPortPos(vps); - } + protected List breakOutOfStateStack() { + log.debug("Block.FIXED --> break out"); + return paintingState.restoreAll(); } - /** Saves the graphics state of the rendering engine. */ + /** {@inheritDoc} */ public void saveGraphicsState() { - + paintingState.save(); } - /** Restores the last graphics state of the rendering engine. */ + /** {@inheritDoc} */ public void restoreGraphicsState() { - + paintingState.restore(); } - /** Indicates the beginning of a text object. */ - public void beginTextObject() { - - } - - /** Indicates the end of a text object. */ - public void endTextObject() { - - } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { - String url = image.getURL(); - drawImage(url, pos); + drawImage(image.getURL(), pos, image.getForeignAttributes()); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderText(TextArea text) { renderInlineAreaBackAndBorders(text); - String name = getInternalFontNameForArea(text); - currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); - AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); + // set font size + int fontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); + paintingState.setFontSize(fontSize); - Color col = (Color) text.getTrait(Trait.COLOR); + // register font as necessary + String internalFontName = getInternalFontNameForArea(text); + Map/*<String,FontMetrics>*/ fontMetricMap = fontInfo.getFonts(); + AFPFont font = (AFPFont)fontMetricMap.get(internalFontName); + AFPPageFonts pageFonts = paintingState.getPageFonts(); + AFPFontAttributes fontAttributes = pageFonts.registerFont(internalFontName, font, fontSize); - int vsci = mpts2units(tf.getWidth(' ', currentFontSize) / 1000 - + text.getTextWordSpaceAdjust() - + text.getTextLetterSpaceAdjust()); + // create text data info + AFPTextDataInfo textDataInfo = new AFPTextDataInfo(); - // word.getOffset() = only height of text itself - // currentBlockIPPosition: 0 for beginning of line; nonzero - // where previous line area failed to take up entire allocated space - int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); - int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); + int fontReference = fontAttributes.getFontReference(); + textDataInfo.setFontReference(fontReference); - // Set letterSpacing - //float ls = fs.getLetterSpacing() / this.currentFontSize; + int x = (currentIPPosition + text.getBorderAndPaddingWidthStart()); + int y = (currentBPPosition + text.getOffset() + text.getBaselineOffset()); - String worddata = text.getText(); + int[] coords = unitConv.mpts2units(new float[] {x, y} ); + textDataInfo.setX(coords[X]); + textDataInfo.setY(coords[Y]); - // Create an AFPFontAttributes object from the current font details - AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, tf, currentFontSize); + Color color = (Color) text.getTrait(Trait.COLOR); + textDataInfo.setColor(color); - if (!currentPageFonts.containsKey(afpFontAttributes.getFontKey())) { - // Font not found on current page, so add the new one - pageFontCounter++; - afpFontAttributes.setFontReference(pageFontCounter); - currentPageFonts.put( - afpFontAttributes.getFontKey(), - afpFontAttributes); + int textWordSpaceAdjust = text.getTextWordSpaceAdjust(); + int textLetterSpaceAdjust = text.getTextLetterSpaceAdjust(); + int textWidth = font.getWidth(' ', fontSize) / 1000; + int variableSpaceCharacterIncrement + = textWidth + textWordSpaceAdjust + textLetterSpaceAdjust; - } else { - // Use the previously stored font attributes - afpFontAttributes = (AFPFontAttributes) currentPageFonts.get( - afpFontAttributes.getFontKey()); - } + variableSpaceCharacterIncrement + = Math.round(unitConv.mpt2units(variableSpaceCharacterIncrement)); + textDataInfo.setVariableSpaceCharacterIncrement(variableSpaceCharacterIncrement); - // Try and get the encoding to use for the font - String encoding = null; + int interCharacterAdjustment + = Math.round(unitConv.mpt2units(textLetterSpaceAdjust)); + textDataInfo.setInterCharacterAdjustment(interCharacterAdjustment); - try { - encoding = tf.getCharacterSet(currentFontSize).getEncoding(); - } catch (Throwable ex) { - encoding = AFPConstants.EBCIDIC_ENCODING; - log.warn( - "renderText():: Error getting encoding for font '" - + tf.getFullName() - + "' - using default encoding " - + encoding); - } + CharacterSet charSet = font.getCharacterSet(fontSize); + String encoding = charSet.getEncoding(); + textDataInfo.setEncoding(encoding); + + String textString = text.getText(); + textDataInfo.setString(textString); try { - afpDataStream.createText( - afpFontAttributes.getFontReference(), - mpts2units(rx), - mpts2units(bl), - col, - vsci, - mpts2units(text.getTextLetterSpaceAdjust()), - worddata.getBytes(encoding)); - } catch (UnsupportedEncodingException usee) { - log.error( - "renderText:: Font " - + afpFontAttributes.getFontKey() - + " caused UnsupportedEncodingException"); + dataStream.createText(textDataInfo); + } catch (UnsupportedEncodingException e) { + AFPEventProducer eventProducer + = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster()); + eventProducer.characterSetEncodingError(this, charSet.getName(), encoding); } + // word.getOffset() = only height of text itself + // currentBlockIPPosition: 0 for beginning of line; nonzero + // where previous line area failed to take up entire allocated space super.renderText(text); - renderTextDecoration(tf, currentFontSize, text, bl, rx); + renderTextDecoration(font, fontSize, text, y, x); } /** - * {@inheritDoc} - */ - public void renderWord(WordArea word) { - // UNUSED - // String name = getInternalFontNameForArea(word.getParentArea()); - // int size = ((Integer) - // word.getParentArea().getTrait(Trait.FONT_SIZE)).intValue(); - // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); - // - // String s = word.getWord(); - // - // FontMetrics metrics = fontInfo.getMetricsFor(name); - - super.renderWord(word); - } - - /** - * {@inheritDoc} - */ - public void renderSpace(SpaceArea space) { - // UNUSED - // String name = getInternalFontNameForArea(space.getParentArea()); - // int size = ((Integer) - // space.getParentArea().getTrait(Trait.FONT_SIZE)).intValue(); - // AFPFont tf = (AFPFont) fontInfo.getFonts().get(name); - // - // String s = space.getSpace(); - // - // FontMetrics metrics = fontInfo.getMetricsFor(name); - - super.renderSpace(space); - } - - /** - * Render leader area. - * This renders a leader area which is an area with a rule. - * @param area the leader area to render + * Render leader area. This renders a leader area which is an area with a + * rule. + * + * @param area + * the leader area to render */ public void renderLeader(Leader area) { renderInlineAreaBackAndBorders(area); int style = area.getRuleStyle(); - float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; + float startx = (currentIPPosition + area + .getBorderAndPaddingWidthStart()) / 1000f; float starty = (currentBPPosition + area.getOffset()) / 1000f; - float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() - + area.getIPD()) / 1000f; + float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() + area + .getIPD()) / 1000f; float ruleThickness = area.getRuleThickness() / 1000f; - Color col = (Color)area.getTrait(Trait.COLOR); + Color col = (Color) area.getTrait(Trait.COLOR); switch (style) { - case EN_SOLID: - case EN_DASHED: - case EN_DOUBLE: - case EN_DOTTED: - case EN_GROOVE: - case EN_RIDGE: - drawBorderLine(startx, starty, endx, starty + ruleThickness, - true, true, style, col); - break; - default: - throw new UnsupportedOperationException("rule style not supported"); + case EN_SOLID: + case EN_DASHED: + case EN_DOUBLE: + case EN_DOTTED: + case EN_GROOVE: + case EN_RIDGE: + drawBorderLine(startx, starty, endx, starty + ruleThickness, true, + true, style, col); + break; + default: + throw new UnsupportedOperationException("rule style not supported"); } super.renderLeader(area); } /** - * Sets the AFPRenderer options - * @param options the <code>Map</code> containing the options - */ -// UNUSED -// public void setOptions(Map options) { -// -// this.afpOptions = options; -// -// } - /** - * Determines the orientation from the string representation, this method - * guarantees to return a value of either 0, 90, 180 or 270. - * - * @return the orientation - */ -// UNUSED -// private int getOrientation(String orientationString) { -// -// int orientation = 0; -// if (orientationString != null && orientationString.length() > 0) { -// try { -// orientation = Integer.parseInt(orientationString); -// } catch (NumberFormatException nfe) { -// log.error("Cannot use orientation of " + orientation -// + " defaulting to zero."); -// orientation = 0; -// } -// } else { -// orientation = 0; -// } -// switch (orientation) { -// case 0: -// break; -// case 90: -// break; -// case 180: -// break; -// case 270: -// break; -// default: -// log.error("Cannot use orientation of " + orientation -// + " defaulting to zero."); -// orientation = 0; -// break; -// } -// -// return orientation; -// -// } - /** - * Sets the rotation to be used for portrait pages, valid values are 0 - * (default), 90, 180, 270. - * - * @param rotation - * The rotation in degrees. - */ - public void setPortraitRotation(int rotation) { - - if (rotation == 0 - || rotation == 90 - || rotation == 180 - || rotation == 270) { - portraitRotation = rotation; - } else { - throw new IllegalArgumentException("The portrait rotation must be one" - + " of the values 0, 90, 180, 270"); - - } - - } - - /** - * Sets the rotation to be used for landsacpe pages, valid values are 0, 90, - * 180, 270 (default). - * - * @param rotation - * The rotation in degrees. - */ - public void setLandscapeRotation(int rotation) { - - if (rotation == 0 - || rotation == 90 - || rotation == 180 - || rotation == 270) { - landscapeRotation = rotation; - } else { - throw new IllegalArgumentException("The landscape rotation must be one" - + " of the values 0, 90, 180, 270"); - } - - } - - /** * Get the MIME type of the renderer. * - * @return The MIME type of the renderer + * @return The MIME type of the renderer */ public String getMimeType() { return MimeConstants.MIME_AFP; @@ -1540,46 +623,40 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * Method to render the page extension. * <p> * - * @param pageViewport the page object + * @param pageViewport + * the page object */ private void renderPageObjectExtensions(PageViewport pageViewport) { - - pageSegmentsMap = null; + pageSegmentMap.clear(); if (pageViewport.getExtensionAttachments() != null && pageViewport.getExtensionAttachments().size() > 0) { // Extract all AFPPageSetup instances from the attachment list on // the s-p-m - Iterator i = pageViewport.getExtensionAttachments().iterator(); - while (i.hasNext()) { - ExtensionAttachment attachment = (ExtensionAttachment)i.next(); + Iterator it = pageViewport.getExtensionAttachments().iterator(); + while (it.hasNext()) { + ExtensionAttachment attachment = (ExtensionAttachment) it.next(); if (AFPPageSetup.CATEGORY.equals(attachment.getCategory())) { AFPPageSetup aps = (AFPPageSetup) attachment; String element = aps.getElementName(); if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) { String overlay = aps.getName(); if (overlay != null) { - afpDataStream.createIncludePageOverlay(overlay); + dataStream.createIncludePageOverlay(overlay); } } else if (AFPElementMapping.INCLUDE_PAGE_SEGMENT .equals(element)) { String name = aps.getName(); String source = aps.getValue(); - if (pageSegmentsMap == null) { - pageSegmentsMap = new HashMap(); - } - pageSegmentsMap.put(source, name); + pageSegmentMap.put(source, name); } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT .equals(element)) { String name = aps.getName(); String value = aps.getValue(); - if (pageSegmentsMap == null) { - pageSegmentsMap = new HashMap(); - } - afpDataStream.createTagLogicalElement(name, value); + dataStream.createTagLogicalElement(name, value); } else if (AFPElementMapping.NO_OPERATION.equals(element)) { String content = aps.getContent(); if (content != null) { - afpDataStream.createNoOperation(content); + dataStream.createNoOperation(content); } } } @@ -1589,206 +666,25 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { } /** - * Converts FOP mpt measurement to afp measurement units - * @param mpt the millipoints value - */ - private int mpts2units(int mpt) { - return mpts2units((double) mpt); - } - - /** - * Converts FOP pt measurement to afp measurement units - * @param mpt the millipoints value - */ - private int pts2units(float mpt) { - return mpts2units(mpt * 1000d); - } - - /** - * Converts FOP mpt measurement to afp measurement units + * Sets the rotation to be used for portrait pages, valid values are 0 + * (default), 90, 180, 270. * - * @param mpt - * the millipoints value - * @return afp measurement unit value + * @param rotation + * The rotation in degrees. */ - private int mpts2units(double mpt) { - return (int)Math.round(mpt / (DPI_CONVERSION_FACTOR / getResolution())); + public void setPortraitRotation(int rotation) { + paintingState.setPortraitRotation(rotation); } /** - * Converts a byte array containing 24 bit RGB image data to a grayscale - * image. + * Sets the rotation to be used for landsacpe pages, valid values are 0, 90, + * 180, 270 (default). * - * @param io - * the target image object - * @param raw - * the buffer containing the RGB image data - * @param width - * the width of the image in pixels - * @param height - * the height of the image in pixels - * @param bitsPerPixel - * the number of bits to use per pixel + * @param rotation + * The rotation in degrees. */ - protected static void convertToGrayScaleImage(ImageObject io, byte[] raw, int width, - int height, int bitsPerPixel) { - int pixelsPerByte = 8 / bitsPerPixel; - int bytewidth = (width / pixelsPerByte); - if ((width % pixelsPerByte) != 0) { - bytewidth++; - } - byte[] bw = new byte[height * bytewidth]; - byte ib; - for (int y = 0; y < height; y++) { - ib = 0; - int i = 3 * y * width; - for (int x = 0; x < width; x++, i += 3) { - - // see http://www.jguru.com/faq/view.jsp?EID=221919 - double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d - * ((int) raw[i + 1] & 0xff) + 0.072169d - * ((int) raw[i + 2] & 0xff); - switch (bitsPerPixel) { - case 1: - if (greyVal < 128) { - ib |= (byte) (1 << (7 - (x % 8))); - } - break; - case 4: - greyVal /= 16; - ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4)); - break; - case 8: - ib = (byte) greyVal; - break; - default: - throw new UnsupportedOperationException( - "Unsupported bits per pixel: " + bitsPerPixel); - } - - if ((x % pixelsPerByte) == (pixelsPerByte - 1) - || ((x + 1) == width)) { - bw[(y * bytewidth) + (x / pixelsPerByte)] = ib; - ib = 0; - } - } - } - io.setImageIDESize((byte) bitsPerPixel); - io.setImageData(bw); - } - - private final class ViewPortPos { - private int x = 0; - - private int y = 0; - - private int rot = 0; - - private ViewPortPos() { - } - - private ViewPortPos(Rectangle2D view, CTM ctm) { - ViewPortPos currentVP = (ViewPortPos) viewPortPositions - .get(viewPortPositions.size() - 1); - int xOrigin; - int yOrigin; - int width; - int height; - switch (currentVP.rot) { - case 90: - width = mpts2units(view.getHeight()); - height = mpts2units(view.getWidth()); - xOrigin = pageWidth - width - mpts2units(view.getY()) - - currentVP.y; - yOrigin = mpts2units(view.getX()) + currentVP.x; - break; - case 180: - width = mpts2units(view.getWidth()); - height = mpts2units(view.getHeight()); - xOrigin = pageWidth - width - mpts2units(view.getX()) - - currentVP.x; - yOrigin = pageHeight - height - mpts2units(view.getY()) - - currentVP.y; - break; - case 270: - width = mpts2units(view.getHeight()); - height = mpts2units(view.getWidth()); - xOrigin = mpts2units(view.getY()) + currentVP.y; - yOrigin = pageHeight - height - mpts2units(view.getX()) - - currentVP.x; - break; - default: - xOrigin = mpts2units(view.getX()) + currentVP.x; - yOrigin = mpts2units(view.getY()) + currentVP.y; - width = mpts2units(view.getWidth()); - height = mpts2units(view.getHeight()); - break; - } - this.rot = currentVP.rot; - double[] ctmf = ctm.toArray(); - if (ctmf[0] == 0.0d && ctmf[1] == -1.0d && ctmf[2] == 1.0d - && ctmf[3] == 0.d) { - this.rot += 270; - } else if (ctmf[0] == -1.0d && ctmf[1] == 0.0d && ctmf[2] == 0.0d - && ctmf[3] == -1.0d) { - this.rot += 180; - } else if (ctmf[0] == 0.0d && ctmf[1] == 1.0d && ctmf[2] == -1.0d - && ctmf[3] == 0.0d) { - this.rot += 90; - } - this.rot %= 360; - switch (this.rot) { - /* - * case 0: this.x = mpts2units(view.getX()) + x; this.y = - * mpts2units(view.getY()) + y; break; case 90: this.x = - * mpts2units(view.getY()) + y; this.y = _pageWidth - - * mpts2units(view.getX() + view.getWidth()) - x; break; case 180: - * this.x = _pageWidth - mpts2units(view.getX() + view.getWidth()) - - * x; this.y = _pageHeight - mpts2units(view.getY() + - * view.getHeight()) - y; break; case 270: this.x = _pageHeight - - * mpts2units(view.getY() + view.getHeight()) - y; this.y = - * mpts2units(view.getX()) + x; break; - */ - case 0: - this.x = xOrigin; - this.y = yOrigin; - break; - case 90: - this.x = yOrigin; - this.y = pageWidth - width - xOrigin; - break; - case 180: - this.x = pageWidth - width - xOrigin; - this.y = pageHeight - height - yOrigin; - break; - case 270: - this.x = pageHeight - height - yOrigin; - this.y = xOrigin; - break; - default: - } - } - - public String toString() { - return "x:" + x + " y:" + y + " rot:" + rot; - } - - } - - private List viewPortPositions = new ArrayList(); - - private void pushViewPortPos(ViewPortPos vpp) { - viewPortPositions.add(vpp); - afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); - } - - private ViewPortPos popViewPortPos() { - ViewPortPos current = (ViewPortPos)viewPortPositions.remove(viewPortPositions.size() - 1); - if (viewPortPositions.size() > 0) { - ViewPortPos vpp = (ViewPortPos)viewPortPositions.get(viewPortPositions.size() - 1); - afpDataStream.setOffsets(vpp.x, vpp.y, vpp.rot); - } - return current; + public void setLandscapeRotation(int rotation) { + paintingState.setLandscapeRotation(rotation); } /** @@ -1798,17 +694,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * number of bits per pixel */ public void setBitsPerPixel(int bitsPerPixel) { - this.bitsPerPixel = bitsPerPixel; - switch (bitsPerPixel) { - case 1: - case 4: - case 8: - break; - default: - log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8."); - bitsPerPixel = 8; - break; - } + paintingState.setBitsPerPixel(bitsPerPixel); } /** @@ -1818,7 +704,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * color image output */ public void setColorImages(boolean colorImages) { - this.colorImages = colorImages; + paintingState.setColorImages(colorImages); + } + + /** + * Sets whether images are supported natively or not + * + * @param nativeImages + * native image support + */ + public void setNativeImagesSupported(boolean nativeImages) { + paintingState.setNativeImagesSupported(nativeImages); } /** @@ -1828,17 +724,73 @@ public class AFPRenderer extends AbstractPathOrientedRenderer { * the output resolution (dpi) */ public void setResolution(int resolution) { - if (log.isDebugEnabled()) { - log.debug("renderer-resolution set to: " + resolution + "dpi"); - } - this.resolution = resolution; + paintingState.setResolution(resolution); } /** * Returns the output/device resolution. + * * @return the resolution in dpi */ public int getResolution() { - return this.resolution; + return paintingState.getResolution(); + } + + /** + * Sets the default resource group file path + * @param filePath the default resource group file path + */ + public void setDefaultResourceGroupFilePath(String filePath) { + resourceManager.setDefaultResourceGroupFilePath(filePath); + } + + /** {@inheritDoc} */ + protected void establishTransformationMatrix(AffineTransform at) { + saveGraphicsState(); + concatenateTransformationMatrix(at); } + + /** {@inheritDoc} */ + public void clip() { + // TODO +// log.debug("NYI clip()"); + } + + /** {@inheritDoc} */ + public void clipRect(float x, float y, float width, float height) { + // TODO +// log.debug("NYI clipRect(x=" + x + ",y=" + y +// + ",width=" + width + ", height=" + height + ")"); + } + + /** {@inheritDoc} */ + public void moveTo(float x, float y) { + // TODO +// log.debug("NYI moveTo(x=" + x + ",y=" + y + ")"); + } + + /** {@inheritDoc} */ + public void lineTo(float x, float y) { + // TODO +// log.debug("NYI lineTo(x=" + x + ",y=" + y + ")"); + } + + /** {@inheritDoc} */ + public void closePath() { + // TODO +// log.debug("NYI closePath()"); + } + + /** Indicates the beginning of a text object. */ + public void beginTextObject() { + //TODO PDF specific maybe? +// log.debug("NYI beginTextObject()"); + } + + /** Indicates the end of a text object. */ + public void endTextObject() { + //TODO PDF specific maybe? +// log.debug("NYI endTextObject()"); + } + } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java index 65e39daad..532d45967 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java @@ -19,10 +19,16 @@ package org.apache.fop.render.afp; +import java.io.File; import java.util.List; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.fop.afp.fonts.AFPFontInfo; +import org.apache.fop.afp.fonts.CharacterSet; +import org.apache.fop.afp.fonts.FopCharacterSet; +import org.apache.fop.afp.fonts.OutlineFont; +import org.apache.fop.afp.fonts.RasterFont; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.fonts.FontTriplet; @@ -30,11 +36,6 @@ import org.apache.fop.fonts.FontUtil; import org.apache.fop.fonts.Typeface; import org.apache.fop.render.PrintRendererConfigurator; import org.apache.fop.render.Renderer; -import org.apache.fop.render.afp.fonts.AFPFontInfo; -import org.apache.fop.render.afp.fonts.CharacterSet; -import org.apache.fop.render.afp.fonts.FopCharacterSet; -import org.apache.fop.render.afp.fonts.OutlineFont; -import org.apache.fop.render.afp.fonts.RasterFont; import org.apache.fop.util.LogUtil; /** @@ -44,6 +45,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { /** * Default constructor + * * @param userAgent user agent */ public AFPRendererConfigurator(FOUserAgent userAgent) { @@ -54,16 +56,17 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { throws ConfigurationException { Configuration[] triple = fontCfg.getChildren("font-triplet"); - List tripleList = new java.util.ArrayList(); + List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/(); if (triple.length == 0) { log.error("Mandatory font configuration element '<font-triplet...' is missing"); return null; } for (int j = 0; j < triple.length; j++) { int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight")); - tripleList.add(new FontTriplet(triple[j].getAttribute("name"), - triple[j].getAttribute("style"), - weight)); + FontTriplet triplet = new FontTriplet(triple[j].getAttribute("name"), + triple[j].getAttribute("style"), + weight); + tripletList.add(triplet); } //build the fonts @@ -137,21 +140,17 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { codepage, encoding, characterset, path)); } } - return new AFPFontInfo(font, tripleList); + return new AFPFontInfo(font, tripletList); } else if ("outline".equalsIgnoreCase(type)) { - String characterset = afpFontCfg.getAttribute("characterset"); if (characterset == null) { log.error("Mandatory afp-font configuration attribute 'characterset=' is missing"); return null; } String name = afpFontCfg.getAttribute("name", characterset); - CharacterSet characterSet = null; - String base14 = afpFontCfg.getAttribute("base14-font", null); - if (base14 != null) { try { Class clazz = Class.forName("org.apache.fop.fonts.base14." @@ -175,7 +174,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { } // Create a new font object OutlineFont font = new OutlineFont(name, characterSet); - return new AFPFontInfo(font, tripleList); + return new AFPFontInfo(font, tripletList); } else { log.error("No or incorrect type attribute"); } @@ -184,36 +183,45 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { /** * Builds a list of AFPFontInfo objects for use with the setup() method. + * * @param cfg Configuration object * @return List the newly created list of fonts * @throws ConfigurationException if something's wrong with the config data */ - private List buildFontListFromConfiguration(Configuration cfg) + private List/*<AFPFontInfo>*/ buildFontListFromConfiguration(Configuration cfg) throws ConfigurationException { - List fontList = new java.util.ArrayList(); + List/*<AFPFontInfo>*/ fontList = new java.util.ArrayList(); Configuration[] font = cfg.getChild("fonts").getChildren("font"); + final String fontPath = null; for (int i = 0; i < font.length; i++) { - AFPFontInfo afi = buildFont(font[i], null); + AFPFontInfo afi = buildFont(font[i], fontPath); if (afi != null) { if (log.isDebugEnabled()) { log.debug("Adding font " + afi.getAFPFont().getFontName()); - for (int j = 0; j < afi.getFontTriplets().size(); ++j) { - FontTriplet triplet = (FontTriplet) afi.getFontTriplets().get(j); + List/*<FontTriplet>*/ fontTriplets = afi.getFontTriplets(); + for (int j = 0; j < fontTriplets.size(); ++j) { + FontTriplet triplet = (FontTriplet) fontTriplets.get(j); log.debug(" Font triplet " + triplet.getName() + ", " + triplet.getStyle() + ", " + triplet.getWeight()); } } - fontList.add(afi); } } return fontList; } + /** images are converted to grayscale bitmapped IOCA */ + private static final String IMAGES_MODE_GRAYSCALE = "b+w"; + + /** images are converted to color bitmapped IOCA */ + private static final String IMAGES_MODE_COLOR = "color"; + /** * Configure the AFP renderer. + * * @param renderer AFP renderer * @throws FOPException fop exception * @see org.apache.fop.render.PrintRendererConfigurator#configure(Renderer) @@ -223,24 +231,56 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator { if (cfg != null) { AFPRenderer afpRenderer = (AFPRenderer)renderer; try { - List fontList = buildFontListFromConfiguration(cfg); + List/*<AFPFontInfo>*/ fontList = buildFontListFromConfiguration(cfg); afpRenderer.setFontList(fontList); } catch (ConfigurationException e) { LogUtil.handleException(log, e, userAgent.getFactory().validateUserConfigStrictly()); } + // image information Configuration imagesCfg = cfg.getChild("images"); - if (!"color".equalsIgnoreCase(imagesCfg.getAttribute("mode", "b+w"))) { - afpRenderer.setBitsPerPixel(imagesCfg.getAttributeAsInteger("bits-per-pixel", 8)); - } else { + + // default to grayscale images + String imagesMode = imagesCfg.getAttribute("mode", IMAGES_MODE_GRAYSCALE); + if (IMAGES_MODE_COLOR.equals(imagesMode)) { afpRenderer.setColorImages(true); + } else { + afpRenderer.setColorImages(false); + // default to 8 bits per pixel + int bitsPerPixel = imagesCfg.getAttributeAsInteger("bits-per-pixel", 8); + afpRenderer.setBitsPerPixel(bitsPerPixel); } + // native image support + boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false); + afpRenderer.setNativeImagesSupported(nativeImageSupport); + + // renderer resolution Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false); if (rendererResolutionCfg != null) { afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240)); } + + // a default external resource group file setting + Configuration resourceGroupFileCfg + = cfg.getChild("resource-group-file", false); + if (resourceGroupFileCfg != null) { + String resourceGroupDest = null; + try { + resourceGroupDest = resourceGroupFileCfg.getValue(); + } catch (ConfigurationException e) { + LogUtil.handleException(log, e, + userAgent.getFactory().validateUserConfigStrictly()); + } + File resourceGroupFile = new File(resourceGroupDest); + if (resourceGroupFile.canWrite()) { + afpRenderer.setDefaultResourceGroupFilePath(resourceGroupDest); + } else { + log.warn("Unable to write to default external resource group file '" + + resourceGroupDest + "'"); + } + } } } } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererContext.java b/src/java/org/apache/fop/render/afp/AFPRendererContext.java new file mode 100644 index 000000000..8d544a7c4 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPRendererContext.java @@ -0,0 +1,83 @@ +/* + * 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.render.afp; + +import java.util.Map; + +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceLevel; +import org.apache.fop.afp.AFPResourceManager; +import org.apache.fop.render.AbstractRenderer; +import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContextConstants; + +public class AFPRendererContext extends RendererContext { + + /** + * Main constructor + * + * @param renderer the current renderer + * @param mime the MIME type of the output that's generated. + */ + public AFPRendererContext(AbstractRenderer renderer, String mime) { + super(renderer, mime); + } + + /** + * Returns a new AFPInfo for this renderer context + * + * @return an AFPInfo for this renderer context + */ + public AFPInfo getInfo() { + AFPInfo info = new AFPInfo(); + info.setWidth(((Integer)getProperty(RendererContextConstants.WIDTH)).intValue()); + info.setHeight(((Integer)getProperty(RendererContextConstants.HEIGHT)).intValue()); + info.setX(((Integer)getProperty(RendererContextConstants.XPOS)).intValue()); + info.setY(((Integer)getProperty(RendererContextConstants.YPOS)).intValue()); + info.setHandlerConfiguration((Configuration)getProperty( + RendererContextConstants.HANDLER_CONFIGURATION)); + info.setFontInfo((org.apache.fop.fonts.FontInfo)getProperty( + AFPRendererContextConstants.AFP_FONT_INFO)); + info.setPaintingState((AFPPaintingState)getProperty( + AFPRendererContextConstants.AFP_PAINTING_STATE)); + info.setResourceManager(((AFPResourceManager)getProperty( + AFPRendererContextConstants.AFP_RESOURCE_MANAGER))); + + Map foreignAttributes = (Map)getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); + if (foreignAttributes != null) { + String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE); + boolean paintAsBitmap = BITMAP.equalsIgnoreCase(conversionMode); + info.setPaintAsBitmap(paintAsBitmap); + + AFPForeignAttributeReader foreignAttributeReader + = new AFPForeignAttributeReader(); + AFPResourceInfo resourceInfo + = foreignAttributeReader.getResourceInfo(foreignAttributes); + // default to inline level if painted as GOCA + if (!resourceInfo.levelChanged() && !paintAsBitmap) { + resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE)); + } + info.setResourceInfo(resourceInfo); + } + return info; + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java b/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java index 428e5b1ca..3302b7f3c 100644 --- a/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java +++ b/src/java/org/apache/fop/render/afp/AFPRendererContextConstants.java @@ -32,4 +32,12 @@ public interface AFPRendererContextConstants extends RendererContextConstants { */ String AFP_GRAYSCALE = "afpGrayscale"; + /** The font information for the AFP renderer. */ + String AFP_FONT_INFO = "afpFontInfo"; + + /** The afp resource manager */ + String AFP_RESOURCE_MANAGER = "afpResourceManager"; + + /** The afp painting state */ + String AFP_PAINTING_STATE = "afpPaintingState"; } diff --git a/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java new file mode 100644 index 000000000..2687d9071 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java @@ -0,0 +1,162 @@ +/* + * 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.render.afp; + +import java.awt.Point; +import java.awt.geom.Rectangle2D; +import java.util.Map; + +import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageInfo; + +/** + * The AFP image information + */ +public class AFPRendererImageInfo { + + /** the image uri */ + protected final String uri; + + /** the current pos */ + protected final Rectangle2D pos; + + /** the origin */ + protected final Point origin; + + /** the foreign attributes */ + protected final Map foreignAttributes; + + /** the image info */ + protected final ImageInfo info; + + /** the image */ + protected final Image img; + + /** the renderer context */ + protected RendererContext rendererContext; + + /** + * Main constructor + * + * @param uri the image uri + * @param pos the image content area + * @param origin the current position + * @param info the image info + * @param img the image + * @param rendererContext the renderer context + * @param foreignAttributes the foreign attributes + */ + public AFPRendererImageInfo(String uri, Rectangle2D pos, Point origin, + ImageInfo info, Image img, RendererContext rendererContext, Map foreignAttributes) { + this.uri = uri; + this.pos = pos; + this.origin = origin; + this.info = info; + this.img = img; + this.rendererContext = rendererContext; + this.foreignAttributes = foreignAttributes; + } + + /** + * Sets the renderer context + * + * @param rendererContext the renderer context + */ + public void setRendererContext(RendererContext rendererContext) { + this.rendererContext = rendererContext; + } + + /** + * Returns the image info + * + * @return the image info + */ + public ImageInfo getImageInfo() { + return this.info; + } + + /** + * Returns the image + * + * @return the image + */ + public Image getImage() { + return this.img; + } + + /** + * Returns the renderer context + * + * @return the renderer context + */ + public RendererContext getRendererContext() { + return this.rendererContext; + } + + /** + * Return the foreign attributes + * @return the foreign attributes + */ + public Map getForeignAttributes() { + return this.foreignAttributes; + } + + /** + * Return the uri + * + * @return the uri + */ + public String getURI() { + return this.uri; + } + + /** + * Return the origin + * + * @return the origin + */ + public Point getOrigin() { + return this.origin; + } + + /** + * Return the position + * + * @return the position + */ + public Rectangle2D getPosition() { + return this.pos; + } + + /** {@inheritDoc} */ + public String toString() { + return "AFPRendererImageInfo{\n" + + "\turi=" + uri + ",\n" + + "\tinfo=" + info + ",\n" + + "\tpos=" + pos + ",\n" + + "\torigin=" + origin + ",\n" + + "\timg=" + img + ",\n" + + "\tforeignAttributes=" + foreignAttributes + ",\n" + + "\trendererContext=" + rendererContext + "\n" + + "}"; + + } +} diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java index 5f077fdc6..9deea77b4 100644 --- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java @@ -20,9 +20,35 @@ package org.apache.fop.render.afp; // FOP +import java.awt.Dimension; +import java.awt.geom.AffineTransform; +import java.io.IOException; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.gvt.GraphicsNode; +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.afp.AFPGraphicsObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceManager; +import org.apache.fop.afp.AFPUnitConverter; +import org.apache.fop.afp.svg.AFPBridgeContext; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContext.RendererContextWrapper; +import org.apache.fop.svg.SVGEventProducer; +import org.apache.fop.svg.SVGUserAgent; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.apache.xmlgraphics.util.MimeConstants; +import org.w3c.dom.Document; /** * AFP XML handler for SVG. Uses Apache Batik for SVG processing. @@ -31,6 +57,147 @@ import org.apache.fop.render.RendererContext; */ public class AFPSVGHandler extends AbstractGenericSVGHandler { + private boolean paintAsBitmap = false; + + /** {@inheritDoc} */ + public void handleXML(RendererContext context, + Document doc, String ns) throws Exception { + if (SVGDOMImplementation.SVG_NAMESPACE_URI.equals(ns)) { + renderSVGDocument(context, doc); + } + } + + /** + * Render the SVG document. + * + * @param rendererContext the renderer context + * @param doc the SVG document + * @throws IOException In case of an I/O error while painting the image + */ + protected void renderSVGDocument(final RendererContext rendererContext, + final Document doc) throws IOException { + + AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext; + AFPInfo afpInfo = afpRendererContext.getInfo(); + + this.paintAsBitmap = afpInfo.paintAsBitmap(); + + FOUserAgent userAgent = rendererContext.getUserAgent(); + + // fallback paint as bitmap + String uri = getDocumentURI(doc); + if (paintAsBitmap) { + try { + super.renderSVGDocument(rendererContext, doc); + } catch (IOException ioe) { + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + userAgent.getEventBroadcaster()); + eventProducer.svgRenderingError(this, ioe, uri); + } + return; + } + + // Create a new AFPGraphics2D + final boolean textAsShapes = afpInfo.strokeText(); + AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes); + + AFPPaintingState paintingState = g2d.getPaintingState(); + paintingState.setImageUri(uri); + + // Create an AFPBridgeContext + BridgeContext bridgeContext = createBridgeContext(userAgent, g2d); + + // Build the SVG DOM and provide the painter with it + GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc); + + // Create Graphics2DImagePainter + final RendererContextWrapper wrappedContext + = RendererContext.wrapRendererContext(rendererContext); + Dimension imageSize = getImageSize(wrappedContext); + Graphics2DImagePainter painter + = createGrapics2DImagePainter(bridgeContext, root, imageSize); + + // Create AFPObjectAreaInfo + RendererContextWrapper rctx = RendererContext.wrapRendererContext(rendererContext); + int x = rctx.getCurrentXPosition(); + int y = rctx.getCurrentYPosition(); + int width = afpInfo.getWidth(); + int height = afpInfo.getHeight(); + int resolution = afpInfo.getResolution(); + + paintingState.save(); // save + + AFPObjectAreaInfo objectAreaInfo + = createObjectAreaInfo(paintingState, x, y, width, height, resolution); + + // Create AFPGraphicsObjectInfo + AFPResourceInfo resourceInfo = afpInfo.getResourceInfo(); + AFPGraphicsObjectInfo graphicsObjectInfo = createGraphicsObjectInfo( + paintingState, painter, userAgent, resourceInfo, g2d); + graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo); + + // Create the GOCA GraphicsObject in the DataStream + AFPResourceManager resourceManager = afpInfo.getResourceManager(); + resourceManager.createObject(graphicsObjectInfo); + + paintingState.restore(); // resume + } + + private AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState, + int x, int y, int width, int height, int resolution) { + // set the data object parameters + AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); + + AffineTransform at = paintingState.getData().getTransform(); + at.translate(x, y); + objectAreaInfo.setX((int)Math.round(at.getTranslateX())); + objectAreaInfo.setY((int)Math.round(at.getTranslateY())); + + objectAreaInfo.setWidthRes(resolution); + objectAreaInfo.setHeightRes(resolution); + + AFPUnitConverter unitConv = paintingState.getUnitConverter(); + objectAreaInfo.setWidth(Math.round(unitConv.mpt2units(width))); + objectAreaInfo.setHeight(Math.round(unitConv.mpt2units(height))); + + int rotation = paintingState.getRotation(); + objectAreaInfo.setRotation(rotation); + + return objectAreaInfo; + } + + private AFPGraphicsObjectInfo createGraphicsObjectInfo(AFPPaintingState paintingState, Graphics2DImagePainter painter, + FOUserAgent userAgent, AFPResourceInfo resourceInfo, AFPGraphics2D g2d) { + AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo(); + + String uri = paintingState.getImageUri(); + graphicsObjectInfo.setUri(uri); + + graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA); + + graphicsObjectInfo.setResourceInfo(resourceInfo); + + graphicsObjectInfo.setPainter(painter); + + // Set the afp graphics 2d implementation + graphicsObjectInfo.setGraphics2D(g2d); + + return graphicsObjectInfo; + } + + public static BridgeContext createBridgeContext(FOUserAgent userAgent, AFPGraphics2D g2d) { + ImageManager imageManager = userAgent.getFactory().getImageManager(); + + SVGUserAgent svgUserAgent + = new SVGUserAgent(userAgent, new AffineTransform()); + + ImageSessionContext imageSessionContext = userAgent.getImageSessionContext(); + + FontInfo fontInfo = g2d.getFontInfo(); + return new AFPBridgeContext(svgUserAgent, fontInfo, imageManager, imageSessionContext, + new AffineTransform(), g2d); + } + /** {@inheritDoc} */ public boolean supportsRenderer(Renderer renderer) { return (renderer instanceof AFPRenderer); @@ -39,9 +206,29 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler { /** {@inheritDoc} */ protected void updateRendererContext(RendererContext context) { //Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY - context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, - Boolean.FALSE); + context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean.FALSE); } -} + /** {@inheritDoc} */ + protected Graphics2DImagePainter createGrapics2DImagePainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) { + Graphics2DImagePainter painter = null; + if (paintAsBitmap()) { + // paint as IOCA Image + painter = super.createGraphics2DImagePainter(root, ctx, imageSize); + } else { + // paint as GOCA Graphics + painter = new Graphics2DImagePainterImpl(root, ctx, imageSize); + } + return painter; + } + /** + * Returns true if the SVG is to be painted as a bitmap + * + * @return true if the SVG is to be painted as a bitmap + */ + private boolean paintAsBitmap() { + return paintAsBitmap; + } + +} diff --git a/src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java b/src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java new file mode 100644 index 000000000..ae8ac9950 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/AbstractAFPImageHandlerRawStream.java @@ -0,0 +1,79 @@ +/* + * 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.render.afp; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.fop.afp.AFPDataObjectInfo; +import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPPaintingState; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawStream; + +/** + * A base abstract AFP raw stream image handler + */ +public abstract class AbstractAFPImageHandlerRawStream extends AFPImageHandler { + + /** {@inheritDoc} */ + public AFPDataObjectInfo generateDataObjectInfo( + AFPRendererImageInfo rendererImageInfo) throws IOException { + AFPDataObjectInfo dataObjectInfo = super.generateDataObjectInfo(rendererImageInfo); + + ImageInfo imageInfo = rendererImageInfo.getImageInfo(); + String mimeType = imageInfo.getMimeType(); + if (mimeType != null) { + dataObjectInfo.setMimeType(mimeType); + } + ImageRawStream rawStream = (ImageRawStream) rendererImageInfo.getImage(); + InputStream inputStream = rawStream.createInputStream(); + try { + dataObjectInfo.setData(IOUtils.toByteArray(inputStream)); + } finally { + IOUtils.closeQuietly(inputStream); + } + + int dataHeight = rawStream.getSize().getHeightPx(); + dataObjectInfo.setDataHeight(dataHeight); + + int dataWidth = rawStream.getSize().getWidthPx(); + dataObjectInfo.setDataWidth(dataWidth); + + ImageSize imageSize = rawStream.getSize(); + dataObjectInfo.setDataHeightRes((int) (imageSize.getDpiHorizontal() * 10)); + dataObjectInfo.setDataWidthRes((int) (imageSize.getDpiVertical() * 10)); + + // set object area info + AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo(); + AFPRendererContext rendererContext + = (AFPRendererContext)rendererImageInfo.getRendererContext(); + AFPInfo afpInfo = rendererContext.getInfo(); + AFPPaintingState paintingState = afpInfo.getPaintingState(); + int resolution = paintingState.getResolution(); + objectAreaInfo.setWidthRes(resolution); + objectAreaInfo.setHeightRes(resolution); + + return dataObjectInfo; + } + +} diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java index 665a77562..6b4bc4eb9 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPAttribute.java @@ -19,14 +19,13 @@ package org.apache.fop.render.afp.extensions; -import org.apache.fop.apps.FOPException; import org.apache.fop.fo.PropertyList; import org.apache.fop.fo.properties.Property; import org.apache.fop.fo.properties.StringProperty; /** * This class extends the org.apache.fop.fo.StringProperty.Maker inner class - * in order to provide a static property maker. The object faciliates + * in order to provide a static property maker. The object facilitates * extraction of attributes from formatted objects based on the static list * as defined in the AFPElementMapping implementation. * <p/> @@ -58,5 +57,4 @@ public class AFPAttribute extends StringProperty.Maker { } return property; } - }
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java index b8bfa74b6..2fdd32649 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java @@ -23,6 +23,7 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; /** * This class extends the org.apache.fop.extensions.ExtensionObj class. The @@ -45,13 +46,13 @@ public class AFPElement extends AbstractAFPExtensionObject { /** {@inheritDoc} */ protected void startOfNode() throws FOPException { super.startOfNode(); - //if (!AFPElementMapping.NAMESPACE.equals(parent.getNamespaceURI()) - // || !AFPElementMapping.PAGE.equals(parent.getLocalName())) { - // throw new ValidationException(getName() + " must be a child of afp:page."); - //} if (parent.getNameId() != Constants.FO_SIMPLE_PAGE_MASTER) { throw new ValidationException(getName() + " must be a child of fo:simple-page-master."); } } + /** {@inheritDoc} */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(getName()); + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java index 216379cc0..c3ba2c43b 100755 --- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java @@ -19,8 +19,6 @@ package org.apache.fop.render.afp.extensions; -import java.util.HashMap; - import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.FONode; @@ -39,7 +37,7 @@ public class AFPElementMapping extends ElementMapping { public static final String PAGE = "page"; /** page group element */ - public static final String PAGE_GROUP = "page-group"; +// public static final String PAGE_GROUP = "page-group"; /** tag logical element */ public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element"; @@ -53,6 +51,9 @@ public class AFPElementMapping extends ElementMapping { /** NOP */ public static final String NO_OPERATION = "no-operation"; + /** resource information (name, level, dest) */ +// public static final String RESOURCE_INFO = "resource-info"; + /** * The namespace used for AFP extensions */ @@ -69,15 +70,18 @@ public class AFPElementMapping extends ElementMapping { } /** - * Private static synchronized method to set up the element and atribute + * Private static synchronized method to set up the element and attribute * HashMaps, this defines what elements and attributes are extracted. */ protected void initialize() { if (foObjs == null) { - foObjs = new HashMap(); + super.foObjs = new java.util.HashMap(); foObjs.put(PAGE, new AFPPageSetupMaker()); - // foObjs.put(PAGE_GROUP, new AFPMaker()); +// foObjs.put( +// PAGE_GROUP, +// new AFPPageGroupMaker() +// ); foObjs.put( TAG_LOGICAL_ELEMENT, new AFPTagLogicalElementMaker()); @@ -90,8 +94,10 @@ public class AFPElementMapping extends ElementMapping { foObjs.put( NO_OPERATION, new AFPNoOperationMaker()); +// foObjs.put( +// RESOURCE_INFO, +// new AFPResourceInfoMaker()); } - } static class AFPPageSetupMaker extends ElementMapping.Maker { @@ -123,4 +129,16 @@ public class AFPElementMapping extends ElementMapping { return new AFPElement(parent, NO_OPERATION); } } + +// static class AFPResourceInfoMaker extends ElementMapping.Maker { +// public FONode make(FONode parent) { +// return new AFPResourceInfoElement(parent); +// } +// } + +// static class AFPPageGroupMaker extends ElementMapping.Maker { +// public FONode make(FONode parent) { +// return new AFPElement(parent, PAGE_GROUP); +// } +// } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java new file mode 100644 index 000000000..9a8429b00 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionAttachment.java @@ -0,0 +1,155 @@ +/* + * 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.render.afp.extensions; + +import java.io.Serializable; + +import org.apache.fop.fo.extensions.ExtensionAttachment; +import org.apache.xmlgraphics.util.XMLizable; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * This is the pass-through value object for the AFP extension. + */ +public abstract class AFPExtensionAttachment + implements ExtensionAttachment, Serializable, XMLizable { + private static final long serialVersionUID = 7190606822558332901L; + + /** The category URI for this extension attachment. */ + public static final String CATEGORY = "apache:fop:extensions:afp"; + + /** + * the extension element name + */ + protected String elementName; + + /** + * the extension content + */ + protected String content; + + /** + * the extension name attribute + */ + protected String name; + + /** + * the extension value attribute + */ + protected String value; + + /** + * Default constructor. + * + * @param elementName the name of the afp extension attachment, may be null + */ + public AFPExtensionAttachment(String elementName) { + this.elementName = elementName; + } + + /** @return the name */ + public String getElementName() { + return elementName; + } + + /** + * @return true if this element has a name attribute + */ + protected boolean hasName() { + return name != null; + } + + /** @return the name */ + public String getName() { + return name; + } + + /** + * Sets the name of the setup code object. + * @param name The name to set. + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * Sets the value + * @param source The value name to set. + */ + public void setValue(String source) { + this.value = source; + } + + /** {@inheritDoc} */ + public String getCategory() { + return CATEGORY; + } + + /** + * @return the data + */ + public String getContent() { + return content; + } + + /** + * Sets the data + * @param content The byte data to set. + */ + public void setContent(String content) { + this.content = content; + } + + /** + * name attribute + */ + protected static final String ATT_NAME = "name"; + + /** + * value attribute + */ + protected static final String ATT_VALUE = "value"; + + /** {@inheritDoc} */ + public void toSAX(ContentHandler handler) throws SAXException { + AttributesImpl atts = new AttributesImpl(); + if (name != null && name.length() > 0) { + atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); + } + if (value != null && value.length() > 0) { + atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value); + } + handler.startElement(CATEGORY, elementName, elementName, atts); + if (content != null && content.length() > 0) { + char[] chars = content.toCharArray(); + handler.characters(chars, 0, chars.length); + } + handler.endElement(CATEGORY, elementName, elementName); + } +} diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java index 61ad9c1e7..08989c03c 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java @@ -54,7 +54,7 @@ public class AFPExtensionHandler extends DefaultHandler || localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY) || localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT) || localName.equals(AFPElementMapping.PAGE) - || localName.equals(AFPElementMapping.PAGE_GROUP)) { + /*|| localName.equals(AFPElementMapping.PAGE_GROUP)*/) { //handled in endElement } else { handled = false; diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java index 30bc217e7..998ce6921 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetup.java @@ -19,33 +19,10 @@ package org.apache.fop.render.afp.extensions; -import java.io.Serializable; - -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; - -import org.apache.xmlgraphics.util.XMLizable; - -import org.apache.fop.fo.extensions.ExtensionAttachment; - /** * This is the pass-through value object for the PostScript extension. */ -public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizable { - - private static final long serialVersionUID = 7190606822558332901L; - - /** The category URI for this extension attachment. */ - public static final String CATEGORY = "apache:fop:extensions:afp"; - - private String elementName; - - private String name; - - private String value; - - private String content; +public class AFPPageSetup extends AFPExtensionAttachment { /** * Default constructor. @@ -53,85 +30,16 @@ public class AFPPageSetup implements ExtensionAttachment, Serializable, XMLizabl * @param elementName the name of the setup code object, may be null */ public AFPPageSetup(String elementName) { - this.elementName = elementName; - } - - /** @return the name */ - public String getElementName() { - return elementName; - } - - /** @return the name */ - public String getName() { - return name; - } - - /** - * Sets the name of the setup code object. - * @param name The name to set. - */ - public void setName(String name) { - this.name = name; + super(elementName); } - /** - * @return the value - */ - public String getValue() { - return value; - } - - /** - * Sets the value - * @param source The value name to set. - */ - public void setValue(String source) { - this.value = source; - } - - /** {@inheritDoc} */ - public String getCategory() { - return CATEGORY; - } + private static final long serialVersionUID = -549941295384013190L; /** - * @return the data + * {@inheritDoc} */ - public String getContent() { - return content; - } - - /** - * Sets the data - * @param content The byte data to set. - */ - public void setContent(String content) { - this.content = content; - } - - /** {@inheritDoc} */ public String toString() { return "AFPPageSetup(element-name=" + getElementName() + " name=" + getName() + " value=" + getValue() + ")"; } - - private static final String ATT_NAME = "name"; - private static final String ATT_VALUE = "value"; - - /** {@inheritDoc} */ - public void toSAX(ContentHandler handler) throws SAXException { - AttributesImpl atts = new AttributesImpl(); - if (name != null && name.length() > 0) { - atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name); - } - if (value != null && value.length() > 0) { - atts.addAttribute(null, ATT_VALUE, ATT_VALUE, "CDATA", value); - } - handler.startElement(CATEGORY, elementName, elementName, atts); - if (content != null && content.length() > 0) { - char[] chars = content.toCharArray(); - handler.characters(chars, 0, chars.length); - } - handler.endElement(CATEGORY, elementName, elementName); - } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java index 4971928f8..d167a8d4b 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java +++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java @@ -23,9 +23,10 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.Constants; import org.apache.fop.fo.FONode; import org.apache.fop.fo.ValidationException; +import org.apache.fop.fo.extensions.ExtensionAttachment; /** - * Extension element for fox:ps-page-setup-code. + * Extension element for afp:ps-page-setup-code. */ public class AFPPageSetupElement extends AbstractAFPExtensionObject { @@ -45,4 +46,10 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject { } } + /** + * {@inheritDoc} + */ + protected ExtensionAttachment instantiateExtensionAttachment() { + return new AFPPageSetup(this.name); + } } diff --git a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java index a92687aab..c0e9c2c89 100644 --- a/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java +++ b/src/java/org/apache/fop/render/afp/extensions/AbstractAFPExtensionObject.java @@ -35,11 +35,14 @@ import org.apache.fop.fo.extensions.ExtensionAttachment; public abstract class AbstractAFPExtensionObject extends FONode { /** - * AFP setup code + * the AFP extension attachment */ - private AFPPageSetup setupCode; + protected AFPExtensionAttachment extensionAttachment; - private String name; + /** + * the element name of this extension + */ + protected String name; /** * @see org.apache.fop.fo.FONode#FONode(FONode) @@ -49,10 +52,11 @@ public abstract class AbstractAFPExtensionObject extends FONode { public AbstractAFPExtensionObject(FONode parent, String name) { super(parent); this.name = name; - this.setupCode = new AFPPageSetup(name); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected void validateChildNode(Locator loc, String nsURI, String localName) throws ValidationException { if (FO_URI.equals(nsURI)) { @@ -60,60 +64,85 @@ public abstract class AbstractAFPExtensionObject extends FONode { } } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ protected void characters(char[] data, int start, int length, - PropertyList pList, Locator locator) { - setupCode.setContent(new String(data, start, length)); + PropertyList pList, Locator locator) throws FOPException { + ((AFPExtensionAttachment)getExtensionAttachment()).setContent( + new String(data, start, length)); } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getNamespaceURI() { return AFPElementMapping.NAMESPACE; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getNormalNamespacePrefix() { return AFPElementMapping.NAMESPACE_PREFIX; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public void processNode(String elementName, Locator locator, Attributes attlist, PropertyList propertyList) throws FOPException { - String name = attlist.getValue("name"); - if (name != null && name.length() > 0) { - setupCode.setName(name); + getExtensionAttachment(); + String attr = attlist.getValue("name"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setName(attr); } else { throw new FOPException(elementName + " must have a name attribute."); } if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) { - name = attlist.getValue("src"); - if (name != null && name.length() > 0) { - setupCode.setValue(name); + attr = attlist.getValue("src"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setValue(attr); } else { throw new FOPException(elementName + " must have a src attribute."); } } else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) { - name = attlist.getValue("value"); - if (name != null && name.length() > 0) { - setupCode.setValue(name); + attr = attlist.getValue("value"); + if (attr != null && attr.length() > 0) { + extensionAttachment.setValue(attr); } else { throw new FOPException(elementName + " must have a value attribute."); } } } - - /** {@inheritDoc} */ + + /** + * {@inheritDoc} + */ protected void endOfNode() throws FOPException { super.endOfNode(); } - /** {@inheritDoc} */ + /** + * Instantiates extension attachment object + * @return extension attachment + */ + protected abstract ExtensionAttachment instantiateExtensionAttachment(); + + /** + * {@inheritDoc} + */ public ExtensionAttachment getExtensionAttachment() { - return this.setupCode; + if (extensionAttachment == null) { + this.extensionAttachment = (AFPExtensionAttachment)instantiateExtensionAttachment(); + } + return this.extensionAttachment; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ public String getLocalName() { return name; } diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java deleted file mode 100644 index 03b5580cf..000000000 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFontCollection.java +++ /dev/null @@ -1,110 +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.render.afp.fonts; - -import java.util.Iterator; -import java.util.List; - -import org.apache.fop.events.EventBroadcaster; -import org.apache.fop.fonts.Font; -import org.apache.fop.fonts.FontCollection; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontTriplet; -import org.apache.fop.fonts.base14.Courier; -import org.apache.fop.fonts.base14.Helvetica; -import org.apache.fop.fonts.base14.TimesRoman; -import org.apache.fop.render.afp.AFPEventProducer; - -/** - * A base collection of AFP fonts - */ -public class AFPFontCollection implements FontCollection { - - private EventBroadcaster eventBroadcaster; - private List/*<EmbedFontInfo>*/ embedFontInfoList; - - /** - * Main constructor - * - * @param eventBroadcaster the event broadcaster - * @param embedFontInfoList the embed font info list - */ - public AFPFontCollection(EventBroadcaster eventBroadcaster, - List/*<EmbedFontInfo>*/ embedFontInfoList) { - this.eventBroadcaster = eventBroadcaster; - this.embedFontInfoList = embedFontInfoList; - } - - /** {@inheritDoc} */ - public int setup(int start, FontInfo fontInfo) { - int num = 1; - if (embedFontInfoList != null && embedFontInfoList.size() > 0) { - for (Iterator it = embedFontInfoList.iterator(); it.hasNext();) { - AFPFontInfo afi = (AFPFontInfo)it.next(); - AFPFont bf = (AFPFont)afi.getAFPFont(); - for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { - FontTriplet ft = (FontTriplet)it2.next(); - fontInfo.addFontProperties("F" + num, ft.getName() - , ft.getStyle(), ft.getWeight()); - fontInfo.addMetrics("F" + num, bf); - num++; - } - } - } else { - AFPEventProducer eventProducer = AFPEventProducer.Provider.get(eventBroadcaster); - eventProducer.warnDefaultFontSetup(this); - } - if (fontInfo.fontLookup("sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZH200 ", - 1, new Helvetica()); - AFPFont bf = new OutlineFont("Helvetica", cs); - fontInfo.addFontProperties( - "F" + num, "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - fontInfo.addMetrics("F" + num, bf); - num++; - } - if (fontInfo.fontLookup("serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZN200 ", - 1, new TimesRoman()); - AFPFont bf = new OutlineFont("Helvetica", cs); - fontInfo.addFontProperties("F" + num, "serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - fontInfo.addMetrics("F" + num, bf); - num++; - } - if (fontInfo.fontLookup("monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) { - CharacterSet cs = new FopCharacterSet("T1V10500", "Cp500", "CZ4200 ", - 1, new Courier()); - AFPFont bf = new OutlineFont("Helvetica", cs); - fontInfo.addFontProperties( - "F" + num, "monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - fontInfo.addMetrics("F" + num, bf); - num++; - } - if (fontInfo.fontLookup("any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL) == null) { - FontTriplet ft = fontInfo.fontLookup( - "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - fontInfo.addFontProperties( - fontInfo.getInternalFontKey(ft), "any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL); - num++; - } - return num; - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java b/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java deleted file mode 100644 index 0c60ec1d7..000000000 --- a/src/java/org/apache/fop/render/afp/modca/AFPDataStream.java +++ /dev/null @@ -1,701 +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.render.afp.modca; - -import java.awt.Color; -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.fonts.AFPFont; -import org.apache.fop.render.afp.tools.StringUtils; - -/** - * A data stream is a continuous ordered stream of data elements and objects - * conforming to a given format. Application programs can generate data streams - * destined for a presentation service, archive library, presentation device or - * another application program. The strategic presentation data stream - * architectures used is Mixed Object Document Content Architecture (MO:DCA�). - * - * The MO:DCA architecture defines the data stream used by applications to - * describe documents and object envelopes for interchange with other - * applications and application services. Documents defined in the MO:DCA format - * may be archived in a database, then later retrieved, viewed, annotated and - * printed in local or distributed systems environments. Presentation fidelity - * is accommodated by including resource objects in the documents that reference - * them. - * - */ -public class AFPDataStream { - - /** - * Static logging instance - */ - protected static Log log = LogFactory.getLog("org.apache.fop.render.afp.modca"); - - /** - * Boolean completion indicator - */ - private boolean complete = false; - - /** - * The application producing the AFP document - */ -// not used -// private String producer = null; - - /** - * The AFP document object - */ - private Document document = null; - - /** - * The current page group object - */ - private PageGroup currentPageGroup = null; - - /** - * The current page object - */ - private PageObject currentPageObject = null; - - /** - * The current overlay object - */ - private Overlay currentOverlay = null; - - /** - * The current page - */ - private AbstractPageObject currentPage = null; - - /** - * The page count - */ - private int pageCount = 0; - - /** - * The page group count - */ -// not used -// private int pageGroupCount = 0; - - /** - * The overlay count - */ - private int ovlCount = 0; - - /** - * The portrait rotation - */ - private int portraitRotation = 0; - - /** - * The landscape rotation - */ - private int landscapeRotation = 270; - - /** - * The x offset - */ - private int xOffset = 0; - - /** - * The y offset - */ - private int yOffset = 0; - - /** - * The rotation - */ - private int rotation; - - /** - * The outputstream for the data stream - */ - private OutputStream outputStream = null; - - /** - * Default constructor for the AFPDataStream. - */ - public AFPDataStream() { - } - - /** - * The document is started by invoking this method which creates an instance - * of the AFP Document object. - * - * @param docOutputStream - * the outputStream which the document is written to. - */ - public void startDocument(OutputStream docOutputStream) { - - if (document != null) { - String msg = "Invalid state - document already started."; - log.warn("startDocument():: " + msg); - throw new IllegalStateException(msg); - } - - this.document = new Document(); - this.outputStream = docOutputStream; - - } - - /** - * The document is ended by invoking this method which creates an instance - * of the AFP Document object and registers the start with a validation map - * which ensures that methods are not invoked out of the correct sequence. - * - * @throws java.io.IOException - * throws an I/O exception of some sort has occurred - */ - public void endDocument() throws IOException { - - if (complete) { - String msg = "Invalid state - document already ended."; - log.warn("endDocument():: " + msg); - throw new IllegalStateException(msg); - } - - if (currentPageObject != null) { - // End the current page if necessary - endPage(); - } - - if (currentPageGroup != null) { - // End the current page group if necessary - endPageGroup(); - } - - document.endDocument(); - document.writeDataStream(this.outputStream); - this.outputStream.flush(); - - complete = true; - - document = null; - - this.outputStream = null; - } - - /** - * Start a new page. When processing has finished on the current page, the - * {@link #endPage()}method must be invoked to mark the page ending. - * - * @param pageWidth - * the width of the page - * @param pageHeight - * the height of the page - * @param pageRotation - * the rotation of the page - * @param pageWidthResolution - * the width resolution of the page - * @param pageHeightResolution - * the height resolution of the page - */ - public void startPage(int pageWidth, int pageHeight, int pageRotation, - int pageWidthResolution, int pageHeightResolution) { - - String pageName = "PGN" - + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); - - currentPageObject = new PageObject(pageName, pageWidth, pageHeight, - pageRotation, pageWidthResolution, pageHeightResolution); - currentPage = currentPageObject; - currentOverlay = null; - setOffsets(0, 0, 0); - } - - /** - * Start a new overlay. When processing has finished on the current overlay, - * the {@link #endOverlay()}method must be invoked to mark the overlay - * ending. - * - * @param overlayX - * the x position of the overlay on the page - * @param overlayY - * the y position of the overlay on the page - * @param overlayWidth - * the width of the overlay - * @param overlayHeight - * the height of the overlay - * @param overlayWidthResolution - * the width resolution of the overlay - * @param overlayHeightResolution - * the height resolution of the overlay - * @param overlayRotation - * the rotation of the overlay - */ - public void startOverlay(int overlayX, int overlayY, int overlayWidth, - int overlayHeight, int overlayWidthResolution, - int overlayHeightResolution, int overlayRotation) { - - String overlayName = "OVL" - + StringUtils.lpad(String.valueOf(ovlCount++), '0', 5); - - currentOverlay = new Overlay(overlayName, overlayWidth, overlayHeight, - overlayWidthResolution, overlayHeightResolution, - overlayRotation); - currentPageObject.addOverlay(currentOverlay); - currentPageObject.createIncludePageOverlay(overlayName, overlayX, - overlayY, 0); - currentPage = currentOverlay; - setOffsets(0, 0, 0); - } - - /** - * Helper method to mark the end of the current overlay. - */ - public void endOverlay() { - - currentOverlay.endPage(); - currentOverlay = null; - currentPage = currentPageObject; - - } - - /** - * Helper method to save the current page. - * - * @return current page object that was saved - */ - public PageObject savePage() { - - PageObject pageObject = currentPageObject; - if (currentPageGroup != null) { - currentPageGroup.addPage(currentPageObject); - } else { - document.addPage(currentPageObject); - } - currentPageObject = null; - currentPage = null; - return pageObject; - - } - - /** - * Helper method to restore the current page. - * - * @param pageObject - * page object - */ - public void restorePage(PageObject pageObject) { - - currentPageObject = pageObject; - currentPage = pageObject; - - } - - /** - * Helper method to mark the end of the current page. - * - * @throws java.io.IOException - * thrown when an I/O exception of some sort has occurred - */ - public void endPage() throws IOException { - - currentPageObject.endPage(); - if (currentPageGroup != null) { - currentPageGroup.addPage(currentPageObject); - } else { - document.addPage(currentPageObject); - document.writeDataStream(this.outputStream); - } - - currentPageObject = null; - currentPage = null; - - } - - /** - * Sets the offsets to be used for element positioning - * - * @param xOff - * the offset in the x direction - * @param yOff - * the offset in the y direction - * @param rot - * the rotation - */ - public void setOffsets(int xOff, int yOff, int rot) { - this.xOffset = xOff; - this.yOffset = yOff; - this.rotation = rot; - } - - /** - * Helper method to create a map coded font object on the current page, this - * method delegates the construction of the map coded font object to the - * active environment group on the current page. - * - * @param fontReference - * the font number used as the resource identifier - * @param font - * the font - * @param size - * the point size of the font - */ - public void createFont(byte fontReference, AFPFont font, int size) { - - currentPage.createFont(fontReference, font, size); - - } - - /** - * Helper method to create text on the current page, this method delegates - * to the current presentation text object in order to construct the text. - * - * @param fontNumber - * the font number used as the resource identifier - * @param x - * the x coordinate of the text - * @param y - * the y coordinate of the text - * @param col - * the text color - * @param vsci - * The variable space character increment. - * @param ica - * The inter character adjustment. - * @param data - * the text data to create - */ - public void createText(int fontNumber, int x, int y, Color col, int vsci, - int ica, byte[] data) { - - currentPage.createText(fontNumber, x + xOffset, y + yOffset, rotation, - col, vsci, ica, data); - - } - - /** - * Returns an ImageObject used to create an image in the datastream. - * - * @param x - * the x position of the image - * @param y - * the y position of the image - * @param w - * the width of the image - * @param h - * the height of the image - * @param wr - * the width resolution of the image - * @param hr - * the height resolution of the image - * @return ImageObject used to create an image in the datastream - */ - public ImageObject getImageObject(int x, int y, int w, int h, int wr, int hr) { - - int xOrigin; - int yOrigin; - int width; - int height; - int widthResolution; - int heightResolution; - - switch (rotation) { - case 90: - xOrigin = currentPage.getWidth() - y - yOffset; - yOrigin = x + xOffset; - width = h; - height = w; - widthResolution = hr; - heightResolution = wr; - break; - case 180: - xOrigin = currentPage.getWidth() - x - xOffset; - yOrigin = currentPage.getHeight() - y - yOffset; - width = w; - height = h; - widthResolution = wr; - heightResolution = hr; - break; - case 270: - xOrigin = y + yOffset; - yOrigin = currentPage.getHeight() - x - xOffset; - width = h; - height = w; - widthResolution = hr; - heightResolution = wr; - break; - default: - xOrigin = x + xOffset; - yOrigin = y + yOffset; - width = w; - height = h; - widthResolution = wr; - heightResolution = hr; - break; - } - ImageObject io = currentPage.getImageObject(); - io.setImageViewport(xOrigin, yOrigin, width, height, rotation, - widthResolution, heightResolution); - return io; - - } - - /** - * Method to create a line on the current page. - * - * @param x1 - * the first x coordinate of the line - * @param y1 - * the first y coordinate of the line - * @param x2 - * the second x coordinate of the line - * @param y2 - * the second y coordinate of the line - * @param thickness - * the thickness of the line - * @param col - * The text color. - */ - public void createLine(int x1, int y1, int x2, int y2, int thickness, - Color col) { - - currentPage.createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset, y2 - + yOffset, thickness, rotation, col); - - } - - /** - * This method will create shading on the page using the specified - * coordinates (the shading contrast is controlled via the red, green, blue - * parameters, by converting this to grey scale). - * - * @param x - * the x coordinate of the shading - * @param y - * the y coordinate of the shading - * @param w - * the width of the shaded area - * @param h - * the height of the shaded area - * @param red - * the red value - * @param green - * the green value - * @param blue - * the blue value - */ - public void createShading(int x, int y, int w, int h, int red, int green, - int blue) { - - currentPage.createShading(x + xOffset, y + xOffset, w, h, red, green, - blue); - - } - - /** - * Helper method which allows creation of the MPO object, via the AEG. And - * the IPO via the Page. (See actual object for descriptions.) - * - * @param name - * the name of the static overlay - */ - public void createIncludePageOverlay(String name) { - - currentPageObject.createIncludePageOverlay(name, 0, 0, rotation); - ActiveEnvironmentGroup aeg = currentPageObject - .getActiveEnvironmentGroup(); - aeg.createOverlay(name); - - } - - /** - * Helper method which allows creation of the IMM object. - * - * @param name - * the name of the medium map - */ - public void createInvokeMediumMap(String name) { - - if (currentPageGroup == null) { - startPageGroup(); - } - currentPageGroup.createInvokeMediumMap(name); - - } - - /** - * Creates an IncludePageSegment on the current page. - * - * @param name - * the name of the include page segment - * @param x - * the x coordinate for the overlay - * @param y - * the y coordinate for the overlay - */ - public void createIncludePageSegment(String name, int x, int y) { - - int xOrigin; - int yOrigin; - switch (rotation) { - case 90: - xOrigin = currentPage.getWidth() - y - yOffset; - yOrigin = x + xOffset; - break; - case 180: - xOrigin = currentPage.getWidth() - x - xOffset; - yOrigin = currentPage.getHeight() - y - yOffset; - break; - case 270: - xOrigin = y + yOffset; - yOrigin = currentPage.getHeight() - x - xOffset; - break; - default: - xOrigin = x + xOffset; - yOrigin = y + yOffset; - break; - } - currentPage.createIncludePageSegment(name, xOrigin, yOrigin); - - } - - /** - * Creates a TagLogicalElement on the current page. - * - * @param attributes - * the array of key value pairs. - */ - public void createPageTagLogicalElement(TagLogicalElementBean[] attributes) { - - for (int i = 0; i < attributes.length; i++) { - String name = (String) attributes[i].getKey(); - String value = (String) attributes[i].getValue(); - currentPage.createTagLogicalElement(name, value); - } - - } - - /** - * Creates a TagLogicalElement on the current page group. - * - * @param attributes - * the array of key value pairs. - */ - public void createPageGroupTagLogicalElement( - TagLogicalElementBean[] attributes) { - - for (int i = 0; i < attributes.length; i++) { - String name = (String) attributes[i].getKey(); - String value = (String) attributes[i].getValue(); - currentPageGroup.createTagLogicalElement(name, value); - } - - } - - /** - * Creates a TagLogicalElement on the current page or page group - * - * @param name - * The tag name - * @param value - * The tag value - */ - public void createTagLogicalElement(String name, String value) { - - if (currentPageGroup != null) { - currentPageGroup.createTagLogicalElement(name, value); - } else { - currentPage.createTagLogicalElement(name, value); - } - - } - - /** - * Creates a NoOperation item - * - * @param content - * byte data - */ - public void createNoOperation(String content) { - currentPage.createNoOperation(content); - } - - /** - * Start a new page group. When processing has finished on the current page - * group the {@link #endPageGroup()}method must be invoked to mark the page - * group ending. - */ - public void startPageGroup() { - - String pageGroupName = "PGP" - + StringUtils.lpad(String.valueOf(pageCount++), '0', 5); - - currentPageGroup = new PageGroup(pageGroupName); - - } - - /** - * Helper method to mark the end of the page group. - * @throws IOException thrown if an I/O exception of some sort has occurred - */ - public void endPageGroup() throws IOException { - - currentPageGroup.endPageGroup(); - document.addPageGroup(currentPageGroup); - document.writeDataStream(outputStream); - currentPageGroup = null; - - } - - /** - * Sets the rotation to be used for portrait pages, valid values are 0 - * (default), 90, 180, 270. - * - * @param pageRotation - * The rotation in degrees. - */ - public void setPortraitRotation(int pageRotation) { - - if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180 - || pageRotation == 270) { - this.portraitRotation = pageRotation; - } else { - throw new IllegalArgumentException( - "The portrait rotation must be one of the values 0, 90, 180, 270"); - } - - } - - /** - * Sets the rotation to be used for landscape pages, valid values are 0, 90, - * 180, 270 (default). - * - * @param pageRotation - * The rotation in degrees. - */ - public void setLandscapeRotation(int pageRotation) { - - if (pageRotation == 0 || pageRotation == 90 || pageRotation == 180 - || pageRotation == 270) { - this.landscapeRotation = pageRotation; - } else { - throw new IllegalArgumentException( - "The landscape rotation must be one of the values 0, 90, 180, 270"); - } - - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java deleted file mode 100644 index ef1b988c0..000000000 --- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java +++ /dev/null @@ -1,66 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * This is the base class for all data stream objects. Page objects are - * responsible for building and generating the binary datastream in an - * AFP format. - * - */ -public abstract class AbstractAFPObject { - - /** - * Static logging instance - */ - protected static final Log log = LogFactory.getLog("org.apache.fop.render.afp.modca"); - - /** - * DataStream objects must implement the writeDataStream() - * method to write its data to the given OutputStream - * @param os The outputsteam stream - * @throws java.io.IOException - */ - public abstract void writeDataStream(OutputStream os) throws IOException; - - /** - * Help method to write a set of AFPObjects to the AFP datastream. - * @param afpObjects a list of AFPObjects - * @param os The stream to write to - * @throws java.io.IOException - */ - protected void writeObjectList(List afpObjects, OutputStream os) - throws IOException { - - for (Iterator it = afpObjects.iterator(); it.hasNext(); ) { - ((AbstractAFPObject)it.next()).writeDataStream(os); - } - - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java deleted file mode 100644 index 85552a9e9..000000000 --- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java +++ /dev/null @@ -1,69 +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.render.afp.modca; -import java.io.UnsupportedEncodingException; - -/** - * This is the base class for all named data stream objects. - * A named data stream object has an 8 byte EBCIDIC name. - */ -public abstract class AbstractNamedAFPObject extends AbstractAFPObject { - - /** - * The actual name of the object - */ - protected String name = null; - - /** - * The name of the object in EBCIDIC bytes - */ - protected byte[] nameBytes; - - /** - * Constructor for the ActiveEnvironmentGroup, this takes a - * name parameter which should be 8 characters long. - * @param name the object name - */ - public AbstractNamedAFPObject(String name) { - - this.name = name; - if (name.length() < 8) { - name = (name + " ").substring(0, 8); - } else if (name.length() > 8) { - log.warn("Constructor:: name truncated to 8 chars" + name); - name = name.substring(0, 8); - } - - try { - - nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - - } catch (UnsupportedEncodingException usee) { - - nameBytes = name.getBytes(); - log.warn( - "Constructor:: UnsupportedEncodingException translating the name " - + name); - - } - - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java deleted file mode 100644 index a99b28107..000000000 --- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java +++ /dev/null @@ -1,435 +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.render.afp.modca; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -import org.apache.fop.render.afp.fonts.AFPFont; -import org.apache.fop.render.afp.tools.StringUtils; - -/** - * Pages contain the data objects that comprise a presentation document. Each - * page has a set of data objects associated with it. Each page within a - * document is independent from any other page, and each must establish its own - * environment parameters. - * - * The page is the level in the document component hierarchy that is used for - * printing or displaying a document's content. The data objects contained in - * the page envelope in the data stream are presented when the page is - * presented. Each data object has layout information associated with it that - * directs the placement and orientation of the data on the page. In addition, - * each page contains layout information that specifies the measurement units, - * page width, and page depth. - * - * A page is initiated by a begin page structured field and terminated by an end - * page structured field. Structured fields that define objects and active - * environment groups or that specify attributes of the page may be encountered - * in page state. - * - */ -public abstract class AbstractPageObject extends AbstractNamedAFPObject { - - /** - * The active environment group for the page - */ - protected ActiveEnvironmentGroup activeEnvironmentGroup = null; - - /** - * The presentation text object, we only have one per page - */ - private PresentationTextObject presentationTextObject = null; - - /** - * The list of objects within the page - */ - protected List objects = new ArrayList(); - - /** - * The list of tag logical elements - */ - protected ArrayList tagLogicalElements = new ArrayList(); - - /** - * The list of the include page segments - */ - protected ArrayList segments = new ArrayList(); - - /** - * The page width - */ - private int width; - - /** - * The page height - */ - private int height; - - /** - * The page rotation - */ - private int rotation = 0; - - /** - * The page state - */ - private boolean complete = false; - - /** - * Construct a new page object for the specified name argument, the page - * name should be an 8 character identifier. - * - * @param name - * the name of the page. - * @param width - * the width of the page. - * @param height - * the height of the page. - * @param rotation - * the rotation of the page. - * @param widthResolution - * the width resolution of the page. - * @param heightResolution - * the height resolution of the page. - */ - public AbstractPageObject(String name, int width, int height, int rotation, - int widthResolution, int heightResolution) { - - super(name); - this.width = width; - this.height = height; - this.rotation = rotation; - - /** - * Every page object must have an ActiveEnvironmentGroup - */ - activeEnvironmentGroup = new ActiveEnvironmentGroup(width, height, - widthResolution, heightResolution); - - if (rotation != 0) { - switch (rotation) { - case 90: - activeEnvironmentGroup.setPosition(width, 0, rotation); - break; - case 180: - activeEnvironmentGroup.setPosition(width, height, rotation); - break; - case 270: - activeEnvironmentGroup.setPosition(0, height, rotation); - break; - default: - } - } - - /** - * We have a presentation text object per page - */ - presentationTextObject = new PresentationTextObject(); - objects.add(presentationTextObject); - - } - - /** - * Helper method to create a map coded font object on the current page, this - * method delegates the construction of the map coded font object to the - * active environment group on the page. - * - * @param fontReference - * the font number used as the resource identifier - * @param font - * the font - * @param size - * the point size of the font - */ - public void createFont(byte fontReference, AFPFont font, int size) { - - activeEnvironmentGroup.createFont(fontReference, font, size, 0); - - } - - /** - * Helper method to create a line on the current page, this method delegates - * to the presentation text object in order to construct the line. - * - * @param x1 - * the first x coordinate of the line - * @param y1 - * the first y coordinate of the line - * @param x2 - * the second x coordinate of the line - * @param y2 - * the second y coordinate of the line - * @param thickness - * the thickness of the line - * @param lineRotation - * the rotation of the line - * @param col - * The text color. - */ - public void createLine(int x1, int y1, int x2, int y2, int thickness, - int lineRotation, Color col) { - - if (presentationTextObject == null) { - presentationTextObject = new PresentationTextObject(); - objects.add(presentationTextObject); - } - presentationTextObject.createLineData(x1, y1, x2, y2, thickness, lineRotation, col); - - } - - /** - * Helper method to create text on the current page, this method delegates - * to the presentation text object in order to construct the text. - * - * @param fontNumber - * the font number used as the resource identifier - * @param x - * the x coordinate of the text data - * @param y - * the y coordinate of the text data - * @param textRotation - * the rotation of the text data - * @param col - * the text color - * @param vsci - * The variable space character increment. - * @param ica - * The inter character adjustment. - * @param data - * the text data to create - */ - public void createText(int fontNumber, int x, int y, int textRotation, Color col, - int vsci, int ica, byte[] data) { - - if (presentationTextObject == null) { - presentationTextObject = new PresentationTextObject(); - objects.add(presentationTextObject); - } - presentationTextObject.createTextData(fontNumber, x, y, textRotation, col, vsci, ica, data); - - } - - /** - * Helper method to mark the end of the page. This should end the control - * sequence on the current presenation text object. - */ - public void endPage() { - - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - } - - complete = true; - - } - - /** - * This method will create shading on the page using the specified - * coordinates (the shading contrast is controlled via the red, green blue - * parameters, by converting this to grey scale). - * - * @param x - * the x coordinate of the shading - * @param y - * the y coordinate of the shading - * @param w - * the width of the shaded area - * @param h - * the height of the shaded area - * @param red - * the red value - * @param green - * the green value - * @param blue - * the blue value - */ - public void createShading(int x, int y, int w, int h, int red, int green, - int blue) { - - int xCoord = 0; - int yCoord = 0; - int areaWidth = 0; - int areaHeight = 0; - - switch (rotation) { - case 90: - xCoord = areaWidth - y - h; - yCoord = x; - areaWidth = h; - areaHeight = w; - break; - case 180: - xCoord = areaWidth - x - w; - yCoord = areaHeight - y - h; - areaWidth = w; - areaHeight = h; - break; - case 270: - xCoord = y; - yCoord = areaHeight - x - w; - areaWidth = h; - areaHeight = w; - break; - default: - xCoord = x; - yCoord = y; - areaWidth = w; - areaHeight = h; - break; - } - - // Convert the color to grey scale - float shade = (float) ((red * 0.3) + (green * 0.59) + (blue * 0.11)); - - int greyscale = Math.round((shade / 255) * 16); - - String imageName = "IMG" - + StringUtils.lpad(String.valueOf(objects.size() + 1), - '0', 5); - - IMImageObject io = new IMImageObject(imageName); - ImageOutputControl ioc = new ImageOutputControl(0, 0); - ImageInputDescriptor iid = new ImageInputDescriptor(); - ImageCellPosition icp = new ImageCellPosition(xCoord, yCoord); - icp.setXFillSize(areaWidth); - icp.setYFillSize(areaHeight); - icp.setXSize(64); - icp.setYSize(8); - - //defining this as a resource - ImageRasterData ird = new ImageRasterData(ImageRasterPattern - .getRasterData(greyscale)); - - io.setImageOutputControl(ioc); - io.setImageInputDescriptor(iid); - io.setImageCellPosition(icp); - io.setImageRasterData(ird); - objects.add(io); - - } - - /** - * Helper method to create an image on the current page and to return - * the object. - * @return the image object - */ - public ImageObject getImageObject() { - - if (presentationTextObject != null) { - presentationTextObject.endControlSequence(); - } - presentationTextObject = null; - - String imageName = "IMG" - + StringUtils.lpad(String.valueOf(objects.size() + 1), - '0', 5); - - ImageObject io = new ImageObject(imageName); - objects.add(io); - return io; - } - - /** - * Creates a TagLogicalElement on the page. - * - * @param name - * the name of the tag - * @param value - * the value of the tag - */ - public void createTagLogicalElement(String name, String value) { - - TagLogicalElement tle = new TagLogicalElement(name, value); - tagLogicalElements.add(tle); - - } - - /** - * Creates a NoOperation on the page. - * - * @param content the byte data - */ - public void createNoOperation(String content) { - - NoOperation noOp = new NoOperation(content); - objects.add(noOp); - - } - - /** - * Creates an IncludePageSegment on the current page. - * - * @param name - * the name of the page segment - * @param xCoor - * the x cooridinate of the page segment. - * @param yCoor - * the y cooridinate of the page segment. - */ - public void createIncludePageSegment(String name, int xCoor, int yCoor) { - - IncludePageSegment ips = new IncludePageSegment(name, xCoor, yCoor); - segments.add(ips); - - } - - /** - * Returns the ActiveEnvironmentGroup associated with this page. - * - * @return the ActiveEnvironmentGroup object - */ - public ActiveEnvironmentGroup getActiveEnvironmentGroup() { - return activeEnvironmentGroup; - } - - /** - * Returns an indication if the page is complete - * @return whether this page is complete - */ - public boolean isComplete() { - return complete; - } - - /** - * Returns the height of the page - * @return the height of the page - */ - public int getHeight() { - return height; - } - - /** - * Returns the width of the page - * @return the width of the page - */ - public int getWidth() { - return width; - } - - /** - * Returns the rotation of the page - * @return the rotation of the page - */ - public int getRotation() { - return rotation; - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java deleted file mode 100644 index 3e341c735..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ActiveEnvironmentGroup.java +++ /dev/null @@ -1,353 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; - -import org.apache.fop.render.afp.fonts.AFPFont; - -/** - * An Active Environment Group (AEG) is associated with each page, - * and is contained in the page's begin-end envelope in the data stream. - * The active environment group contains layout and formatting information - * that defines the measurement units and size of the page, and may contain - * resource information. - * - * Any objects that are required for page presentation and that are to be - * treated as resource objects must be mapped with a map structured field - * in the AEG. The scope of an active environment group is the scope of its - * containing page or overlay. - * - */ -public final class ActiveEnvironmentGroup extends AbstractNamedAFPObject { - - /** - * Default name for the active environment group - */ - private static final String DEFAULT_NAME = "AEG00001"; - - /** - * The collection of MapCodedFont objects - */ - private ArrayList mapCodedFonts = new ArrayList(); - - /** - * The Object Area Descriptor for the active environment group - */ - private ObjectAreaDescriptor objectAreaDescriptor = null; - - /** - * The Object Area Position for the active environment group - */ - private ObjectAreaPosition objectAreaPosition = null; - - /** - * The PresentationTextDescriptor for the active environment group - */ - private PresentationTextDescriptor presentationTextDataDescriptor = null; - - /** - * The PageDescriptor for the active environment group - */ - private PageDescriptor pageDescriptor = null; - - /** - * The collection of MapPageOverlay objects - */ - private ArrayList mapPageOverlays = new ArrayList(); - - /** - * Default constructor for the ActiveEnvironmentGroup. - * @param width the page width - * @param height the page height - * @param widthResolution the page width resolution - * @param heightResolution the page height resolution - */ - public ActiveEnvironmentGroup(int width, int height, - int widthResolution, int heightResolution) { - - this(DEFAULT_NAME, width, height, widthResolution, heightResolution); - - } - - /** - * Constructor for the ActiveEnvironmentGroup, this takes a - * name parameter which must be 8 characters long. - * @param name the active environment group name - * @param width the page width - * @param height the page height - * @param widthResolution the page width resolution - * @param heightResolution the page height resolution - */ - public ActiveEnvironmentGroup(String name, int width, int height, - int widthResolution, int heightResolution) { - - super(name); - - // Create PageDescriptor - pageDescriptor = new PageDescriptor(width, height, widthResolution, heightResolution); - - // Create ObjectAreaDescriptor - objectAreaDescriptor = new ObjectAreaDescriptor(width, height, - widthResolution, heightResolution); - - // Create PresentationTextDataDescriptor - presentationTextDataDescriptor = new PresentationTextDescriptor(width, height, - widthResolution, heightResolution); - - } - - /** - * Set the position of the object area - * @param x the x offset - * @param y the y offset - * @param rotation the rotation - */ - public void setPosition(int x, int y, int rotation) { - - // Create ObjectAreaPosition - objectAreaPosition = new ObjectAreaPosition(x, y, rotation); - - } - - /** - * Accessor method to obtain the PageDescriptor object of the - * active environment group. - * @return the page descriptor object - */ - public PageDescriptor getPageDescriptor() { - - return pageDescriptor; - - } - - /** - * Accessor method to obtain the PresentationTextDataDescriptor object of - * the active environment group. - * @return the presentation text descriptor - */ - public PresentationTextDescriptor getPresentationTextDataDescriptor() { - - return presentationTextDataDescriptor; - - } - - /** - * Accessor method to write the AFP datastream for the active environment group. - * @param os The stream to write to - * @throws java.io.IOException throws if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(mapCodedFonts, os); - - writeObjectList(mapPageOverlays, os); - - pageDescriptor.writeDataStream(os); - - if (objectAreaDescriptor != null && objectAreaPosition != null) { - objectAreaDescriptor.writeDataStream(os); - objectAreaPosition.writeDataStream(os); - } - - presentationTextDataDescriptor.writeDataStream(os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the active environment group. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xC9; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the active environment group. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xC9; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Method to create a map coded font object - * @param fontReference the font number used as the resource identifier - * @param font the font - * @param size the point size of the font - * @param orientation the orientation of the font (e.g. 0, 90, 180, 270) - */ - public void createFont( - byte fontReference, - AFPFont font, - int size, - int orientation) { - - MapCodedFont mcf = getCurrentMapCodedFont(); - - if (mcf == null) { - mcf = new MapCodedFont(); - mapCodedFonts.add(mcf); - } - - try { - - mcf.addFont( - fontReference, - font, - size, - orientation); - - } catch (MaximumSizeExceededException msee) { - - mcf = new MapCodedFont(); - mapCodedFonts.add(mcf); - - try { - - mcf.addFont( - fontReference, - font, - size, - orientation); - - } catch (MaximumSizeExceededException ex) { - - // Should never happen (but log just in case) - log.error("createFont():: resulted in a MaximumSizeExceededException"); - - } - - } - - } - - /** - * Actually creates the MPO object. - * Also creates the supporting object (an IPO) - * @param name the name of the overlay to be used - */ - public void createOverlay(String name) { - - MapPageOverlay mpo = getCurrentMapPageOverlay(); - - if (mpo == null) { - mpo = new MapPageOverlay(); - mapPageOverlays.add(mpo); - } - - try { - - mpo.addOverlay(name); - - } catch (MaximumSizeExceededException msee) { - mpo = new MapPageOverlay(); - mapPageOverlays.add(mpo); - try { - mpo.addOverlay(name); - } catch (MaximumSizeExceededException ex) { - // Should never happen (but log just in case) - log.error("createOverlay():: resulted in a MaximumSizeExceededException"); - } - } - } - - /** - * Getter method for the most recent MapCodedFont added to the - * Active Environment Group (returns null if no MapCodedFonts exist) - * @return the most recent Map Coded Font. - */ - private MapCodedFont getCurrentMapCodedFont() { - - int size = mapCodedFonts.size(); - if (size > 0) { - return (MapCodedFont) mapCodedFonts.get(mapCodedFonts.size() - 1); - } else { - return null; - } - - } - - /** - * Getter method for the most recent MapPageOverlay added to the - * Active Environment Group (returns null if no MapPageOverlay exist) - * @return the most recent Map Coded Font - */ - private MapPageOverlay getCurrentMapPageOverlay() { - - int size = mapPageOverlays.size(); - if (size > 0) { - return (MapPageOverlay) mapPageOverlays.get( - mapPageOverlays.size() - 1); - } else { - return null; - } - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Document.java b/src/java/org/apache/fop/render/afp/modca/Document.java deleted file mode 100644 index 3d2d40a3a..000000000 --- a/src/java/org/apache/fop/render/afp/modca/Document.java +++ /dev/null @@ -1,213 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.List; - -/** - * The document is the highest level of the MO:DCA data-stream document - * component hierarchy. Documents can be made up of pages, and the pages, - * which are at the intermediate level, can be made up of objects. Objects - * are at the lowest level, and can be bar codes, graphics, images, and - * presentation text. - * - * At each level of the hierarchy certain sets of MO:DCA data structures, - * called structured fields, are permissible. The document, pages and objects - * are bounded by structured fields that define their beginnings and their ends. - * These structured fields, called begin-end pairs, provide an envelope for the - * data-stream components. This feature enables a processor of the data stream - * that is not fully compliant with the architecture to bypass those objects - * that are beyond its scope, and to process the data stream to the best of its - * abilities. - * - * A presentation document is one that has been formatted and is intended for - * presentation, usually on a printer or display device. A data stream containing - * a presentation document should produce the same document content in the - * same format on different printers or display devices dependent, however, - * on the capabilities of each of the printers or display devices. A presentation - * document can reference resources that are to be included as part of the - * document to be presented. - * - */ -public final class Document extends AbstractNamedAFPObject { - - /** - * Ststic default name reference - */ - private static final String DEFAULT_NAME = "DOC00001"; - - /** - * A list of the objects in the document - */ - private List objects = new java.util.ArrayList(); - - /** - * The document started state - */ - private boolean started = false; - - /** - * The document completion state - */ - private boolean complete = false; - - /** - * Default constructor for the document object. - */ - public Document() { - this(DEFAULT_NAME); - } - - /** - * Constructor for the document object. - * @param name The name of the document - */ - public Document(String name) { - - super(name); - - } - - /** - * Adds a page to the document. - * @param page - the Page object - */ - public void addPage(PageObject page) { - if (!objects.contains(page)) { - objects.add(page); - } - } - - /** - * Adds a PageGroup to the document. - * @param pageGroup the PageGroup object - */ - public void addPageGroup(PageGroup pageGroup) { - objects.add(pageGroup); - } - - /** - * Method to mark the end of the page group. - */ - public void endDocument() { - - complete = true; - - } - - /** - * Returns an indication if the page group is complete - * @return whether or not this page group is complete - */ - public boolean isComplete() { - return complete; - } - - /** - * Accessor method to write the AFP datastream for document. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - if (!started) { - writeStart(os); - started = true; - } - - for (Iterator it = objects.iterator(); it.hasNext();) { - AbstractAFPObject ao = (AbstractAFPObject)it.next(); - if (ao instanceof PageObject && ((PageObject)ao).isComplete() - || ao instanceof PageGroup && ((PageGroup)ao).isComplete()) { - ao.writeDataStream(os); - it.remove(); - } else { - break; - } - } - - if (complete) { - writeEnd(os); - } - - } - - /** - * Helper method to write the start of the Document - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xA8; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the Document. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xA8; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java deleted file mode 100644 index e6f9f1857..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java +++ /dev/null @@ -1,295 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - */ -public class ImageContent extends AbstractAFPObject { - - /** - * The image size parameter - */ - private ImageSizeParameter _imageSizeParameter = null; - - /** - * The image encoding - */ - private byte _encoding = 0x03; - - /** - * The image ide size - */ - private byte _size = 1; - - /** - * The image compression - */ - private byte _compression = (byte)0xC0; - - /** - * The image color model - */ - private byte _colorModel = 0x01; - - /** - * The image data - */ - private byte _data[] = null; - - /** - * Constructor for the image content - */ - public ImageContent() { - - } - - /** - * Sets the image size parameters - * resolution, hsize and vsize. - * @param hresol The horizontal resolution of the image. - * @param vresol The vertical resolution of the image. - * @param hsize The horizontal size of the image. - * @param vsize The vertival size of the image. - */ - public void setImageSize(int hresol, int vresol, int hsize, int vsize) { - _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize); - } - - /** - * Sets the image encoding. - * @param encoding The image encoding. - */ - public void setImageEncoding(byte encoding) { - _encoding = encoding; - } - - /** - * Sets the image compression. - * @param compression The image compression. - */ - public void setImageCompression(byte compression) { - _compression = compression; - } - - /** - * Sets the image IDE size. - * @param size The IDE size. - */ - public void setImageIDESize(byte size) { - _size = size; - } - - /** - * Sets the image IDE color model. - * @param colorModel the IDE color model. - */ - public void setImageIDEColorModel(byte colorModel) { - _colorModel = colorModel; - } - - /** - * Set the data of the image. - */ - public void setImageData(byte data[]) { - _data = data; - } - - /** - * Accessor method to write the AFP datastream for the Image Content - * @param os The stream to write to - * @throws java.io.IOException - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - if (_imageSizeParameter != null) { - _imageSizeParameter.writeDataStream(os); - } - - os.write(getImageEncodingParameter()); - - os.write(getImageIDESizeParameter()); - - os.write(getIDEStructureParameter()); - - os.write(getExternalAlgorithmParameter()); - - if (_data != null) { - int off = 0; - while (off < _data.length) { - int len = Math.min(30000, _data.length - off); - os.write(getImageDataStart(len)); - os.write(_data, off, len); - off += len; - } - } - - writeEnd(os); - - } - - /** - * Helper method to write the start of the Image Content. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[] { - (byte)0x91, // ID - 0x01, // Length - (byte)0xff, // Object Type = IOCA Image Object - }; - - os.write(data); - - } - - /** - * Helper method to write the end of the Image Content. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[] { - (byte)0x93, // ID - 0x00, // Length - }; - - os.write(data); - - } - - /** - * Helper method to return the start of the image segment. - * @return byte[] The data stream. - */ - private byte[] getImageDataStart(int len) { - - byte[] data = new byte[] { - (byte)0xFE, // ID - (byte)0x92, // ID - 0x00, // Length - 0x00, // Length - }; - - byte[] l = BinaryUtils.convert(len, 2); - data[2] = l[0]; - data[3] = l[1]; - - - return data; - - } - - /** - * Helper method to return the image encoding parameter. - * @return byte[] The data stream. - */ - private byte[] getImageEncodingParameter() { - - byte[] data = new byte[] { - (byte)0x95, // ID - 0x02, // Length - _encoding, - 0x01, // RECID - }; - - return data; - - } - - /** - * Helper method to return the external algorithm parameter. - * @return byte[] The data stream. - */ - private byte[] getExternalAlgorithmParameter() { - - if (_encoding == (byte)0x83 && _compression != 0) { - byte[] data = new byte[] { - (byte)0x95, // ID - 0x00, // Length - 0x10, // ALGTYPE = Compression Algorithm - 0x00, // Reserved - (byte)0x83, // COMPRID = JPEG - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Reserved - _compression, // MARKER - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Reserved - }; - data[1] = (byte)(data.length - 2); - return data; - } - return new byte[0]; - } - - /** - * Helper method to return the image encoding parameter. - * @return byte[] The data stream. - */ - private byte[] getImageIDESizeParameter() { - - byte[] data = new byte[] { - (byte)0x96, // ID - 0x01, // Length - _size, - }; - - return data; - - } - - /** - * Helper method to return the external algorithm parameter. - * @return byte[] The data stream. - */ - private byte[] getIDEStructureParameter() { - - if (_colorModel != 0 && _size == 24) { - byte bits = (byte)(_size / 3); - byte[] data = new byte[] { - (byte)0x9B, // ID - 0x00, // Length - 0x00, // FLAGS - 0x00, // Reserved - _colorModel, // COLOR MODEL - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Reserved - bits, - bits, - bits, - }; - data[1] = (byte)(data.length - 2); - return data; - } - return new byte[0]; - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java deleted file mode 100644 index 9250f0c7f..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java +++ /dev/null @@ -1,109 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - */ -public class ImageDataDescriptor extends AbstractAFPObject { - - private int _xresol = 0; - private int _yresol = 0; - private int _width = 0; - private int _height = 0; - - /** - * Constructor for a ImageDataDescriptor for the specified - * resolution, width and height. - * @param xresol The horizontal resolution of the image. - * @param yresol The vertical resolution of the image. - * @param width The width of the image. - * @param height The height of the height. - */ - public ImageDataDescriptor(int xresol, int yresol, int width, int height) { - - _xresol = xresol; - _yresol = yresol; - _width = width; - _height = height; - - } - - /** - * Accessor method to write the AFP datastream for the Image Data Descriptor - * @param os The stream to write to - * @throws java.io.IOException - */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = new byte[] { - 0x5A, - 0x00, - 0x20, - (byte) 0xD3, - (byte) 0xA6, - (byte) 0xFB, - 0x00, // Flags - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Unit base - 10 Inches - 0x00, // XRESOL - 0x00, // - 0x00, // YRESOL - 0x00, // - 0x00, // XSIZE - 0x00, // - 0x00, // YSIZE - 0x00, // - (byte)0xF7, // ID = Set IOCA Function Set - 0x02, // Length - 0x01, // Category = Function set identifier - 0x0B, // FCNSET = IOCA FS 11 - }; - - byte[] l = BinaryUtils.convert(data.length - 1, 2); - data[1] = l[0]; - data[2] = l[1]; - - byte[] x = BinaryUtils.convert(_xresol, 2); - data[10] = x[0]; - data[11] = x[1]; - - byte[] y = BinaryUtils.convert(_yresol, 2); - data[12] = y[0]; - data[13] = y[1]; - - byte[] w = BinaryUtils.convert(_width, 2); - data[14] = w[0]; - data[15] = w[1]; - - byte[] h = BinaryUtils.convert(_height, 2); - data[16] = h[0]; - data[17] = h[1]; - - os.write(data); - - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/ImageObject.java b/src/java/org/apache/fop/render/afp/modca/ImageObject.java deleted file mode 100644 index 66c46c872..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ImageObject.java +++ /dev/null @@ -1,275 +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.render.afp.modca; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * An IOCA Image Data Object - */ -public class ImageObject extends AbstractNamedAFPObject { - - /** - * The object environment group - */ - private ObjectEnvironmentGroup objectEnvironmentGroup = null; - - /** - * The image segment - */ - private ImageSegment imageSegment = null; - - /** - * Constructor for the image object with the specified name, - * the name must be a fixed length of eight characters. - * @param name The name of the image. - */ - public ImageObject(String name) { - - super(name); - - } - - /** - * Sets the image display area position and size. - * - * @param x - * the x position of the image - * @param y - * the y position of the image - * @param w - * the width of the image - * @param h - * the height of the image - * @param r - * the rotation of the image - * @param wr - * the width resolution of the image - * @param hr - * the height resolution of the image - */ - public void setImageViewport(int x, int y, int w, int h, int r, int wr, int hr) { - if (objectEnvironmentGroup == null) { - objectEnvironmentGroup = new ObjectEnvironmentGroup(); - } - objectEnvironmentGroup.setObjectArea(x, y, w, h, r, wr, hr); - } - - /** - * Set the dimensions of the image. - * @param xresol the x resolution of the image - * @param yresol the y resolution of the image - * @param width the image width - * @param height the image height - */ - public void setImageParameters(int xresol, int yresol, int width, int height) { - if (objectEnvironmentGroup == null) { - objectEnvironmentGroup = new ObjectEnvironmentGroup(); - } - objectEnvironmentGroup.setImageData(xresol, yresol, width, height); - if (imageSegment == null) { - imageSegment = new ImageSegment(); - } - imageSegment.setImageSize(xresol, yresol, width, height); - } - - /** - * Sets the image encoding. - * @param encoding The image encoding. - */ - public void setImageEncoding(byte encoding) { - if (imageSegment == null) { - imageSegment = new ImageSegment(); - } - imageSegment.setImageEncoding(encoding); - } - - /** - * Sets the image compression. - * @param compression The image compression. - */ - public void setImageCompression(byte compression) { - if (imageSegment == null) { - imageSegment = new ImageSegment(); - } - imageSegment.setImageCompression(compression); - } - - /** - * Sets the image IDE size. - * @param size The IDE size. - */ - public void setImageIDESize(byte size) { - if (imageSegment == null) { - imageSegment = new ImageSegment(); - } - imageSegment.setImageIDESize(size); - } - - /** - * Sets the image IDE color model. - * @param colorModel the IDE color model. - */ - public void setImageIDEColorModel(byte colorModel) { - if (imageSegment == null) { - imageSegment = new ImageSegment(); - } - imageSegment.setImageIDEColorModel(colorModel); - } - - /** - * Set the data of the image. - * @param data The image data - */ - public void setImageData(byte[] data) { - if (imageSegment == null) { - imageSegment = new ImageSegment(); - } - imageSegment.setImageData(data); - } - - /** - * Sets the ObjectEnvironmentGroup. - * @param objectEnvironmentGroup The objectEnvironmentGroup to set - */ - public void setObjectEnvironmentGroup(ObjectEnvironmentGroup objectEnvironmentGroup) { - this.objectEnvironmentGroup = objectEnvironmentGroup; - } - - /** - * Helper method to return the start of the image object. - * @return byte[] The data stream. - */ - private byte[] getIPDStart(int len) { - - byte[] data = new byte[] { - - 0x5A, // Structured field identifier - 0x00, // Length byte 1 - 0x10, // Length byte 2 - (byte) 0xD3, // Structured field id byte 1 - (byte) 0xEE, // Structured field id byte 2 - (byte) 0xFB, // Structured field id byte 3 - 0x00, // Flags - 0x00, // Reserved - 0x00, // Reserved - }; - - byte[] l = BinaryUtils.convert(len + 8, 2); - data[1] = l[0]; - data[2] = l[1]; - - return data; - - } - - /** - * Accessor method to write the AFP datastream for the Image Object - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - if (objectEnvironmentGroup != null) { - objectEnvironmentGroup.writeDataStream(os); - } - - if (imageSegment != null) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - imageSegment.writeDataStream(baos); - byte[] b = baos.toByteArray(); - int off = 0; - while (off < b.length) { - int len = Math.min(30000, b.length - off); - os.write(getIPDStart(len)); - os.write(b, off, len); - off += len; - } - } - - writeEnd(os); - - } - - /** - * Helper method to write the start of the Image Object. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xFB; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the Image Object. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xFB; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java deleted file mode 100644 index 7d6cc18aa..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java +++ /dev/null @@ -1,214 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -/** - * An Image Segment is represented by a set of self-defining fields, fields - * that describe their own contents. It starts with a Begin Segment, and - * ends with an End Segment. - * - * Between the Begin Segment and End Segment is the image information to - * be processed, called the Image Content. - * - * Only one Image Content can exist within a single IOCA Image Segment. - */ -public class ImageSegment extends AbstractAFPObject { - - /** - * Default name for the object environment group - */ - private static final String DEFAULT_NAME = "IS01"; - - /** - * The name of the image segment - */ - private String name; - - /** - * The name of the image segment as EBCIDIC bytes - */ - private byte[] nameBytes; - - /** - * The ImageContent for the image segment - */ - private ImageContent imageContent = null; - - /** - * Default constructor for the ImageSegment. - */ - public ImageSegment() { - this(DEFAULT_NAME); - } - - /** - * Constructor for the image segment with the specified name, - * the name must be a fixed length of eight characters. - * @param name The name of the image. - */ - public ImageSegment(String name) { - - if (name.length() != 4) { - String msg = "Image segment name must be 4 characters long " + name; - log.error("Constructor:: " + msg); - throw new IllegalArgumentException(msg); - } - - this.name = name; - - try { - this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING); - } catch (UnsupportedEncodingException usee) { - this.nameBytes = name.getBytes(); - log.warn( - "Constructor:: UnsupportedEncodingException translating the name " - + name); - } - } - - /** - * Sets the image size parameters - * resolution, hsize and vsize. - * @param hresol The horizontal resolution of the image. - * @param vresol The vertical resolution of the image. - * @param hsize The horizontal size of the image. - * @param vsize The vertival size of the image. - */ - public void setImageSize(int hresol, int vresol, int hsize, int vsize) { - if (imageContent == null) { - imageContent = new ImageContent(); - } - imageContent.setImageSize(hresol, vresol, hsize, vsize); - } - - /** - * Sets the image encoding. - * @param encoding The image encoding. - */ - public void setImageEncoding(byte encoding) { - if (imageContent == null) { - imageContent = new ImageContent(); - } - imageContent.setImageEncoding(encoding); - } - - /** - * Sets the image compression. - * @param compression The image compression. - */ - public void setImageCompression(byte compression) { - if (imageContent == null) { - imageContent = new ImageContent(); - } - imageContent.setImageCompression(compression); - } - - /** - * Sets the image IDE size. - * @param size The IDE size. - */ - public void setImageIDESize(byte size) { - if (imageContent == null) { - imageContent = new ImageContent(); - } - imageContent.setImageIDESize(size); - } - - /** - * Sets the image IDE color model. - * @param colorModel the IDE color model. - */ - public void setImageIDEColorModel(byte colorModel) { - if (imageContent == null) { - imageContent = new ImageContent(); - } - imageContent.setImageIDEColorModel(colorModel); - } - - /** - * Set the data of the image. - * @param data the image data - */ - public void setImageData(byte[] data) { - if (imageContent == null) { - imageContent = new ImageContent(); - } - imageContent.setImageData(data); - } - - /** - * Accessor method to write the AFP datastream for the Image Segment - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception occurred - */ - public void writeDataStream(OutputStream os) throws IOException { - - writeStart(os); - - if (imageContent != null) { - imageContent.writeDataStream(os); - } - - writeEnd(os); - - } - - /** - * Helper method to write the start of the Image Segment. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[] { - 0x70, // ID - 0x04, // Length - 0x00, // Name byte 1 - 0x00, // Name byte 2 - 0x00, // Name byte 3 - 0x00, // Name byte 4 - }; - - for (int i = 0; i < nameBytes.length; i++) { - - data[2 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the Image Segment. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) throws IOException { - - byte[] data = new byte[] { - 0x71, // ID - 0x00, // Length - }; - os.write(data); - } -} diff --git a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java b/src/java/org/apache/fop/render/afp/modca/IncludeObject.java deleted file mode 100644 index 890fdcd9d..000000000 --- a/src/java/org/apache/fop/render/afp/modca/IncludeObject.java +++ /dev/null @@ -1,171 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; - -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * An Include Object structured field references an object on a page or overlay. - * It optionally contains parameters that identify the object and that specify - * presentation parameters such as object position, size, orientation, mapping, - * and default color. - * <p> - * Where the presentation parameters conflict with parameters specified in the - * object's environment group (OEG), the parameters in the Include Object - * structured field override. If the referenced object is a page segment, the - * IOB parameters override the corresponding environment group parameters on all - * data objects in the page segment. - * </p> - */ -public class IncludeObject extends AbstractNamedAFPObject { - - /** - * The object type - */ - private byte objectType = (byte) 0x92; - - /** - * The orientation on the include object - */ - private int orientation = 0; - - /** - * Constructor for the include object with the specified name, the name must - * be a fixed length of eight characters and is the name of the referenced - * object. - * - * @param name - * the name of the image - */ - public IncludeObject(String name) { - - super(name); - objectType = (byte) 0xFB; - - } - - /** - * Sets the orientation to use for the Include Object. - * - * @param orientation - * The orientation (0,90, 180, 270) - */ - public void setOrientation(int orientation) { - - if (orientation == 0 || orientation == 90 || orientation == 180 - || orientation == 270) { - this.orientation = orientation; - } else { - throw new IllegalArgumentException( - "The orientation must be one of the values 0, 90, 180, 270"); - } - - } - - /** - * Accessor method to write the AFP datastream for the Include Object - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = new byte[37]; - - data[0] = 0x5A; - - // Set the total record length - byte[] rl1 = BinaryUtils.convert(36, 2); //Ignore first byte - data[1] = rl1[0]; - data[2] = rl1[1]; - - // Structured field ID for a IOB - data[3] = (byte) 0xD3; - data[4] = (byte) 0xAF; - data[5] = (byte) 0xC3; - - data[6] = 0x00; // Reserved - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - data[9 + i] = nameBytes[i]; - } - - data[17] = 0x00; - data[18] = objectType; - - // XoaOset - data[20] = (byte) 0xFF; - data[21] = (byte) 0xFF; - data[22] = (byte) 0xFF; - - // YoaOset - data[23] = (byte) 0xFF; - data[24] = (byte) 0xFF; - data[25] = (byte) 0xFF; - - switch (orientation) { - case 90: - data[26] = 0x2D; - data[27] = 0x00; - data[28] = 0x5A; - data[29] = 0x00; - break; - case 180: - data[26] = 0x5A; - data[27] = 0x00; - data[28] = (byte) 0x87; - data[29] = 0x00; - break; - case 270: - data[26] = (byte) 0x87; - data[27] = 0x00; - data[28] = 0x00; - data[29] = 0x00; - break; - default: - data[26] = 0x00; - data[27] = 0x00; - data[28] = 0x2D; - data[29] = 0x00; - break; - } - - // XocaOset - data[30] = (byte) 0xFF; - data[31] = (byte) 0xFF; - data[32] = (byte) 0xFF; - - // YocaOset - data[33] = (byte) 0xFF; - data[34] = (byte) 0xFF; - data[35] = (byte) 0xFF; - - data[36] = 0x01; - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java deleted file mode 100644 index 561c8c6fe..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java +++ /dev/null @@ -1,102 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * The Object Area Descriptor structured field specifies the size and attributes - * of an object area presentation space. - * - */ -public class ObjectAreaDescriptor extends AbstractDescriptor { - - /** - * Construct an object area descriptor for the specified object width - * and object height. - * @param width The page width. - * @param height The page height. - * @param widthResolution The page width resolution. - * @param heightResolution The page height resolution. - */ - public ObjectAreaDescriptor(int width, int height, int widthResolution, int heightResolution) { - super(width, height, widthResolution, heightResolution); - } - - /** - * Accessor method to write the AFP datastream for the Object Area Descriptor - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = new byte[29]; - data[0] = 0x5A; - - byte[] len = BinaryUtils.convert(data.length - 1, 2); - data[1] = len[0]; // Length - data[2] = len[1]; - - data[3] = (byte) 0xD3; - data[4] = (byte) 0xA6; - data[5] = (byte) 0x6B; - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - data[9] = 0x03; // Triplet length - data[10] = 0x43; // tid = Descriptor Position Triplet - data[11] = 0x01; // DesPosId = 1 - data[12] = 0x08; // Triplet length - data[13] = 0x4B; // tid = Measurement Units Triplet - data[14] = 0x00; // XaoBase = 10 inches - data[15] = 0x00; // YaoBase = 10 inches - - // XaoUnits - byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2); - data[16] = xdpi[0]; - data[17] = xdpi[1]; - - // YaoUnits - byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2); - data[18] = ydpi[0]; - data[19] = ydpi[1]; - - data[20] = 0x09; // Triplet length - data[21] = 0x4C; // tid = Object Area Size - data[22] = 0x02; // Size Type - - byte[] x = BinaryUtils.convert(width, 3); - data[23] = x[0]; - data[24] = x[1]; - data[25] = x[2]; - - byte[] y = BinaryUtils.convert(height, 3); - data[26] = y[0]; - data[27] = y[1]; - data[28] = y[2]; - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java deleted file mode 100644 index e500c1269..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaPosition.java +++ /dev/null @@ -1,112 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; -import org.apache.fop.render.afp.tools.BinaryUtils; - -/** - * The Object Area Position structured field specifies the origin and - * orientation of the object area, and the origin and orientation of the - * object content within the object area. - */ -public class ObjectAreaPosition extends AbstractAFPObject { - - private int _x = 0; - private int _y = 0; - private int _rot = 0; - - /** - * Construct an object area position for the specified object y, y position. - * @param x The x coordinate. - * @param y The y coordinate. - * @param rotation The coordinate system rotation (must be 0, 90, 180, 270). - */ - public ObjectAreaPosition(int x, int y, int rotation) { - - _x = x; - _y = y; - _rot = rotation; - } - - /** - * Accessor method to write the AFP datastream for the Object Area Position - * @param os The stream to write to - * @throws java.io.IOException - */ - public void writeDataStream(OutputStream os) - throws IOException { - - byte[] data = new byte[] { - 0x5A, - 0x00, // Length - 0x20, // Length - (byte) 0xD3, - (byte) 0xAC, - (byte) 0x6B, - 0x00, // Flags - 0x00, // Reserved - 0x00, // Reserved - 0x01, // OAPosID = 1 - 0x17, // RGLength = 23 - 0x00, // XoaOSet - 0x00, - 0x00, - 0x00, // YoaOSet - 0x00, - 0x00, - (byte)(_rot / 2), // XoaOrent - 0x00, - (byte)(_rot / 2 + 45), // YoaOrent - 0x00, - 0x00, // Reserved - 0x00, // XocaOSet - 0x00, - 0x00, - 0x00, // YocaOSet - 0x00, - 0x00, - 0x00, // XocaOrent - 0x00, - 0x2D, // YocaOrent - 0x00, - 0x01, // RefCSys - }; - - byte[] l = BinaryUtils.convert(data.length - 1, 2); - data[1] = l[0]; - data[2] = l[1]; - - byte[] x = BinaryUtils.convert(_x, 3); - data[11] = x[0]; - data[12] = x[1]; - data[13] = x[2]; - - byte[] y = BinaryUtils.convert(_y, 3); - data[14] = y[0]; - data[15] = y[1]; - data[16] = y[2]; - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java b/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java deleted file mode 100644 index d6b029122..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ObjectEnvironmentGroup.java +++ /dev/null @@ -1,198 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; - - -/** - * An Object Environment Group (OEG) may be associated with an object and is contained - * within the object's begin-end envelope. - * The object environment group defines the object's origin and orientation on the page, - * and can contain font and color attribute table information. The scope of an object - * environment group is the scope of its containing object. - * - * An application that creates a data-stream document may omit some of the parameters - * normally contained in the object environment group, or it may specify that one or - * more default values are to be used. - */ -public final class ObjectEnvironmentGroup extends AbstractNamedAFPObject { - - /** - * Default name for the object environment group - */ - private static final String DEFAULT_NAME = "OEG00001"; - - /** - * The ObjectAreaDescriptor for the object environment group - */ - private ObjectAreaDescriptor objectAreaDescriptor = null; - - /** - * The ObjectAreaPosition for the object environment group - */ - private ObjectAreaPosition objectAreaPosition = null; - - /** - * The ImageDataDescriptor for the object environment group - */ - private ImageDataDescriptor imageDataDescriptor = null; - - /** - * Default constructor for the ObjectEnvironmentGroup. - */ - public ObjectEnvironmentGroup() { - - this(DEFAULT_NAME); - - } - - /** - * Constructor for the ObjectEnvironmentGroup, this takes a - * name parameter which must be 8 characters long. - * @param name the object environment group name - */ - public ObjectEnvironmentGroup(String name) { - - super(name); - - } - - /** - * Sets the object area parameters. - * @param x the x position of the object - * @param y the y position of the object - * @param width the object width - * @param height the object height - * @param rotation the object orientation - * @param widthResolution the object resolution width - * @param heightResolution the object resolution height - */ - public void setObjectArea(int x, int y, int width, int height, int rotation, - int widthResolution, int heightResolution) { - - objectAreaDescriptor = new ObjectAreaDescriptor(width, height, - widthResolution, heightResolution); - objectAreaPosition = new ObjectAreaPosition(x, y, rotation); - - } - - /** - * Set the dimensions of the image. - * @param xresol the x resolution of the image - * @param yresol the y resolution of the image - * @param width the image width - * @param height the image height - */ - public void setImageData(int xresol, int yresol, int width, int height) { - imageDataDescriptor = new ImageDataDescriptor(xresol, yresol, width, height); - } - - /** - * Accessor method to obtain write the AFP datastream for - * the object environment group. - * @param os The stream to write to - * @throws java.io.IOException throw if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - - writeStart(os); - - objectAreaDescriptor.writeDataStream(os); - - objectAreaPosition.writeDataStream(os); - - if (imageDataDescriptor != null) { - imageDataDescriptor.writeDataStream(os); - } - - writeEnd(os); - - } - - /** - * Helper method to write the start of the object environment group. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[] { - 0x5A, // Structured field identifier - 0x00, // Length byte 1 - 0x10, // Length byte 2 - (byte) 0xD3, // Structured field id byte 1 - (byte) 0xA8, // Structured field id byte 2 - (byte) 0xC7, // Structured field id byte 3 - 0x00, // Flags - 0x00, // Reserved - 0x00, // Reserved - 0x00, // Name - 0x00, // - 0x00, // - 0x00, // - 0x00, // - 0x00, // - 0x00, // - 0x00, // - }; - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the object environment group. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xC7; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/Overlay.java b/src/java/org/apache/fop/render/afp/modca/Overlay.java deleted file mode 100644 index 3a4cdfb11..000000000 --- a/src/java/org/apache/fop/render/afp/modca/Overlay.java +++ /dev/null @@ -1,139 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * An overlay is a MO:DCA-P resource object. - * - * It may be stored in an external resource library or it may be - * carried in a resource group. An overlay is similar to a page in - * that it defines its own environment and carries the same data objects. - */ -public class Overlay extends AbstractPageObject { - - /** - * Construct a new overlay object for the specified name argument, the overlay - * name should be an 8 character identifier. - * - * @param name - * the name of the page. - * @param width - * the width of the page. - * @param height - * the height of the page. - * @param rotation - * the rotation of the page. - * @param widthResolution - * the width resolution of the page. - * @param heightResolution - * the height resolution of the page. - */ - public Overlay(String name, int width, int height, int rotation, - int widthResolution, int heightResolution) { - - super(name, width, height, rotation, widthResolution, heightResolution); - - } - - /** - * Accessor method to write the AFP datastream for the overlay. - * - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - activeEnvironmentGroup.writeDataStream(os); - - writeObjectList(segments, os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the overlay. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xDF; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the overlay. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xDF; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -} diff --git a/src/java/org/apache/fop/render/afp/modca/PageGroup.java b/src/java/org/apache/fop/render/afp/modca/PageGroup.java deleted file mode 100644 index 0b40a83c5..000000000 --- a/src/java/org/apache/fop/render/afp/modca/PageGroup.java +++ /dev/null @@ -1,208 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * A page group is used in the data stream to define a named, logical grouping - * of sequential pages. Page groups are delimited by begin-end structured fields - * that carry the name of the page group. Page groups are defined so that the - * pages that comprise the group can be referenced or processed as a single - * entity. Page groups are often processed in stand-alone fashion; that is, they - * are indexed, retrieved, and presented outside the context of the containing - * document. - * - * @author <a href="mailto:pete@townsend.uk.com">Pete Townsend </a> - */ -public class PageGroup extends AbstractNamedAFPObject { - - /** - * The pages contained within this group - */ - private List objects = new ArrayList(); - - /** - * The tag logical elements contained within this group - */ - private List tagLogicalElements = new ArrayList(); - - /** - * The page state - */ - private boolean complete = false; - - /** - * Constructor for the PageGroup. - * - * @param name - * the name of the page group - */ - public PageGroup(String name) { - - super(name); - - } - - /** - * Adds a page object to the group. - * - * @param page - * the page object to add - */ - public void addPage(PageObject page) { - - if (!objects.contains(page)) { - objects.add(page); - } - - } - - /** - * @return the name of the page group - */ - public String getName() { - return name; - } - - /** - * Creates a TagLogicalElement on the page. - * - * @param name - * the name of the tag - * @param value - * the value of the tag - */ - public void createTagLogicalElement(String name, String value) { - - TagLogicalElement tle = new TagLogicalElement(name, value); - tagLogicalElements.add(tle); - - } - - /** - * Creates an InvokeMediaMap on the page. - * - * @param name - * the name of the media map - */ - public void createInvokeMediumMap(String name) { - - InvokeMediumMap imm = new InvokeMediumMap(name); - objects.add(imm); - - } - - /** - * Method to mark the end of the page group. - */ - public void endPageGroup() { - - complete = true; - - } - - /** - * Returns an indication if the page group is complete - * @return whether or not this page group is complete or not - */ - public boolean isComplete() { - return complete; - } - - /** - * Accessor method to write the AFP datastream for the page group. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the page group. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xAD; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the page group. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xAD; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java deleted file mode 100644 index 5b9a00a89..000000000 --- a/src/java/org/apache/fop/render/afp/modca/PageObject.java +++ /dev/null @@ -1,191 +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.render.afp.modca; -import java.io.IOException; -import java.io.OutputStream; - - - -/** - * Pages contain the data objects that comprise a presentation document. Each - * page has a set of data objects associated with it. Each page within a - * document is independent from any other page, and each must establish its own - * environment parameters. - * - * The page is the level in the document component hierarchy that is used for - * printing or displaying a document's content. The data objects contained in - * the page envelope in the data stream are presented when the page is - * presented. Each data object has layout information associated with it that - * directs the placement and orientation of the data on the page. In addition, - * each page contains layout information that specifies the measurement units, - * page width, and page depth. - * - * A page is initiated by a begin page structured field and terminated by an end - * page structured field. Structured fields that define objects and active - * environment groups or that specify attributes of the page may be encountered - * in page state. - * - */ -public class PageObject extends AbstractPageObject { - - /** - * The resource group object - */ - private ResourceGroup resourceGroup = null; - - /** - * Construct a new page object for the specified name argument, the page - * name should be an 8 character identifier. - * - * @param name - * the name of the page. - * @param width - * the width of the page. - * @param height - * the height of the page. - * @param rotation - * the rotation of the page. - * @param widthResolution - * the width resolution of the page. - * @param heightResolution - * the height resolution of the page. - */ - public PageObject(String name, int width, int height, int rotation, - int widthResolution, int heightResolution) { - - super(name, width, height, rotation, widthResolution, heightResolution); - - } - - /** - * Adds an overlay to the page resources - * @param overlay the overlay to add - */ - public void addOverlay(Overlay overlay) { - if (resourceGroup == null) { - resourceGroup = new ResourceGroup(); - } - resourceGroup.addOverlay(overlay); - } - - /** - * Creates an IncludePageOverlay on the page. - * - * @param name - * the name of the overlay - * @param x - * the x position of the overlay - * @param y - * the y position of the overlay - * @param orientation - * the orientation required for the overlay - */ - public void createIncludePageOverlay(String name, int x, int y, int orientation) { - - IncludePageOverlay ipo = new IncludePageOverlay(name, x, y, orientation); - objects.add(ipo); - - } - - /** - * Accessor method to write the AFP datastream for the page. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - if (resourceGroup != null) { - resourceGroup.writeDataStream(os); - } - - activeEnvironmentGroup.writeDataStream(os); - - writeObjectList(segments, os); - - writeObjectList(tagLogicalElements, os); - - writeObjectList(objects, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the page. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xAF; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the page. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xAF; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java deleted file mode 100644 index c0f06439e..000000000 --- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java +++ /dev/null @@ -1,337 +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.render.afp.modca; - -import java.awt.Color; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; - -/** - * The Presentation Text object is the data object used in document processing - * environments for representing text which has been prepared for presentation. - * Text, as used here, means an ordered string of characters, such as graphic - * symbols, numbers, and letters, that are suitable for the specific purpose of - * representing coherent information. Text which has been prepared for - * presentation has been reduced to a primitive form through explicit - * specification of the characters and their placement in the presentation - * space. Control sequences which designate specific control functions may be - * embedded within the text. These functions extend the primitive form by - * applying specific characteristics to the text when it is presented. The - * collection of the graphic characters and control codes is called Presentation - * Text, and the object that contains the Presentation Text is called the - * PresentationText object. - * - */ -public class PresentationTextObject extends AbstractNamedAFPObject { - - /** - * Default name for the presentation text object - */ - private static final String DEFAULT_NAME = "PTO00001"; - - private PresentationTextData currentPresentationTextData = null; - - private ArrayList presentationTextData = new ArrayList(); - - /** - * Default constructor for the PresentationTextObject - */ - public PresentationTextObject() { - - this(DEFAULT_NAME); - - } - - /** - * Construct a new PresentationTextObject for the specified name argument, - * the name should be an 8 character identifier. - * @param name the name of this presentation object - */ - public PresentationTextObject(String name) { - - super(name); - - } - - /** - * Create the presentation text data for the byte array of data. - * - * @param fontNumber - * The font resource identifier. - * @param x - * The x coordinate for the text data. - * @param y - * The y coordinate for the text data. - * @param col - * The text color. - * @param vsci - * The variable space character increment. - * @param ica - * The inter character increment. - * @param data - * The text data to be created. - */ - public void createTextData(int fontNumber, int x, int y, Color col, - int vsci, int ica, byte[] data) { - - // Use a default orientation of zero - createTextData(fontNumber, x, y, 0, col, vsci, ica, data); - - } - - /** - * Create the presentation text data for the byte array of data. - * - * @param fontNumber - * The font resource identifier. - * @param x - * The x coordinate for the text data. - * @param y - * The y coordinate for the text data. - * @param orientation - * The orientation of the text data. - * @param col - * The text color. - * @param vsci - * The variable space character increment. - * @param ica - * The inter character adjustment. - * @param data - * The text data to be created. - */ - public void createTextData(int fontNumber, int x, int y, int orientation, - Color col, int vsci, int ica, byte[] data) { - - if (currentPresentationTextData == null) { - startPresentationTextData(); - } - - try { - - currentPresentationTextData.createTextData(fontNumber, x, y, - orientation, col, vsci, ica, data); - - } catch (MaximumSizeExceededException msee) { - - endPresentationTextData(); - createTextData(fontNumber, x, y, orientation, col, vsci, ica, data); - - } - - } - - /** - * Drawing of lines using the starting and ending coordinates, thickness. - * - * @param x1 - * The first x coordinate of the line. - * @param y1 - * The first y coordinate of the line. - * @param x2 - * The second x coordinate of the line. - * @param y2 - * The second y coordinate of the line. - * @param thickness - * The thickness of the line. - * @param col - * The text color. - */ - public void createLineData(int x1, int y1, int x2, int y2, int thickness, Color col) { - // Default orientation - createLineData(x1, y1, x2, y2, thickness, 0, col); - } - - /** - * Drawing of lines using the starting and ending coordinates, thickness and - * orientation arguments. - * - * @param x1 - * The first x coordinate of the line. - * @param y1 - * The first y coordinate of the line. - * @param x2 - * The second x coordinate of the line. - * @param y2 - * The second y coordinate of the line. - * @param thickness - * The thickness of the line. - * @param orientation - * The orientation of the line. - * @param col - * The text color. - */ - public void createLineData(int x1, int y1, int x2, int y2, int thickness, - int orientation, Color col) { - - if (currentPresentationTextData == null) { - startPresentationTextData(); - } - - try { - - currentPresentationTextData.createLineData(x1, y1, x2, y2, - thickness, orientation, col); - - } catch (MaximumSizeExceededException msee) { - - endPresentationTextData(); - createLineData(x1, y1, x2, y2, thickness, orientation, col); - - } - - } - - /** - * Helper method to mark the start of the presentation text data - */ - private void startPresentationTextData() { - - if (presentationTextData.size() == 0) { - currentPresentationTextData = new PresentationTextData(true); - } else { - currentPresentationTextData = new PresentationTextData(); - } - - presentationTextData.add(currentPresentationTextData); - - } - - /** - * Helper method to mark the end of the presentation text data - */ - private void endPresentationTextData() { - - currentPresentationTextData = null; - - } - - /** - * Accessor method to write the AFP datastream for the PresentationTextObject. - * @param os The stream to write to - * @throws java.io.IOException thrown if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(presentationTextData, os); - - writeEnd(os); - - } - - /** - * Returns the name of this presentation text object - * @return the name of this presentation text object - */ - public String getName() { - - return name; - - } - - /** - * Helper method to write the start of the presenation text object. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0x9B; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the presenation text object. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0x9B; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * A control sequence is a sequence of bytes that specifies a control - * function. A control sequence consists of a control sequence introducer - * and zero or more parameters. The control sequence can extend multiple - * presentation text data objects, but must eventually be terminated. This - * method terminates the control sequence. - */ - public void endControlSequence() { - - if (currentPresentationTextData == null) { - startPresentationTextData(); - } - - try { - - currentPresentationTextData.endControlSequence(); - - } catch (MaximumSizeExceededException msee) { - - endPresentationTextData(); - endControlSequence(); - - } - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java b/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java deleted file mode 100644 index 07043dcf1..000000000 --- a/src/java/org/apache/fop/render/afp/modca/ResourceGroup.java +++ /dev/null @@ -1,154 +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.render.afp.modca; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -/** - * A Resource Group contains a set of overlays. - */ -public final class ResourceGroup extends AbstractNamedAFPObject { - - /** - * Default name for the resource group - */ - private static final String DEFAULT_NAME = "RG000001"; - - - /** - * The overlays contained in this resource group - */ - private List overlays = new ArrayList(); - - /** - * Default constructor - */ - public ResourceGroup() { - - this(DEFAULT_NAME); - - } - - /** - * Constructor for the ResourceGroup, this takes a - * name parameter which must be 8 characters long. - * @param name the resource group name - */ - public ResourceGroup(String name) { - - super(name); - - } - - /** - * Adds an overlay to the resource group - * @param overlay the overlay to add - */ - public void addOverlay(Overlay overlay) { - overlays.add(overlay); - } - - /** - * Returns the list of overlays - * @return the list of overlays - */ - public List getOverlays() { - return overlays; - } - - /** - * Accessor method to obtain write the AFP datastream for - * the resource group. - * @param os The stream to write to - * @throws java.io.IOException if an I/O exception of some sort has occurred - */ - public void writeDataStream(OutputStream os) - throws IOException { - - writeStart(os); - - writeObjectList(overlays, os); - - writeEnd(os); - - } - - /** - * Helper method to write the start of the resource group. - * @param os The stream to write to - */ - private void writeStart(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA8; // Structured field id byte 2 - data[5] = (byte) 0xC6; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - - /** - * Helper method to write the end of the resource group. - * @param os The stream to write to - */ - private void writeEnd(OutputStream os) - throws IOException { - - byte[] data = new byte[17]; - - data[0] = 0x5A; // Structured field identifier - data[1] = 0x00; // Length byte 1 - data[2] = 0x10; // Length byte 2 - data[3] = (byte) 0xD3; // Structured field id byte 1 - data[4] = (byte) 0xA9; // Structured field id byte 2 - data[5] = (byte) 0xC6; // Structured field id byte 3 - data[6] = 0x00; // Flags - data[7] = 0x00; // Reserved - data[8] = 0x00; // Reserved - - for (int i = 0; i < nameBytes.length; i++) { - - data[9 + i] = nameBytes[i]; - - } - - os.write(data); - - } - -}
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/afp/package.html b/src/java/org/apache/fop/render/afp/package.html new file mode 100644 index 000000000..3e611d964 --- /dev/null +++ b/src/java/org/apache/fop/render/afp/package.html @@ -0,0 +1,23 @@ +<!-- + 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.html 643433 2008-04-01 15:08:24Z acumiskey $ --> +<HTML> +<TITLE>org.apache.fop.render.afp Package</TITLE> +<BODY> +<P>An AFP Renderer implementation and supporting classes.</P> +</BODY> +</HTML>
\ No newline at end of file diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index f67c2c7a2..5b4c6b13a 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -149,14 +149,11 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { Rectangle2D bounds = getPageViewport(pageNum).getViewArea(); pageWidth = (int) Math.round(bounds.getWidth() / 1000f); pageHeight = (int) Math.round(bounds.getHeight() / 1000f); - double scaleX = scaleFactor + double scale = scaleFactor * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) / userAgent.getTargetPixelUnitToMillimeter(); - double scaleY = scaleFactor - * (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION) - / userAgent.getTargetPixelUnitToMillimeter(); - int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5); - int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5); + int bitmapWidth = (int) ((pageWidth * scale) + 0.5); + int bitmapHeight = (int) ((pageHeight * scale) + 0.5); return new Dimension(bitmapWidth, bitmapHeight); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index e3f79dea2..54da30436 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -135,7 +135,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** The current state, holds a Graphics2D and its context */ protected Java2DGraphicsState state; - private Stack stateStack = new Stack(); + private final Stack stateStack = new Stack(); /** true if the renderer has finished rendering all the pages */ private boolean renderingDone; @@ -146,9 +146,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem public Java2DRenderer() { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setUserAgent(FOUserAgent foUserAgent) { super.setUserAgent(foUserAgent); userAgent.setRendererOverride(this); // for document regeneration @@ -164,9 +162,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem return userAgent; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void setupFontInfo(FontInfo inFontInfo) { //Don't call super.setupFontInfo() here! Java2D needs a special font setup // create a temp Image to test font metrics on @@ -442,16 +438,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem state.transform(new AffineTransform(CTMHelper.toPDFArray(ctm))); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void endVParea() { restoreGraphicsState(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected List breakOutOfStateStack() { log.debug("Block.FIXED --> break out"); List breakOutList; @@ -464,10 +456,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem return breakOutList; } - /** - * {@inheritDoc} - * java.util.List) - */ + /** {@inheritDoc} */ protected void restoreStateStackAfterBreakOut(List breakOutList) { log.debug("Block.FIXED --> restoring context after break-out"); @@ -479,16 +468,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void updateColor(Color col, boolean fill) { state.updateColor(col); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void clip() { if (currentPath == null) { throw new IllegalStateException("No current path available!"); @@ -497,16 +482,12 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem currentPath = null; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void closePath() { currentPath.closePath(); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void lineTo(float x, float y) { if (currentPath == null) { currentPath = new GeneralPath(); @@ -514,9 +495,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem currentPath.lineTo(x, y); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void moveTo(float x, float y) { if (currentPath == null) { currentPath = new GeneralPath(); @@ -524,23 +503,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem currentPath.moveTo(x, y); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void clipRect(float x, float y, float width, float height) { state.updateClip(new Rectangle2D.Float(x, y, width, height)); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void fillRect(float x, float y, float width, float height) { state.getGraph().fill(new Rectangle2D.Float(x, y, width, height)); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz, boolean startOrBefore, int style, Color col) { Graphics2D g2d = state.getGraph(); @@ -711,9 +684,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem } } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderText(TextArea text) { renderInlineAreaBackAndBorders(text); @@ -895,18 +866,20 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem super.renderLeader(area); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public void renderImage(Image image, Rectangle2D pos) { // endTextObject(); String url = image.getURL(); drawImage(url, pos); } - /** - * {@inheritDoc} - */ + private static final ImageFlavor[] FLAVOURS = new ImageFlavor[] + {ImageFlavor.GRAPHICS2D, + ImageFlavor.BUFFERED_IMAGE, + ImageFlavor.RENDERED_IMAGE, + ImageFlavor.XML_DOM}; + + /** {@inheritDoc} */ protected void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) { int x = currentIPPosition + (int)Math.round(pos.getX()); @@ -918,14 +891,9 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem try { ImageSessionContext sessionContext = getUserAgent().getImageSessionContext(); info = manager.getImageInfo(uri, sessionContext); - final ImageFlavor[] flavors = new ImageFlavor[] - {ImageFlavor.GRAPHICS2D, - ImageFlavor.BUFFERED_IMAGE, - ImageFlavor.RENDERED_IMAGE, - ImageFlavor.XML_DOM}; Map hints = ImageUtil.getDefaultHints(sessionContext); org.apache.xmlgraphics.image.loader.Image img = manager.getImage( - info, flavors, hints, sessionContext); + info, FLAVOURS, hints, sessionContext); if (img instanceof ImageGraphics2D) { ImageGraphics2D imageG2D = (ImageGraphics2D)img; int width = (int)pos.getWidth(); diff --git a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java index 12b269a44..ba5c86059 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java +++ b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java @@ -20,20 +20,21 @@ package org.apache.fop.render.java2d; import java.awt.geom.AffineTransform; - -import org.w3c.dom.Document; +import java.io.IOException; +import java.util.Map; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; +import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.w3c.dom.Document; /** * Java2D XML handler for SVG (uses Apache Batik). @@ -66,6 +67,11 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler pdfi.height = ((Integer)context.getProperty(HEIGHT)).intValue(); pdfi.currentXPosition = ((Integer)context.getProperty(XPOS)).intValue(); pdfi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue(); + Map foreign = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); + if (foreign != null + && BITMAP.equalsIgnoreCase((String)foreign.get(CONVERSION_MODE))) { + pdfi.paintAsBitmap = true; + } return pdfi; } @@ -83,6 +89,7 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler public int currentXPosition; /** see Java2D_YPOS */ public int currentYPosition; + public boolean paintAsBitmap; /** {@inheritDoc} */ public String toString() { @@ -91,7 +98,8 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler + "width = " + width + ", " + "height = " + height + ", " + "currentXPosition = " + currentXPosition + ", " - + "currentYPosition = " + currentYPosition + "}"; + + "currentYPosition = " + currentYPosition + ", " + + "paintAsBitmap = " + paintAsBitmap + "}"; } } @@ -103,6 +111,18 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler log.debug("renderSVGDocument(" + context + ", " + doc + ", " + info + ")"); } + // fallback paint as bitmap + if (info.paintAsBitmap) { + try { + super.renderSVGDocument(context, doc); + } catch (IOException ioe) { + SVGEventProducer eventProducer = SVGEventProducer.Provider.get( + context.getUserAgent().getEventBroadcaster()); + eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc)); + } + return; + } + int x = info.currentXPosition; int y = info.currentYPosition; @@ -126,8 +146,8 @@ public class Java2DSVGHandler extends AbstractGenericSVGHandler float iw = (float) ctx.getDocumentSize().getWidth() * 1000f; float ih = (float) ctx.getDocumentSize().getHeight() * 1000f; - float w = (float) info.width; - float h = (float) info.height; + float w = info.width; + float h = info.height; AffineTransform origTransform = info.state.getGraph().getTransform(); diff --git a/src/java/org/apache/fop/render/pcl/PCLRenderer.java b/src/java/org/apache/fop/render/pcl/PCLRenderer.java index 5aad34391..5faeb834d 100644 --- a/src/java/org/apache/fop/render/pcl/PCLRenderer.java +++ b/src/java/org/apache/fop/render/pcl/PCLRenderer.java @@ -717,7 +717,7 @@ public class PCLRenderer extends PrintRenderer { public Dimension getImageSize() { return paintRect.getSize(); } - + }; g2a.paintImage(painter, rc, paintRect.x, paintRect.y, paintRect.width, paintRect.height); diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java index 2aa11227a..01d863e6a 100644 --- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java @@ -95,8 +95,8 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter { AffineTransform transform = new AffineTransform(); transform.translate(fx, fy); - pdfInfo.pdfState.concatenate(transform); - graphics.setPDFState(pdfInfo.pdfState); + pdfInfo.pdfPaintingState.concatenate(transform); + graphics.setPaintingState(pdfInfo.pdfPaintingState); graphics.setOutputStream(pdfInfo.outputStream); if (pdfInfo.paintAsBitmap) { diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java index f93ee5a97..6343d0c50 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandler.java @@ -23,36 +23,15 @@ import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; -import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.ImageFlavor; - import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.ImageHandler; import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.image.loader.Image; /** * This interface is used for handling all sorts of image type for PDF output. */ -public interface PDFImageHandler { - - /** - * Returns the priority for this image handler. A lower value means higher priority. This - * information is used to build the ordered/prioritized list of supported ImageFlavors for - * the PDF renderer. The built-in handlers use priorities between 100 and 999. - * @return a positive integer (>0) indicating the priority - */ - int getPriority(); - - /** - * Returns the {@link ImageFlavor}s supported by this instance - * @return the supported image flavors - */ - ImageFlavor[] getSupportedImageFlavors(); - - /** - * Returns the {@link Image} subclass supported by this instance. - * @return the Image type - */ - Class getSupportedImageClass(); +public interface PDFImageHandler extends ImageHandler { /** * Generates the PDF objects for the given {@link Image} instance. If the handler generates diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java index a58fe5922..3e4a9b354 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java @@ -23,13 +23,12 @@ import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; -import org.apache.fop.pdf.PDFXObject; -import org.apache.fop.render.RendererContext; - /** * PDFImageHandler implementation which handles Graphics2D images. */ diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java index 9f56ebfea..1ba498ff0 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java @@ -23,15 +23,14 @@ import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; -import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.ImageFlavor; -import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; - import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFImage; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; /** * PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4). diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java index f971a49ae..41a2d7565 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java @@ -23,15 +23,14 @@ import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; -import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.ImageFlavor; -import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; - import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFImage; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; /** * PDFImageHandler implementation which handles raw JPEG images. diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java index b664a0a24..1d4c733a3 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java @@ -19,171 +19,18 @@ package org.apache.fop.render.pdf; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.ImageFlavor; -import org.apache.xmlgraphics.util.Service; +import org.apache.fop.render.AbstractImageHandlerRegistry; /** * This class holds references to various image handlers used by the PDF renderer. It also * supports automatic discovery of additional handlers available through * the class path. */ -public class PDFImageHandlerRegistry { - - /** the logger */ - private static Log log = LogFactory.getLog(PDFImageHandlerRegistry.class); - - private static final Comparator HANDLER_COMPARATOR = new Comparator() { - public int compare(Object o1, Object o2) { - PDFImageHandler h1 = (PDFImageHandler)o1; - PDFImageHandler h2 = (PDFImageHandler)o2; - return h1.getPriority() - h2.getPriority(); - } - }; - - /** Map containing PDF image handlers for various MIME types */ - private Map handlers = new java.util.HashMap(); - /** List containing the same handlers as above but ordered by priority */ - private List handlerList = new java.util.LinkedList(); +public class PDFImageHandlerRegistry extends AbstractImageHandlerRegistry { - /** Sorted Set of registered handlers */ - private ImageFlavor[] supportedFlavors = new ImageFlavor[0]; - private int handlerRegistrations; - private int lastSync; - - /** - * Default constructor. - */ - public PDFImageHandlerRegistry() { - discoverHandlers(); - } - - /** - * Add an PDFImageHandler. The handler itself is inspected to find out what it supports. - * @param classname the fully qualified class name - */ - public void addHandler(String classname) { - try { - PDFImageHandler handlerInstance - = (PDFImageHandler)Class.forName(classname).newInstance(); - addHandler(handlerInstance); - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Could not find " - + classname); - } catch (InstantiationException e) { - throw new IllegalArgumentException("Could not instantiate " - + classname); - } catch (IllegalAccessException e) { - throw new IllegalArgumentException("Could not access " - + classname); - } catch (ClassCastException e) { - throw new IllegalArgumentException(classname - + " is not an " - + PDFImageHandler.class.getName()); - } + /** {@inheritDoc} */ + public Class getHandlerClass() { + return PDFImageHandler.class; } - /** - * Add an image handler. The handler itself is inspected to find out what it supports. - * @param handler the PDFImageHandler instance - */ - public synchronized void addHandler(PDFImageHandler handler) { - Class imageClass = handler.getSupportedImageClass(); - this.handlers.put(imageClass, handler); - - //Sorted insert - ListIterator iter = this.handlerList.listIterator(); - while (iter.hasNext()) { - PDFImageHandler h = (PDFImageHandler)iter.next(); - if (HANDLER_COMPARATOR.compare(handler, h) < 0) { - iter.previous(); - break; - } - } - iter.add(handler); - this.handlerRegistrations++; - } - - /** - * Returns an PDFImageHandler which handles an specific image type given the MIME type - * of the image. - * @param img the Image to be handled - * @return the PDFImageHandler responsible for handling the image or null if none is available - */ - public PDFImageHandler getHandler(Image img) { - return getHandler(img.getClass()); - } - - /** - * Returns an PDFImageHandler which handles an specific image type given the MIME type - * of the image. - * @param imageClass the Image subclass for which to get a handler - * @return the PDFImageHandler responsible for handling the image or null if none is available - */ - protected synchronized PDFImageHandler getHandler(Class imageClass) { - PDFImageHandler handler = null; - Class cl = imageClass; - while (cl != null) { - handler = (PDFImageHandler)handlers.get(cl); - if (handler != null) { - break; - } - cl = cl.getSuperclass(); - } - return handler; - } - - /** - * Returns the ordered array of supported image flavors. - * @return the array of image flavors - */ - public synchronized ImageFlavor[] getSupportedFlavors() { - if (this.lastSync != this.handlerRegistrations) { - //Extract all ImageFlavors into a single array - List flavors = new java.util.ArrayList(); - Iterator iter = this.handlerList.iterator(); - while (iter.hasNext()) { - ImageFlavor[] f = ((PDFImageHandler)iter.next()).getSupportedImageFlavors(); - for (int i = 0; i < f.length; i++) { - flavors.add(f[i]); - } - } - this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]); - this.lastSync = this.handlerRegistrations; - } - return this.supportedFlavors; - } - - /** - * Discovers PDFImageHandler implementations through the classpath and dynamically - * registers them. - */ - private void discoverHandlers() { - // add mappings from available services - Iterator providers = Service.providers(PDFImageHandler.class); - if (providers != null) { - while (providers.hasNext()) { - PDFImageHandler handler = (PDFImageHandler)providers.next(); - try { - if (log.isDebugEnabled()) { - log.debug("Dynamically adding PDFImageHandler: " - + handler.getClass().getName()); - } - addHandler(handler); - } catch (IllegalArgumentException e) { - log.error("Error while adding PDFImageHandler", e); - } - - } - } - } } diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java index 783cb225c..268ff8862 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java @@ -23,15 +23,14 @@ import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; -import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.ImageFlavor; -import org.apache.xmlgraphics.image.loader.impl.ImageRendered; - import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFImage; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.RendererContext; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; /** * PDFImageHandler implementation which handles RenderedImage instances. diff --git a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java index d111e733f..26ba83371 100644 --- a/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java +++ b/src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java @@ -24,14 +24,12 @@ import java.awt.Rectangle; import java.io.IOException; import java.util.Map; -import org.w3c.dom.Document; - +import org.apache.fop.pdf.PDFXObject; +import org.apache.fop.render.RendererContext; import org.apache.xmlgraphics.image.loader.Image; import org.apache.xmlgraphics.image.loader.ImageFlavor; import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; - -import org.apache.fop.pdf.PDFXObject; -import org.apache.fop.render.RendererContext; +import org.w3c.dom.Document; /** * PDFImageHandler implementation which handles XML-based images. diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java index 8c016198b..e31f1eaea 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java @@ -40,16 +40,6 @@ import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import org.apache.commons.io.IOUtils; - -import org.apache.xmlgraphics.image.loader.ImageException; -import org.apache.xmlgraphics.image.loader.ImageInfo; -import org.apache.xmlgraphics.image.loader.ImageManager; -import org.apache.xmlgraphics.image.loader.ImageSessionContext; -import org.apache.xmlgraphics.image.loader.util.ImageUtil; -import org.apache.xmlgraphics.xmp.Metadata; -import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter; -import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema; - import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; @@ -104,9 +94,9 @@ import org.apache.fop.pdf.PDFOutline; import org.apache.fop.pdf.PDFOutputIntent; import org.apache.fop.pdf.PDFPage; import org.apache.fop.pdf.PDFPageLabels; +import org.apache.fop.pdf.PDFPaintingState; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; import org.apache.fop.pdf.PDFTextUtil; import org.apache.fop.pdf.PDFXMode; @@ -114,9 +104,19 @@ import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; +import org.apache.fop.util.AbstractPaintingState; import org.apache.fop.util.CharUtilities; import org.apache.fop.util.ColorProfileUtil; import org.apache.fop.util.ColorUtil; +import org.apache.fop.util.AbstractPaintingState.AbstractData; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.util.ImageUtil; +import org.apache.xmlgraphics.xmp.Metadata; +import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter; +import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema; /** * Renderer that renders areas to PDF. @@ -250,8 +250,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** Optional URI to an output profile to be used. */ protected String outputProfileURI; - /** drawing state */ - protected PDFState currentState = null; + /** Painting state */ + protected PDFPaintingState paintingState = null; /** Text generation utility holding the current font status */ protected PDFTextUtil textutil; @@ -262,7 +262,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { protected Map filterMap; /** Image handler registry */ - private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry(); + private final PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry(); /** * create the PDF renderer @@ -519,7 +519,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { currentStream = null; currentContext = null; currentPage = null; - currentState = null; + paintingState = null; this.textutil = null; idPositions.clear(); @@ -640,7 +640,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ protected void saveGraphicsState() { endTextObject(); - currentState.push(); + paintingState.save(); currentStream.add("q\n"); } @@ -648,7 +648,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { endTextObject(); currentStream.add("Q\n"); if (popState) { - currentState.pop(); + paintingState.restore(); } } @@ -783,11 +783,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } }; - currentState = new PDFState(); + paintingState = new PDFPaintingState(); // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0, pageHeight / 1000f); - currentState.concatenate(basicPageTransform); + paintingState.concatenate(basicPageTransform); currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n"); super.renderPage(page); @@ -807,7 +807,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { protected void startVParea(CTM ctm, Rectangle2D clippingRect) { saveGraphicsState(); // Set the given CTM in the graphics state - currentState.concatenate( + paintingState.concatenate( new AffineTransform(CTMHelper.toPDFArray(ctm))); if (clippingRect != null) { @@ -828,7 +828,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** {@inheritDoc} */ protected void concatenateTransformationMatrix(AffineTransform at) { if (!at.isIdentity()) { - currentState.concatenate(at); + paintingState.concatenate(at); currentStream.add(CTMHelper.toPDFString(at, false) + " cm\n"); } } @@ -1018,7 +1018,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * @param width line width in points */ private void updateLineWidth(float width) { - if (currentState.setLineWidth(width)) { + if (paintingState.setLineWidth(width)) { //Only write if value has changed WRT the current line width currentStream.add(format(width) + " w\n"); } @@ -1069,10 +1069,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { /** * {@inheritDoc} */ - protected void fillRect(float x, float y, float w, float h) { - if (w != 0 && h != 0) { + protected void fillRect(float x, float y, float width, float height) { + if (width > 0 && height > 0) { currentStream.add(format(x) + " " + format(y) + " " - + format(w) + " " + format(h) + " re f\n"); + + format(width) + " " + format(height) + " re f\n"); } } @@ -1094,11 +1094,12 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { * @return the saved state stack to recreate later */ protected List breakOutOfStateStack() { +// return currentState.popAll(); List breakOutList = new java.util.ArrayList(); - PDFState.Data data; + AbstractPaintingState.AbstractData data; while (true) { - data = currentState.getData(); - if (currentState.pop() == null) { + data = paintingState.getData(); + if (paintingState.restore() == null) { break; } if (breakOutList.size() == 0) { @@ -1116,10 +1117,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { */ protected void restoreStateStackAfterBreakOut(List breakOutList) { comment("------ restoring context after break-out..."); - PDFState.Data data; +// currentState.pushAll(breakOutList); + AbstractData data; Iterator i = breakOutList.iterator(); while (i.hasNext()) { - data = (PDFState.Data)i.next(); + data = (AbstractData)i.next(); saveGraphicsState(); AffineTransform at = data.getTransform(); concatenateTransformationMatrix(at); @@ -1259,7 +1261,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { */ protected void saveAbsolutePosition(String id, int relativeIPP, int relativeBPP) { saveAbsolutePosition(id, currentPageRef, - relativeIPP, relativeBPP, currentState.getTransform()); + relativeIPP, relativeBPP, paintingState.getTransform()); } /** @@ -1283,8 +1285,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { bpp += currentBPPosition; } AffineTransform tf = positioning == Block.FIXED - ? currentState.getBaseTransform() - : currentState.getTransform(); + ? paintingState.getBaseTransform() + : paintingState.getTransform(); saveAbsolutePosition(id, currentPageRef, ipp, bpp, tf); } } @@ -1347,7 +1349,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { int bpp = currentBPPosition + ip.getOffset(); ipRect = new Rectangle2D.Float(ipp / 1000f, bpp / 1000f, ip.getIPD() / 1000f, ip.getBPD() / 1000f); - AffineTransform transform = currentState.getTransform(); + AffineTransform transform = paintingState.getTransform(); ipRect = transform.createTransformedShape(ipRect).getBounds2D(); factory = pdfDoc.getFactory(); @@ -1581,9 +1583,9 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } boolean update = false; if (fill) { - update = currentState.setBackColor(col); + update = paintingState.setBackColor(col); } else { - update = currentState.setColor(col); + update = paintingState.setColor(col); } if (update) { @@ -1656,7 +1658,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext); //First check for a dynamically registered handler - PDFImageHandler handler = imageHandlerRegistry.getHandler(img.getClass()); + PDFImageHandler handler + = (PDFImageHandler)imageHandlerRegistry.getHandler(img.getClass()); if (handler != null) { if (log.isDebugEnabled()) { log.debug("Using PDFImageHandler: " + handler.getClass().getName()); @@ -1695,6 +1698,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { this.pdfDoc.output(ostream); } catch (IOException ioe) { // ioexception will be caught later + log.error(ioe.getMessage()); } } @@ -1723,7 +1727,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { x, y, width, height, foreignAttributes); context.setProperty(PDFRendererContextConstants.PDF_DOCUMENT, pdfDoc); context.setProperty(PDFRendererContextConstants.OUTPUT_STREAM, ostream); - context.setProperty(PDFRendererContextConstants.PDF_STATE, currentState); + context.setProperty(PDFRendererContextConstants.PDF_PAINTING_STATE, paintingState); context.setProperty(PDFRendererContextConstants.PDF_PAGE, currentPage); context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext == null ? currentPage : currentContext); @@ -1743,7 +1747,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { public void renderLeader(Leader area) { renderInlineAreaBackAndBorders(area); - currentState.push(); + paintingState.save(); saveGraphicsState(); int style = area.getRuleStyle(); float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; @@ -1801,7 +1805,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer { } restoreGraphicsState(); - currentState.pop(); + paintingState.restore(); beginTextObject(); super.renderLeader(area); } diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java index 4ac16d725..8d1042f7f 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java @@ -42,6 +42,7 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { /** * Default constructor + * * @param userAgent user agent */ public PDFRendererConfigurator(FOUserAgent userAgent) { @@ -52,6 +53,7 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { * Configure the PDF renderer. * Get the configuration to be used for pdf stream filters, * fonts etc. + * * @param renderer pdf renderer * @throws FOPException fop exception */ @@ -79,7 +81,8 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { if (s != null) { pdfRenderer.setXMode(PDFXMode.valueOf(s)); } - Configuration encryptionParamsConfig = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false); + Configuration encryptionParamsConfig + = cfg.getChild(PDFRenderer.ENCRYPTION_PARAMS, false); if (encryptionParamsConfig != null) { PDFEncryptionParams encryptionParams = new PDFEncryptionParams(); Configuration ownerPasswordConfig = encryptionParamsConfig.getChild( @@ -124,15 +127,18 @@ public class PDFRendererConfigurator extends PrintRendererConfigurator { if (s != null) { pdfRenderer.setOutputProfileURI(s); } - Configuration disableColorSpaceConfig = cfg.getChild(PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); + Configuration disableColorSpaceConfig = cfg.getChild( + PDFRenderer.KEY_DISABLE_SRGB_COLORSPACE, false); if (disableColorSpaceConfig != null) { - pdfRenderer.disableSRGBColorSpace = disableColorSpaceConfig.getValueAsBoolean(false); + pdfRenderer.disableSRGBColorSpace + = disableColorSpaceConfig.getValueAsBoolean(false); } } } /** * Builds a filter map from an Avalon Configuration object. + * * @param cfg the Configuration object * @return Map the newly built filter map * @throws ConfigurationException if a filter list is defined twice diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java b/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java index de51aabc7..33888d442 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java @@ -29,8 +29,8 @@ public interface PDFRendererContextConstants extends RendererContextConstants { /** The PDF document that this image is being drawn into. */ String PDF_DOCUMENT = "pdfDoc"; - /** The current pdf state. */ - String PDF_STATE = "pdfState"; + /** The current PDF painting state. */ + String PDF_PAINTING_STATE = "pdfPaintingState"; /** The current PDF page for page renference and as a resource context. */ String PDF_PAGE = "pdfPage"; diff --git a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java index 864a82517..5d027aefe 100644 --- a/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java @@ -25,8 +25,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Map; -import org.w3c.dom.Document; - import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; @@ -35,16 +33,12 @@ import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.util.SVGConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.util.QName; - import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontInfo; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFPage; +import org.apache.fop.pdf.PDFPaintingState; import org.apache.fop.pdf.PDFResourceContext; -import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; @@ -55,6 +49,7 @@ import org.apache.fop.svg.PDFBridgeContext; import org.apache.fop.svg.PDFGraphics2D; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.w3c.dom.Document; /** * PDF XML handler for SVG (uses Apache Batik). @@ -78,7 +73,7 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler PDFInfo pdfi = new PDFInfo(); pdfi.pdfDoc = (PDFDocument)context.getProperty(PDF_DOCUMENT); pdfi.outputStream = (OutputStream)context.getProperty(OUTPUT_STREAM); - pdfi.pdfState = (PDFState)context.getProperty(PDF_STATE); + pdfi.pdfPaintingState = (PDFPaintingState)context.getProperty(PDF_PAINTING_STATE); pdfi.pdfPage = (PDFPage)context.getProperty(PDF_PAGE); pdfi.pdfContext = (PDFResourceContext)context.getProperty(PDF_CONTEXT); pdfi.currentStream = (PDFStream)context.getProperty(PDF_STREAM); @@ -91,9 +86,9 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler pdfi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue(); pdfi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION); Map foreign = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); - QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode"); + if (foreign != null - && "bitmap".equalsIgnoreCase((String)foreign.get(qName))) { + && BITMAP.equalsIgnoreCase((String)foreign.get(CONVERSION_MODE))) { pdfi.paintAsBitmap = true; } return pdfi; @@ -108,7 +103,7 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler /** see OUTPUT_STREAM */ public OutputStream outputStream; /** see PDF_STATE */ - public PDFState pdfState; + public PDFPaintingState pdfPaintingState; /** see PDF_PAGE */ public PDFPage pdfPage; /** see PDF_CONTEXT */ @@ -198,8 +193,8 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler float w = (float)ctx.getDocumentSize().getWidth() * 1000f; float h = (float)ctx.getDocumentSize().getHeight() * 1000f; - float sx = pdfInfo.width / (float)w; - float sy = pdfInfo.height / (float)h; + float sx = pdfInfo.width / w; + float sy = pdfInfo.height / h; //Scaling and translation for the bounding box of the image AffineTransform scaling = new AffineTransform( @@ -248,16 +243,16 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler pdfInfo.currentStream.add("%SVG start\n"); //Save state and update coordinate system for the SVG image - pdfInfo.pdfState.push(); - pdfInfo.pdfState.concatenate(imageTransform); + pdfInfo.pdfPaintingState.save(); + pdfInfo.pdfPaintingState.concatenate(imageTransform); //Now that we have the complete transformation matrix for the image, we can update the //transformation matrix for the AElementBridge. PDFAElementBridge aBridge = (PDFAElementBridge)ctx.getBridge( SVGDOMImplementation.SVG_NAMESPACE_URI, SVGConstants.SVG_A_TAG); - aBridge.getCurrentTransform().setTransform(pdfInfo.pdfState.getTransform()); + aBridge.getCurrentTransform().setTransform(pdfInfo.pdfPaintingState.getTransform()); - graphics.setPDFState(pdfInfo.pdfState); + graphics.setPaintingState(pdfInfo.pdfPaintingState); graphics.setOutputStream(pdfInfo.outputStream); try { root.paint(graphics); @@ -267,7 +262,7 @@ public class PDFSVGHandler extends AbstractGenericSVGHandler context.getUserAgent().getEventBroadcaster()); eventProducer.svgRenderingError(this, e, getDocumentURI(doc)); } - pdfInfo.pdfState.pop(); + pdfInfo.pdfPaintingState.restore(); renderer.restoreGraphicsState(); pdfInfo.currentStream.add("%SVG end\n"); } diff --git a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java index e5d8200b7..542a69a4a 100644 --- a/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/ps/PSGraphics2DAdapter.java @@ -33,6 +33,7 @@ import org.apache.xmlgraphics.util.QName; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.render.AbstractGraphics2DAdapter; +import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.render.RendererContext.RendererContextWrapper; diff --git a/src/java/org/apache/fop/render/ps/PSTextPainter.java b/src/java/org/apache/fop/render/ps/PSTextPainter.java index 31cb4b605..a318c6465 100644 --- a/src/java/org/apache/fop/render/ps/PSTextPainter.java +++ b/src/java/org/apache/fop/render/ps/PSTextPainter.java @@ -19,41 +19,35 @@ package org.apache.fop.render.ps; +import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.font.TextAttribute; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; -/* java.awt.Font is not imported to avoid confusion with - org.apache.fop.fonts.Font */ - +import java.io.IOException; import java.text.AttributedCharacterIterator; import java.text.CharacterIterator; -import java.awt.font.TextAttribute; -import java.awt.Shape; -import java.awt.Paint; -import java.awt.Stroke; -import java.awt.Color; -import java.io.IOException; -import java.util.List; import java.util.Iterator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.java2d.TextHandler; +import java.util.List; import org.apache.batik.dom.svg.SVGOMTextElement; -import org.apache.batik.gvt.text.Mark; -import org.apache.batik.gvt.TextPainter; import org.apache.batik.gvt.TextNode; -import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; -import org.apache.batik.gvt.text.TextPaintInfo; +import org.apache.batik.gvt.TextPainter; import org.apache.batik.gvt.font.GVTFontFamily; import org.apache.batik.gvt.renderer.StrokingTextPainter; - +import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; +import org.apache.batik.gvt.text.Mark; +import org.apache.batik.gvt.text.TextPaintInfo; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; + /** * Renders the attributed character iterator of a <tt>TextNode</tt>. @@ -74,8 +68,8 @@ public class PSTextPainter implements TextPainter { /** the logger for this class */ protected Log log = LogFactory.getLog(PSTextPainter.class); - private NativeTextHandler nativeTextHandler; - private FontInfo fontInfo; + private final NativeTextHandler nativeTextHandler; + private final FontInfo fontInfo; /** * Use the stroking text painter to get the bounds and shape. @@ -317,7 +311,7 @@ public class PSTextPainter implements TextPainter { } drawPrimitiveString(g2d, loc, font, txt, tx); - loc.setLocation(loc.getX() + (double)advance, loc.getY()); + loc.setLocation(loc.getX() + advance, loc.getY()); return loc; } @@ -422,7 +416,7 @@ public class PSTextPainter implements TextPainter { fStyle |= java.awt.Font.ITALIC; } return new java.awt.Font(font.getFontName(), fStyle, - (int)(font.getFontSize() / 1000)); + (font.getFontSize() / 1000)); } private float getStringWidth(String str, Font font) { diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java index c47649eb1..eb0f4d833 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentAfterElement.java @@ -43,7 +43,7 @@ public class PSCommentAfterElement extends AbstractPSCommentElement { * @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { - return ELEMENT; + return PSCommentAfter.ELEMENT; } /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java index f441553b7..951e685b3 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSCommentBeforeElement.java @@ -43,7 +43,7 @@ public class PSCommentBeforeElement extends AbstractPSCommentElement { * @see org.apache.fop.fo.FONode#getLocalName() */ public String getLocalName() { - return ELEMENT; + return PSCommentBefore.ELEMENT; } /** diff --git a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java index d1a1ede37..2044385a8 100644 --- a/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java +++ b/src/java/org/apache/fop/render/ps/extensions/PSExtensionElementMapping.java @@ -42,8 +42,8 @@ public class PSExtensionElementMapping extends ElementMapping { foObjs.put(PSSetupCodeElement.ELEMENT, new PSSetupCodeMaker()); foObjs.put(PSPageSetupCodeElement.ELEMENT, new PSPageSetupCodeMaker()); foObjs.put(PSSetPageDeviceElement.ELEMENT, new PSSetPageDeviceMaker()); - foObjs.put(PSCommentBeforeElement.ELEMENT, new PSCommentBeforeMaker()); - foObjs.put(PSCommentAfterElement.ELEMENT, new PSCommentAfterMaker()); + foObjs.put(PSCommentBefore.ELEMENT, new PSCommentBeforeMaker()); + foObjs.put(PSCommentAfter.ELEMENT, new PSCommentAfterMaker()); } } diff --git a/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java b/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java new file mode 100644 index 000000000..ae4d67516 --- /dev/null +++ b/src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java @@ -0,0 +1,142 @@ +/* + * 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.svg; + +import java.awt.geom.AffineTransform; +import java.lang.reflect.Constructor; + +import org.apache.batik.bridge.Bridge; +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.DocumentLoader; +import org.apache.batik.bridge.UserAgent; +import org.apache.fop.fonts.FontInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; + +/** + * A FOP base implementation of a Batik BridgeContext. + */ +public abstract class AbstractFOPBridgeContext extends BridgeContext { + + /** The font list. */ + protected final FontInfo fontInfo; + + protected final ImageManager imageManager; + protected final ImageSessionContext imageSessionContext; + + protected final AffineTransform linkTransform; + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param loader the Document Loader to use for referenced documents. + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param linkTransform AffineTransform to properly place links, + * may be null + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null + */ + public AbstractFOPBridgeContext(UserAgent userAgent, + DocumentLoader loader, + FontInfo fontInfo, + ImageManager imageManager, + ImageSessionContext imageSessionContext, + AffineTransform linkTransform) { + super(userAgent, loader); + this.fontInfo = fontInfo; + this.imageManager = imageManager; + this.imageSessionContext = imageSessionContext; + this.linkTransform = linkTransform; + } + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null + */ + public AbstractFOPBridgeContext(UserAgent userAgent, + FontInfo fontInfo, + ImageManager imageManager, + ImageSessionContext imageSessionContext, + AffineTransform linkTransform) { + super(userAgent); + this.fontInfo = fontInfo; + this.imageManager = imageManager; + this.imageSessionContext = imageSessionContext; + this.linkTransform = linkTransform; + } + + /** + * Constructs a new bridge context. + * @param userAgent the user agent + * @param fontInfo the font list for the text painter, may be null + * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + */ + public AbstractFOPBridgeContext(UserAgent userAgent, + FontInfo fontInfo, + ImageManager imageManager, + ImageSessionContext imageSessionContext) { + this(userAgent, fontInfo, imageManager, imageSessionContext, null); + } + + /** + * Returns the ImageManager to be used by the ImageElementBridge. + * @return the image manager + */ + public ImageManager getImageManager() { + return this.imageManager; + } + + /** + * Returns the ImageSessionContext to be used by the ImageElementBridge. + * @return the image session context + */ + public ImageSessionContext getImageSessionContext() { + return this.imageSessionContext; + } + + protected void putElementBridgeConditional(String className, String testFor) { + try { + Class.forName(testFor); + //if we get here the test class is available + + Class clazz = Class.forName(className); + Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class}); + putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo})); + } catch (Throwable t) { + //simply ignore (bridges instantiated over this method are optional) + } + } + + // Make sure any 'sub bridge contexts' also have our bridges. + //TODO There's no matching method in the super-class here + public abstract BridgeContext createBridgeContext(); + +} diff --git a/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java new file mode 100644 index 000000000..31895cebe --- /dev/null +++ b/src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java @@ -0,0 +1,284 @@ +/* + * 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.svg; + +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Rectangle2D; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.SVGImageElementBridge; +import org.apache.batik.gvt.AbstractGraphicsNode; +import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.util.ParsedURL; +import org.apache.xmlgraphics.image.loader.Image; +import org.apache.xmlgraphics.image.loader.ImageException; +import org.apache.xmlgraphics.image.loader.ImageFlavor; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageManager; +import org.apache.xmlgraphics.image.loader.ImageSessionContext; +import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; +import org.w3c.dom.Element; +import org.w3c.dom.svg.SVGDocument; + +/** + * Bridge class for the <image> element when jpeg images. + * + * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> + */ +public abstract class AbstractFOPImageElementBridge extends SVGImageElementBridge { + + /** + * Constructs a new bridge for the <image> element. + */ + public AbstractFOPImageElementBridge() { } + + /** + * Create the raster image node. + * THis checks if it is a jpeg file and creates a jpeg node + * so the jpeg can be inserted directly into the pdf document. + * @param ctx the bridge context + * @param imageElement the svg element for the image + * @param purl the parsed url for the image resource + * @return a new graphics node + */ + protected GraphicsNode createImageGraphicsNode + (BridgeContext ctx, Element imageElement, ParsedURL purl) { + AbstractFOPBridgeContext bridgeCtx = (AbstractFOPBridgeContext)ctx; + + ImageManager manager = bridgeCtx.getImageManager(); + ImageSessionContext sessionContext = bridgeCtx.getImageSessionContext(); + try { + ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext); + ImageFlavor[] supportedFlavors = getSupportedFlavours(); + Image image = manager.getImage(info, supportedFlavors, sessionContext); + + //TODO color profile overrides aren't handled, yet! + //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx); + AbstractGraphicsNode specializedNode = null; + if (image instanceof ImageXMLDOM) { + ImageXMLDOM xmlImage = (ImageXMLDOM)image; + if (xmlImage.getDocument() instanceof SVGDocument) { + return createSVGImageNode(ctx, imageElement, + (SVGDocument)xmlImage.getDocument()); + } else { + //Convert image to Graphics2D + image = manager.convertImage(xmlImage, + new ImageFlavor[] {ImageFlavor.GRAPHICS2D}); + } + } + if (image instanceof ImageRawJPEG) { + specializedNode = createLoaderImageNode(image, ctx, imageElement, purl); + } else if (image instanceof ImageRawCCITTFax) { + specializedNode = createLoaderImageNode(image, ctx, imageElement, purl); + } else if (image instanceof ImageGraphics2D) { + ImageGraphics2D g2dImage = (ImageGraphics2D)image; + specializedNode = new Graphics2DNode(g2dImage); + } else { + ctx.getUserAgent().displayError( + new ImageException("Cannot convert an image to a usable format: " + purl)); + } + + Rectangle2D imgBounds = getImageBounds(ctx, imageElement); + Rectangle2D bounds = specializedNode.getPrimitiveBounds(); + float [] vb = new float[4]; + vb[0] = 0; // x + vb[1] = 0; // y + vb[2] = (float) bounds.getWidth(); // width + vb[3] = (float) bounds.getHeight(); // height + + // handles the 'preserveAspectRatio', 'overflow' and 'clip' + // and sets the appropriate AffineTransform to the image node + initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds); + return specializedNode; + } catch (Exception e) { + ctx.getUserAgent().displayError(e); + } + + return superCreateGraphicsNode(ctx, imageElement, purl); + } + + /** + * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode. + * @param ctx the bridge context + * @param imageElement the image element + * @param purl the parsed URL + * @return the newly created graphics node + * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element) + */ + protected GraphicsNode superCreateGraphicsNode + (BridgeContext ctx, Element imageElement, ParsedURL purl) { + return super.createImageGraphicsNode(ctx, imageElement, purl); + } + + /** + * Returns an array of supported image flavours + * + * @return an array of supported image flavours + */ + protected abstract ImageFlavor[] getSupportedFlavours(); + + /** + * Creates a loader image node implementation + * @param purl the parsed url + * @param imageElement the image element + * @param ctx the batik bridge context + * @param image the image + * + * @return a loader image node implementation + */ + protected LoaderImageNode createLoaderImageNode( + Image image, BridgeContext ctx, Element imageElement, ParsedURL purl) { + return new LoaderImageNode(image, ctx, imageElement, purl); + } + + /** + * An image node for natively handled Image instance. + * This holds a natively handled image so that it can be drawn into + * the PDFGraphics2D. + */ + public class LoaderImageNode extends AbstractGraphicsNode { + + protected final Image image; + protected final BridgeContext ctx; + protected final Element imageElement; + protected final ParsedURL purl; + protected GraphicsNode origGraphicsNode = null; + + /** + * Create a new image node for drawing natively handled images + * into PDF graphics. + * @param image the JPEG image + * @param ctx the bridge context + * @param imageElement the SVG image element + * @param purl the URL to the image + */ + public LoaderImageNode(Image image, BridgeContext ctx, + Element imageElement, ParsedURL purl) { + this.image = image; + this.ctx = ctx; + this.imageElement = imageElement; + this.purl = purl; + } + + /** {@inheritDoc} */ + public Shape getOutline() { + return getPrimitiveBounds(); + } + + /** {@inheritDoc} */ + public void primitivePaint(Graphics2D g2d) { + if (g2d instanceof NativeImageHandler) { + NativeImageHandler nativeImageHandler = (NativeImageHandler) g2d; + float x = 0; + float y = 0; + try { + float width = image.getSize().getWidthPx(); + float height = image.getSize().getHeightPx(); + nativeImageHandler.addNativeImage(image, x, y, width, height); + } catch (Exception e) { + ctx.getUserAgent().displayError(e); + } + } else { + // Not going directly into PDF so use + // original implementation so filters etc work. + if (origGraphicsNode == null) { + // Haven't constructed base class Graphics Node, + // so do so now. + origGraphicsNode + = superCreateGraphicsNode(ctx, imageElement, purl); + } + origGraphicsNode.primitivePaint(g2d); + } + } + + /** {@inheritDoc} */ + public Rectangle2D getGeometryBounds() { + return getPrimitiveBounds(); + } + + /** {@inheritDoc} */ + public Rectangle2D getPrimitiveBounds() { + return new Rectangle2D.Double(0, 0, + image.getSize().getWidthPx(), + image.getSize().getHeightPx()); + } + + /** {@inheritDoc} */ + public Rectangle2D getSensitiveBounds() { + //No interactive features, just return primitive bounds + return getPrimitiveBounds(); + } + + } + + /** + * A node that holds a Graphics2D image. + */ + public class Graphics2DNode extends AbstractGraphicsNode { + + private final ImageGraphics2D image; + + /** + * Create a new Graphics2D node. + * @param g2d the Graphics2D image + */ + public Graphics2DNode(ImageGraphics2D g2d) { + this.image = g2d; + } + + /** {@inheritDoc} */ + public Shape getOutline() { + return getPrimitiveBounds(); + } + + /** {@inheritDoc} */ + public void primitivePaint(Graphics2D g2d) { + int width = image.getSize().getWidthPx(); + int height = image.getSize().getHeightPx(); + Rectangle2D area = new Rectangle2D.Double(0, 0, width, height); + Graphics2DImagePainter painter = image.getGraphics2DImagePainter(); + painter.paint(g2d, area); + } + + /** {@inheritDoc} */ + public Rectangle2D getGeometryBounds() { + return getPrimitiveBounds(); + } + + /** {@inheritDoc} */ + public Rectangle2D getPrimitiveBounds() { + return new Rectangle2D.Double(0, 0, + image.getSize().getWidthPx(), + image.getSize().getHeightPx()); + } + + /** {@inheritDoc} */ + public Rectangle2D getSensitiveBounds() { + //No interactive features, just return primitive bounds + return getPrimitiveBounds(); + } + + } +} diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java new file mode 100644 index 000000000..53b8e2ad5 --- /dev/null +++ b/src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java @@ -0,0 +1,113 @@ +/* + * 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.svg; + +import org.apache.batik.bridge.BridgeContext; +import org.apache.batik.bridge.SVGTextElementBridge; +import org.apache.batik.gvt.GraphicsNode; +import org.apache.batik.gvt.TextNode; +import org.apache.batik.gvt.TextPainter; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Bridge class for the <text> element. + * This bridge will use the direct text painter if the text + * for the element is simple. + * + * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> + */ +public abstract class AbstractFOPTextElementBridge extends SVGTextElementBridge { + + /** text painter */ + protected TextPainter textPainter; + + /** + * Main constructor + * + * @param textPainter the text painter + */ + public AbstractFOPTextElementBridge(TextPainter textPainter) { + this.textPainter = textPainter; + } + + /** + * Create a text element bridge. + * + * This set the text painter on the node if the text is simple. + * @param ctx the bridge context + * @param e the svg element + * @return the text graphics node created by the super class + */ + public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { + GraphicsNode node = super.createGraphicsNode(ctx, e); + if (node != null) { + //Set our own text painter + ((TextNode)node).setTextPainter(textPainter); + } + return node; + } + + /** + * Check if text element contains simple text. + * This checks the children of the text element to determine + * if the text is simple. The text is simple if it can be rendered + * with basic text drawing algorithms. This means there are no + * alternate characters, the font is known and there are no effects + * applied to the text. + * + * @param ctx the bridge context + * @param element the svg text element + * @param node the graphics node + * @return true if this text is simple of false if it cannot be + * easily rendered using normal drawString on the Graphics2D + */ + protected boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) { + for (Node n = element.getFirstChild(); + n != null; + n = n.getNextSibling()) { + + switch (n.getNodeType()) { + case Node.ELEMENT_NODE: + + if (n.getLocalName().equals(SVG_TSPAN_TAG) + || n.getLocalName().equals(SVG_ALT_GLYPH_TAG)) { + return false; + } else if (n.getLocalName().equals(SVG_TEXT_PATH_TAG)) { + return false; + } else if (n.getLocalName().equals(SVG_TREF_TAG)) { + return false; + } + break; + case Node.TEXT_NODE: + case Node.CDATA_SECTION_NODE: + default: + } + } + + /*if (CSSUtilities.convertFilter(element, node, ctx) != null) { + return false; + }*/ + + return true; + } + +} + diff --git a/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java new file mode 100644 index 000000000..560c76cb5 --- /dev/null +++ b/src/java/org/apache/fop/svg/AbstractFOPTextPainter.java @@ -0,0 +1,528 @@ +/* + * 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.svg; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.Shape; +import java.awt.font.TextAttribute; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.text.AttributedCharacterIterator; +import java.text.CharacterIterator; +import java.util.Iterator; +import java.util.List; + +import org.apache.batik.dom.svg.SVGOMTextElement; +import org.apache.batik.gvt.TextNode; +import org.apache.batik.gvt.TextPainter; +import org.apache.batik.gvt.font.GVTFontFamily; +import org.apache.batik.gvt.renderer.StrokingTextPainter; +import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; +import org.apache.batik.gvt.text.Mark; +import org.apache.batik.gvt.text.TextPaintInfo; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.fonts.Font; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontTriplet; + + +/** + * Renders the attributed character iterator of a <tt>TextNode</tt>. + * This class draws the text directly into the Graphics2D so that + * the text is not drawn using shapes. + * If the text is simple enough to draw then it sets the font and calls + * drawString. If the text is complex or the cannot be translated + * into a simple drawString the StrokingTextPainter is used instead. + */ +public abstract class AbstractFOPTextPainter implements TextPainter { + + /** the logger for this class */ + protected Log log = LogFactory.getLog(AbstractFOPTextPainter.class); + + private final FOPTextHandler nativeTextHandler; + + /** + * Use the stroking text painter to get the bounds and shape. + * Also used as a fallback to draw the string with strokes. + */ + protected static final TextPainter + PROXY_PAINTER = StrokingTextPainter.getInstance(); + + /** + * Create a new PS text painter with the given font information. + * @param nativeTextHandler the NativeTextHandler instance used for text painting + */ + public AbstractFOPTextPainter(FOPTextHandler nativeTextHandler) { + this.nativeTextHandler = nativeTextHandler; + } + + /** + * Paints the specified attributed character iterator using the + * specified Graphics2D and context and font context. + * + * @param node the TextNode to paint + * @param g2d the Graphics2D to use + */ + public void paint(TextNode node, Graphics2D g2d) { + Point2D loc = node.getLocation(); + log.debug("painting text node " + node); + if (hasUnsupportedAttributes(node)) { + log.debug("hasUnsuportedAttributes"); + PROXY_PAINTER.paint(node, g2d); + } else { + log.debug("allAttributesSupported"); + paintTextRuns(node.getTextRuns(), g2d, loc); + } + } + + private boolean hasUnsupportedAttributes(TextNode node) { + Iterator iter = node.getTextRuns().iterator(); + while (iter.hasNext()) { + StrokingTextPainter.TextRun + run = (StrokingTextPainter.TextRun)iter.next(); + AttributedCharacterIterator aci = run.getACI(); + boolean hasUnsupported = hasUnsupportedAttributes(aci); + if (hasUnsupported) { + return true; + } + } + return false; + } + + private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) { + boolean hasUnsupported = false; + + Font font = getFont(aci); + String text = getText(aci); + if (hasUnsupportedGlyphs(text, font)) { + log.trace("-> Unsupported glyphs found"); + hasUnsupported = true; + } + + TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); + if ((tpi != null) + && ((tpi.strokeStroke != null && tpi.strokePaint != null) + || (tpi.strikethroughStroke != null) + || (tpi.underlineStroke != null) + || (tpi.overlineStroke != null))) { + log.trace("-> under/overlines etc. found"); + hasUnsupported = true; + } + + //Alpha is not supported + Paint foreground = (Paint) aci.getAttribute(TextAttribute.FOREGROUND); + if (foreground instanceof Color) { + Color col = (Color)foreground; + if (col.getAlpha() != 255) { + log.trace("-> transparency found"); + hasUnsupported = true; + } + } + + Object letSpace = aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING); + if (letSpace != null) { + log.trace("-> letter spacing found"); + hasUnsupported = true; + } + + Object wordSpace = aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING); + if (wordSpace != null) { + log.trace("-> word spacing found"); + hasUnsupported = true; + } + + Object lengthAdjust = aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST); + if (lengthAdjust != null) { + log.trace("-> length adjustments found"); + hasUnsupported = true; + } + + Object writeMod = aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE); + if (writeMod != null + && !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals( + writeMod)) { + log.trace("-> Unsupported writing modes found"); + hasUnsupported = true; + } + + Object vertOr = aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.VERTICAL_ORIENTATION); + if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals( + vertOr)) { + log.trace("-> vertical orientation found"); + hasUnsupported = true; + } + + Object rcDel = aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); + //Batik 1.6 returns null here which makes it impossible to determine whether this can + //be painted or not, i.e. fall back to stroking. :-( + if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) { + log.trace("-> spans found"); + hasUnsupported = true; //Filter spans + } + + if (hasUnsupported) { + log.trace("Unsupported attributes found in ACI, using StrokingTextPainter"); + } + return hasUnsupported; + } + + /** + * Paint a list of text runs on the Graphics2D at a given location. + * @param textRuns the list of text runs + * @param g2d the Graphics2D to paint to + * @param loc the current location of the "cursor" + */ + protected void paintTextRuns(List textRuns, Graphics2D g2d, Point2D loc) { + Point2D currentloc = loc; + Iterator i = textRuns.iterator(); + while (i.hasNext()) { + StrokingTextPainter.TextRun + run = (StrokingTextPainter.TextRun)i.next(); + currentloc = paintTextRun(run, g2d, currentloc); + } + } + + /** + * Paint a single text run on the Graphics2D at a given location. + * @param run the text run to paint + * @param g2d the Graphics2D to paint to + * @param loc the current location of the "cursor" + * @return the new location of the "cursor" after painting the text run + */ + protected Point2D paintTextRun(StrokingTextPainter.TextRun run, Graphics2D g2d, Point2D loc) { + AttributedCharacterIterator aci = run.getACI(); + aci.first(); + + updateLocationFromACI(aci, loc); + AffineTransform at = g2d.getTransform(); + loc = at.transform(loc, null); + + // font + Font font = getFont(aci); + if (font != null) { + nativeTextHandler.setOverrideFont(font); + } + + // color + TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO); + if (tpi == null) { + return loc; + } + Paint foreground = tpi.fillPaint; + if (foreground instanceof Color) { + Color col = (Color)foreground; + g2d.setColor(col); + } + g2d.setPaint(foreground); + + // text + String txt = getText(aci); + float advance = getStringWidth(txt, font); + float tx = 0; + TextNode.Anchor anchor = (TextNode.Anchor)aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE); + if (anchor != null) { + switch (anchor.getType()) { + case TextNode.Anchor.ANCHOR_MIDDLE: + tx = -advance / 2; + break; + case TextNode.Anchor.ANCHOR_END: + tx = -advance; + break; + default: //nop + } + } + + // draw string + double x = loc.getX(); + double y = loc.getY(); + try { + try { + nativeTextHandler.drawString(g2d, txt, (float)x + tx, (float)y); + } catch (IOException ioe) { + if (g2d instanceof AFPGraphics2D) { + ((AFPGraphics2D)g2d).handleIOException(ioe); + } + } + } finally { + nativeTextHandler.setOverrideFont(null); + } + loc.setLocation(loc.getX() + advance, loc.getY()); + return loc; + } + + /** + * Extract the raw text from an ACI. + * @param aci ACI to inspect + * @return the extracted text + */ + protected String getText(AttributedCharacterIterator aci) { + StringBuffer sb = new StringBuffer(aci.getEndIndex() - aci.getBeginIndex()); + for (char c = aci.first(); c != CharacterIterator.DONE; c = aci.next()) { + sb.append(c); + } + return sb.toString(); + } + + private void updateLocationFromACI( + AttributedCharacterIterator aci, + Point2D loc) { + //Adjust position of span + Float xpos = (Float)aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.X); + Float ypos = (Float)aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.Y); + Float dxpos = (Float)aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.DX); + Float dypos = (Float)aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.DY); + if (xpos != null) { + loc.setLocation(xpos.doubleValue(), loc.getY()); + } + if (ypos != null) { + loc.setLocation(loc.getX(), ypos.doubleValue()); + } + if (dxpos != null) { + loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY()); + } + if (dypos != null) { + loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue()); + } + } + + private String getStyle(AttributedCharacterIterator aci) { + Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE); + return ((posture != null) && (posture.floatValue() > 0.0)) + ? Font.STYLE_ITALIC + : Font.STYLE_NORMAL; + } + + private int getWeight(AttributedCharacterIterator aci) { + Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT); + return ((taWeight != null) && (taWeight.floatValue() > 1.0)) + ? Font.WEIGHT_BOLD + : Font.WEIGHT_NORMAL; + } + + private Font getFont(AttributedCharacterIterator aci) { + Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE); + String style = getStyle(aci); + int weight = getWeight(aci); + + FontInfo fontInfo = nativeTextHandler.getFontInfo(); + String fontFamily = null; + List gvtFonts = (List) aci.getAttribute( + GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES); + if (gvtFonts != null) { + Iterator i = gvtFonts.iterator(); + while (i.hasNext()) { + GVTFontFamily fam = (GVTFontFamily) i.next(); + /* (todo) Enable SVG Font painting + if (fam instanceof SVGFontFamily) { + PROXY_PAINTER.paint(node, g2d); + return; + }*/ + fontFamily = fam.getFamilyName(); + if (fontInfo.hasFont(fontFamily, style, weight)) { + FontTriplet triplet = fontInfo.fontLookup( + fontFamily, style, weight); + int fsize = (int)(fontSize.floatValue() * 1000); + return fontInfo.getFontInstance(triplet, fsize); + } + } + } + FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL); + int fsize = (int)(fontSize.floatValue() * 1000); + return fontInfo.getFontInstance(triplet, fsize); + } + + private float getStringWidth(String str, Font font) { + float wordWidth = 0; + float whitespaceWidth = font.getWidth(font.mapChar(' ')); + + for (int i = 0; i < str.length(); i++) { + float charWidth; + char c = str.charAt(i); + if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) { + charWidth = font.getWidth(font.mapChar(c)); + if (charWidth <= 0) { + charWidth = whitespaceWidth; + } + } else { + charWidth = whitespaceWidth; + } + wordWidth += charWidth; + } + return wordWidth / 1000f; + } + + private boolean hasUnsupportedGlyphs(String str, Font font) { + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (!((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))) { + if (!font.hasChar(c)) { + return true; + } + } + } + return false; + } + + /** + * Get the outline shape of the text characters. + * This uses the StrokingTextPainter to get the outline + * shape since in theory it should be the same. + * + * @param node the text node + * @return the outline shape of the text characters + */ + public Shape getOutline(TextNode node) { + return PROXY_PAINTER.getOutline(node); + } + + /** + * Get the bounds. + * This uses the StrokingTextPainter to get the bounds + * since in theory it should be the same. + * + * @param node the text node + * @return the bounds of the text + */ + public Rectangle2D getBounds2D(TextNode node) { + /* (todo) getBounds2D() is too slow + * because it uses the StrokingTextPainter. We should implement this + * method ourselves. */ + return PROXY_PAINTER.getBounds2D(node); + } + + /** + * Get the geometry bounds. + * This uses the StrokingTextPainter to get the bounds + * since in theory it should be the same. + * + * @param node the text node + * @return the bounds of the text + */ + public Rectangle2D getGeometryBounds(TextNode node) { + return PROXY_PAINTER.getGeometryBounds(node); + } + + // Methods that have no purpose for PS + + /** + * Get the mark. + * This does nothing since the output is AFP and not interactive. + * + * @param node the text node + * @param pos the position + * @param all select all + * @return null + */ + public Mark getMark(TextNode node, int pos, boolean all) { + return null; + } + + /** + * Select at. + * This does nothing since the output is AFP and not interactive. + * + * @param x the x position + * @param y the y position + * @param node the text node + * @return null + */ + public Mark selectAt(double x, double y, TextNode node) { + return null; + } + + /** + * Select to. + * This does nothing since the output is AFP and not interactive. + * + * @param x the x position + * @param y the y position + * @param beginMark the start mark + * @return null + */ + public Mark selectTo(double x, double y, Mark beginMark) { + return null; + } + + /** + * Selec first. + * This does nothing since the output is AFP and not interactive. + * + * @param node the text node + * @return null + */ + public Mark selectFirst(TextNode node) { + return null; + } + + /** + * Select last. + * This does nothing since the output is AFP and not interactive. + * + * @param node the text node + * @return null + */ + public Mark selectLast(TextNode node) { + return null; + } + + /** + * Get selected. + * This does nothing since the output is AFP and not interactive. + * + * @param start the start mark + * @param finish the finish mark + * @return null + */ + public int[] getSelected(Mark start, Mark finish) { + return null; + } + + /** + * Get the highlighted shape. + * This does nothing since the output is AFP and not interactive. + * + * @param beginMark the start mark + * @param endMark the end mark + * @return null + */ + public Shape getHighlightShape(Mark beginMark, Mark endMark) { + return null; + } + +} diff --git a/src/java/org/apache/fop/svg/FOPTextHandler.java b/src/java/org/apache/fop/svg/FOPTextHandler.java new file mode 100644 index 000000000..8fa9eeedd --- /dev/null +++ b/src/java/org/apache/fop/svg/FOPTextHandler.java @@ -0,0 +1,27 @@ +/* + * 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.svg; + +public interface FOPTextHandler extends org.apache.xmlgraphics.java2d.TextHandler { + + void setOverrideFont(org.apache.fop.fonts.Font font); + + org.apache.fop.fonts.FontInfo getFontInfo(); +} diff --git a/src/java/org/apache/fop/svg/GraphicsConfiguration.java b/src/java/org/apache/fop/svg/GraphicsConfiguration.java index ca3b3363c..881096b9a 100644 --- a/src/java/org/apache/fop/svg/GraphicsConfiguration.java +++ b/src/java/org/apache/fop/svg/GraphicsConfiguration.java @@ -17,7 +17,6 @@ /* $Id$ */ - package org.apache.fop.svg; import java.awt.image.VolatileImage; diff --git a/src/java/org/apache/fop/svg/NativeImageHandler.java b/src/java/org/apache/fop/svg/NativeImageHandler.java new file mode 100644 index 000000000..8e74cba1d --- /dev/null +++ b/src/java/org/apache/fop/svg/NativeImageHandler.java @@ -0,0 +1,40 @@ +/* + * 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.svg; + +public interface NativeImageHandler { + + /** + * Add a natively handled image directly to the document. + * This is used by the ImageElementBridge to draw a natively handled image + * (like JPEG or CCITT images) + * directly into the document rather than converting the image into + * a bitmap and increasing the size. + * + * @param image the image to draw + * @param x the x position + * @param y the y position + * @param width the width to draw the image + * @param height the height to draw the image + */ + void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y, + float width, float height); + +} diff --git a/src/java/org/apache/fop/svg/PDFBridgeContext.java b/src/java/org/apache/fop/svg/PDFBridgeContext.java index fdf83784f..364c7a6f3 100644 --- a/src/java/org/apache/fop/svg/PDFBridgeContext.java +++ b/src/java/org/apache/fop/svg/PDFBridgeContext.java @@ -20,30 +20,20 @@ package org.apache.fop.svg; import java.awt.geom.AffineTransform; -import java.lang.reflect.Constructor; -import org.apache.batik.bridge.Bridge; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.DocumentLoader; +import org.apache.batik.bridge.SVGTextElementBridge; import org.apache.batik.bridge.UserAgent; - +import org.apache.batik.gvt.TextPainter; +import org.apache.fop.fonts.FontInfo; import org.apache.xmlgraphics.image.loader.ImageManager; import org.apache.xmlgraphics.image.loader.ImageSessionContext; -import org.apache.fop.fonts.FontInfo; - /** * BridgeContext which registers the custom bridges for PDF output. */ -public class PDFBridgeContext extends BridgeContext { - - /** The font list. */ - private final FontInfo fontInfo; - - private final ImageManager imageManager; - private final ImageSessionContext imageSessionContext; - - private AffineTransform linkTransform; +public class PDFBridgeContext extends AbstractFOPBridgeContext { /** * Constructs a new bridge context. @@ -53,18 +43,16 @@ public class PDFBridgeContext extends BridgeContext { * in which case text is painted as shapes * @param linkTransform AffineTransform to properly place links, * may be null + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null */ - public PDFBridgeContext(UserAgent userAgent, - DocumentLoader loader, - FontInfo fontInfo, - ImageManager imageManager, - ImageSessionContext imageSessionContext, - AffineTransform linkTransform) { - super(userAgent, loader); - this.fontInfo = fontInfo; - this.imageManager = imageManager; - this.imageSessionContext = imageSessionContext; - this.linkTransform = linkTransform; + public PDFBridgeContext(UserAgent userAgent, DocumentLoader documentLoader, + FontInfo fontInfo, ImageManager imageManager, + ImageSessionContext imageSessionContext, + AffineTransform linkTransform) { + super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform); } /** @@ -72,19 +60,12 @@ public class PDFBridgeContext extends BridgeContext { * @param userAgent the user agent * @param fontInfo the font list for the text painter, may be null * in which case text is painted as shapes - * @param linkTransform AffineTransform to properly place links, - * may be null + * @param imageManager an image manager + * @param imageSessionContext an image session context */ - public PDFBridgeContext(UserAgent userAgent, - FontInfo fontInfo, - ImageManager imageManager, - ImageSessionContext imageSessionContext, - AffineTransform linkTransform) { - super(userAgent); - this.fontInfo = fontInfo; - this.imageManager = imageManager; - this.imageSessionContext = imageSessionContext; - this.linkTransform = linkTransform; + public PDFBridgeContext(UserAgent userAgent, FontInfo fontInfo, + ImageManager imageManager, ImageSessionContext imageSessionContext) { + super(userAgent, fontInfo, imageManager, imageSessionContext); } /** @@ -92,41 +73,15 @@ public class PDFBridgeContext extends BridgeContext { * @param userAgent the user agent * @param fontInfo the font list for the text painter, may be null * in which case text is painted as shapes + * @param imageManager an image manager + * @param imageSessionContext an image session context + * @param linkTransform AffineTransform to properly place links, + * may be null */ - public PDFBridgeContext(UserAgent userAgent, - FontInfo fontInfo, - ImageManager imageManager, - ImageSessionContext imageSessionContext) { - this(userAgent, fontInfo, imageManager, imageSessionContext, null); - } - - /** - * Returns the ImageManager to be used by the ImageElementBridge. - * @return the image manager - */ - public ImageManager getImageManager() { - return this.imageManager; - } - - /** - * Returns the ImageSessionContext to be used by the ImageElementBridge. - * @return the image session context - */ - public ImageSessionContext getImageSessionContext() { - return this.imageSessionContext; - } - - private void putPDFElementBridgeConditional(String className, String testFor) { - try { - Class.forName(testFor); - //if we get here the test class is available - - Class clazz = Class.forName(className); - Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class}); - putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo})); - } catch (Throwable t) { - //simply ignore (bridges instantiated over this method are optional) - } + public PDFBridgeContext(SVGUserAgent userAgent, FontInfo fontInfo, + ImageManager imageManager, ImageSessionContext imageSessionContext, + AffineTransform linkTransform) { + super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform); } /** {@inheritDoc} */ @@ -134,23 +89,24 @@ public class PDFBridgeContext extends BridgeContext { super.registerSVGBridges(); if (fontInfo != null) { - PDFTextElementBridge textElementBridge = new PDFTextElementBridge(fontInfo); + TextPainter textPainter = new PDFTextPainter(fontInfo); + SVGTextElementBridge textElementBridge = new PDFTextElementBridge(textPainter); putBridge(textElementBridge); //Batik flow text extension (may not always be available) //putBridge(new PDFBatikFlowTextElementBridge(fontInfo); - putPDFElementBridgeConditional( + putElementBridgeConditional( "org.apache.fop.svg.PDFBatikFlowTextElementBridge", "org.apache.batik.extension.svg.BatikFlowTextElementBridge"); //SVG 1.2 flow text support //putBridge(new PDFSVG12TextElementBridge(fontInfo)); //-->Batik 1.7 - putPDFElementBridgeConditional( + putElementBridgeConditional( "org.apache.fop.svg.PDFSVG12TextElementBridge", "org.apache.batik.bridge.svg12.SVG12TextElementBridge"); //putBridge(new PDFSVGFlowRootElementBridge(fontInfo)); - putPDFElementBridgeConditional( + putElementBridgeConditional( "org.apache.fop.svg.PDFSVGFlowRootElementBridge", "org.apache.batik.bridge.svg12.SVGFlowRootElementBridge"); } diff --git a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java index dd13df1c4..cc6e06978 100644 --- a/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java @@ -19,30 +19,30 @@ package org.apache.fop.svg; -import org.apache.fop.Version; -import org.apache.fop.pdf.PDFDocument; -import org.apache.fop.pdf.PDFFilterList; -import org.apache.fop.pdf.PDFPage; -import org.apache.fop.pdf.PDFStream; -import org.apache.fop.pdf.PDFState; -import org.apache.fop.pdf.PDFNumber; -import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFColor; -import org.apache.fop.pdf.PDFAnnotList; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontSetup; - -import java.awt.Graphics; -import java.awt.Font; import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.StringWriter; +import org.apache.fop.Version; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontSetup; +import org.apache.fop.pdf.PDFAnnotList; +import org.apache.fop.pdf.PDFColor; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFFilterList; +import org.apache.fop.pdf.PDFNumber; +import org.apache.fop.pdf.PDFPage; +import org.apache.fop.pdf.PDFPaintingState; +import org.apache.fop.pdf.PDFResources; +import org.apache.fop.pdf.PDFStream; + /** * This class is a wrapper for the <tt>PDFGraphics2D</tt> that * is used to create a full document around the pdf rendering from @@ -52,7 +52,7 @@ import java.io.StringWriter; */ public class PDFDocumentGraphics2D extends PDFGraphics2D { - private PDFContext pdfContext; + private final PDFContext pdfContext; private int width; private int height; @@ -296,7 +296,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { throw new IllegalStateException("Close page first before starting another"); } //Start page - graphicsState = new PDFState(); + paintingState = new PDFPaintingState(); if (this.initialTransform == null) { //Save initial transformation matrix this.initialTransform = getTransform(); @@ -322,7 +322,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { pageRef = page.referencePDF(); AffineTransform at = new AffineTransform(1.0, 0.0, 0.0, -1.0, - 0.0, (double)height); + 0.0, height); currentStream.write("1 0 0 -1 0 " + height + " cm\n"); if (svgWidth != 0) { double scaleX = width / svgWidth; @@ -340,7 +340,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { scale(1 / s, 1 / s); } // Remember the transform we installed. - graphicsState.concatenate(at); + paintingState.concatenate(at); pdfContext.increasePageCount(); } diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index cd0a4133b..5053209e3 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -59,19 +59,9 @@ import org.apache.batik.ext.awt.RadialGradientPaint; import org.apache.batik.ext.awt.RenderingHintsKeyExt; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.PatternPaint; - -import org.apache.xmlgraphics.image.loader.ImageInfo; -import org.apache.xmlgraphics.image.loader.ImageSize; -import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; -import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; -import org.apache.xmlgraphics.image.loader.impl.ImageRendered; -import org.apache.xmlgraphics.java2d.AbstractGraphics2D; -import org.apache.xmlgraphics.java2d.GraphicContext; - import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; -import org.apache.fop.fonts.FontTriplet; import org.apache.fop.pdf.BitmapImage; import org.apache.fop.pdf.PDFAnnotList; import org.apache.fop.pdf.PDFColor; @@ -83,16 +73,23 @@ import org.apache.fop.pdf.PDFImage; import org.apache.fop.pdf.PDFImageXObject; import org.apache.fop.pdf.PDFLink; import org.apache.fop.pdf.PDFNumber; +import org.apache.fop.pdf.PDFPaintingState; import org.apache.fop.pdf.PDFPattern; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFText; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter; import org.apache.fop.render.pdf.ImageRawJPEGAdapter; import org.apache.fop.render.pdf.ImageRenderedAdapter; import org.apache.fop.util.ColorExt; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.java2d.AbstractGraphics2D; +import org.apache.xmlgraphics.java2d.GraphicContext; /** * PDF Graphics 2D. @@ -103,8 +100,7 @@ import org.apache.fop.util.ColorExt; * @version $Id$ * @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D */ -public class PDFGraphics2D extends AbstractGraphics2D { - +public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHandler { private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform(); /** The number of decimal places. */ @@ -129,9 +125,9 @@ public class PDFGraphics2D extends AbstractGraphics2D { protected String pageRef; /** - * the current state of the pdf graphics + * The PDF painting state */ - protected PDFState graphicsState; + protected PDFPaintingState paintingState; /** * The PDF graphics state level that this svg is being drawn into. @@ -200,7 +196,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { currentFontSize = size; fontInfo = fi; pageRef = pref; - graphicsState = new PDFState(); + paintingState = new PDFPaintingState(); } /** @@ -226,7 +222,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { this.currentFontSize = g.currentFontSize; this.fontInfo = g.fontInfo; this.pageRef = g.pageRef; - this.graphicsState = g.graphicsState; + this.paintingState = g.paintingState; this.currentStream = g.currentStream; this.nativeCount = g.nativeCount; this.outputStream = g.outputStream; @@ -266,9 +262,9 @@ public class PDFGraphics2D extends AbstractGraphics2D { * * @param state the PDF state */ - public void setPDFState(PDFState state) { - graphicsState = state; - baseLevel = graphicsState.getStackLevel(); + public void setPaintingState(PDFPaintingState state) { + paintingState = state; + baseLevel = paintingState.getStackLevel(); } /** @@ -369,7 +365,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { * @return the transformation matrix that established the basic user space for this document */ protected AffineTransform getBaseTransform() { - AffineTransform at = new AffineTransform(graphicsState.getTransform()); + AffineTransform at = new AffineTransform(paintingState.getTransform()); return at; } @@ -417,7 +413,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { * @param width the width to draw the image * @param height the height to draw the image */ - void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y, + public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y, float width, float height) { preparePainting(); String key = image.getInfo().getOriginalURI(); @@ -518,10 +514,14 @@ public class PDFGraphics2D extends AbstractGraphics2D { g.setBackground(new Color(1, 1, 1, 0)); g.setPaint(new Color(1, 1, 1, 0)); g.fillRect(0, 0, width, height); - g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight())); + + int imageWidth = buf.getWidth(); + int imageHeight = buf.getHeight(); + g.clip(new Rectangle(0, 0, imageWidth, imageHeight)); g.setComposite(gc.getComposite()); - if (!g.drawImage(img, 0, 0, buf.getWidth(), buf.getHeight(), observer)) { + boolean drawn = g.drawImage(img, 0, 0, imageWidth, imageHeight, observer); + if (!drawn) { return false; } g.dispose(); @@ -602,13 +602,13 @@ public class PDFGraphics2D extends AbstractGraphics2D { trans.getMatrix(tranvals); Shape imclip = getClip(); - boolean newClip = graphicsState.checkClip(imclip); - boolean newTransform = graphicsState.checkTransform(trans) + boolean newClip = paintingState.checkClip(imclip); + boolean newTransform = paintingState.checkTransform(trans) && !trans.isIdentity(); if (newClip || newTransform) { currentStream.write("q\n"); - graphicsState.push(); + paintingState.save(); if (newTransform) { concatMatrix(tranvals); } @@ -625,7 +625,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { applyColor(c, true); Paint paint = getPaint(); - if (graphicsState.setPaint(paint)) { + if (paintingState.setPaint(paint)) { if (!applyPaint(paint, false)) { // Stroke the shape and use it to 'clip' // the paint contents. @@ -634,7 +634,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.restore(); } return; } @@ -646,7 +646,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { doDrawing(false, true, false); if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.restore(); } } @@ -1324,7 +1324,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { if (ovFontState == null) { java.awt.Font gFont = getFont(); fontTransform = gFont.getTransform(); - fontState = getInternalFontForAWTFont(gFont); + fontState = fontInfo.getFontInstanceForAWTFont(gFont); } else { fontState = fontInfo.getFontInstance( ovFontState.getFontTriplet(), ovFontState.getFontSize()); @@ -1380,7 +1380,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { if (!useMultiByte) { if (ch > 127) { currentStream.write("\\"); - currentStream.write(Integer.toOctalString((int)ch)); + currentStream.write(Integer.toOctalString(ch)); } else { switch (ch) { case '(': @@ -1397,8 +1397,8 @@ public class PDFGraphics2D extends AbstractGraphics2D { } if (kerningAvailable && (i + 1) < l) { - addKerning(currentStream, (new Integer((int)ch)), - (new Integer((int)fontState.mapChar(s.charAt(i + 1)))), + addKerning(currentStream, (new Integer(ch)), + (new Integer(fontState.mapChar(s.charAt(i + 1)))), kerning, startText, endText); } @@ -1426,7 +1426,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { vals.put(PDFGState.GSTATE_ALPHA_STROKE, new Float(strokeAlpha / 255f)); } PDFGState gstate = pdfDoc.getFactory().makeGState( - vals, graphicsState.getGState()); + vals, paintingState.getGState()); resourceContext.addGState(gstate); currentStream.write("/" + gstate.getName() + " gs\n"); } @@ -1438,7 +1438,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { */ protected void updateCurrentFont(Font font) { String name = font.getFontName(); - float size = (float)font.getFontSize() / 1000f; + float size = font.getFontSize() / 1000f; //Only update if necessary if ((!name.equals(this.currentFontName)) @@ -1453,19 +1453,10 @@ public class PDFGraphics2D extends AbstractGraphics2D { * Returns a suitable internal font given an AWT Font instance. * @param awtFont the AWT font * @return the internal Font + * @deprecated use FontInfo.getFontInstanceForAWTFont(java.awt.Font awtFont) instead */ protected Font getInternalFontForAWTFont(java.awt.Font awtFont) { - Font fontState; - String n = awtFont.getFamily(); - if (n.equals("sanserif")) { - n = "sans-serif"; - } - float siz = awtFont.getSize2D(); - String style = awtFont.isItalic() ? "italic" : "normal"; - int weight = awtFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL; - FontTriplet triplet = fontInfo.fontLookup(n, style, weight); - fontState = fontInfo.getFontInstance(triplet, (int)(siz * 1000 + 0.5)); - return fontState; + return fontInfo.getFontInstanceForAWTFont(awtFont); } /** @@ -1617,13 +1608,13 @@ public class PDFGraphics2D extends AbstractGraphics2D { trans.getMatrix(tranvals); Shape imclip = getClip(); - boolean newClip = graphicsState.checkClip(imclip); - boolean newTransform = graphicsState.checkTransform(trans) + boolean newClip = paintingState.checkClip(imclip); + boolean newTransform = paintingState.checkTransform(trans) && !trans.isIdentity(); if (newClip || newTransform) { currentStream.write("q\n"); - graphicsState.push(); + paintingState.save(); if (newTransform) { concatMatrix(tranvals); } @@ -1640,14 +1631,14 @@ public class PDFGraphics2D extends AbstractGraphics2D { applyColor(c, false); Paint paint = getPaint(); - if (graphicsState.setPaint(paint)) { + if (paintingState.setPaint(paint)) { if (!applyPaint(paint, true)) { // Use the shape to 'clip' the paint contents. applyUnknownPaint(paint, s); if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.restore(); } return; } @@ -1660,7 +1651,7 @@ public class PDFGraphics2D extends AbstractGraphics2D { iter.getWindingRule() == PathIterator.WIND_EVEN_ODD); if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.restore(); } } diff --git a/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java b/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java index 83a431d5e..0204a2756 100644 --- a/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java +++ b/src/java/org/apache/fop/svg/PDFGraphicsConfiguration.java @@ -26,6 +26,7 @@ import java.awt.image.ColorModel; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; + /** * Our implementation of the class that returns information about * roughly what we can handle and want to see (alpha for example). diff --git a/src/java/org/apache/fop/svg/PDFImageElementBridge.java b/src/java/org/apache/fop/svg/PDFImageElementBridge.java index 7eb89d2b1..1a17aa410 100644 --- a/src/java/org/apache/fop/svg/PDFImageElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFImageElementBridge.java @@ -19,36 +19,14 @@ package org.apache.fop.svg; -import java.awt.Graphics2D; -import java.awt.Shape; -import java.awt.geom.Rectangle2D; - -import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; - -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.SVGImageElementBridge; -import org.apache.batik.gvt.AbstractGraphicsNode; -import org.apache.batik.gvt.GraphicsNode; -import org.apache.batik.util.ParsedURL; - -import org.apache.xmlgraphics.image.loader.Image; -import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageFlavor; -import org.apache.xmlgraphics.image.loader.ImageInfo; -import org.apache.xmlgraphics.image.loader.ImageManager; -import org.apache.xmlgraphics.image.loader.ImageSessionContext; -import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D; -import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; -import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; -import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM; /** - * Bridge class for the <image> element when jpeg images. + * PDF Image Element Bridge class for the <image> element when jpeg images. * * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> */ -public class PDFImageElementBridge extends SVGImageElementBridge { +public class PDFImageElementBridge extends AbstractFOPImageElementBridge { /** * Constructs a new bridge for the <image> element. @@ -60,210 +38,9 @@ public class PDFImageElementBridge extends SVGImageElementBridge { ImageFlavor.RAW_CCITTFAX, ImageFlavor.GRAPHICS2D, ImageFlavor.XML_DOM}; - /** - * Create the raster image node. - * THis checks if it is a jpeg file and creates a jpeg node - * so the jpeg can be inserted directly into the pdf document. - * @param ctx the bridge context - * @param imageElement the svg element for the image - * @param purl the parsed url for the image resource - * @return a new graphics node - */ - protected GraphicsNode createImageGraphicsNode - (BridgeContext ctx, Element imageElement, ParsedURL purl) { - PDFBridgeContext pdfCtx = (PDFBridgeContext)ctx; - - ImageManager manager = pdfCtx.getImageManager(); - ImageSessionContext sessionContext = pdfCtx.getImageSessionContext(); - try { - ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext); - Image image = manager.getImage(info, supportedFlavors, sessionContext); - - //TODO color profile overrides aren't handled, yet! - //ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx); - AbstractGraphicsNode specializedNode = null; - if (image instanceof ImageXMLDOM) { - ImageXMLDOM xmlImage = (ImageXMLDOM)image; - if (xmlImage.getDocument() instanceof SVGDocument) { - return createSVGImageNode(ctx, imageElement, - (SVGDocument)xmlImage.getDocument()); - } else { - //Convert image to Graphics2D - image = manager.convertImage(xmlImage, - new ImageFlavor[] {ImageFlavor.GRAPHICS2D}); - } - } - if (image instanceof ImageRawJPEG) { - specializedNode = new LoaderImageNode(image, ctx, imageElement, purl); - } else if (image instanceof ImageRawCCITTFax) { - specializedNode = new LoaderImageNode(image, ctx, imageElement, purl); - } else if (image instanceof ImageGraphics2D) { - ImageGraphics2D g2dImage = (ImageGraphics2D)image; - specializedNode = new Graphics2DNode(g2dImage); - } else { - ctx.getUserAgent().displayError( - new ImageException("Cannot convert an image to a usable format: " + purl)); - } - - Rectangle2D imgBounds = getImageBounds(ctx, imageElement); - Rectangle2D bounds = specializedNode.getPrimitiveBounds(); - float [] vb = new float[4]; - vb[0] = 0; // x - vb[1] = 0; // y - vb[2] = (float) bounds.getWidth(); // width - vb[3] = (float) bounds.getHeight(); // height - - // handles the 'preserveAspectRatio', 'overflow' and 'clip' - // and sets the appropriate AffineTransform to the image node - initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds); - return specializedNode; - } catch (Exception e) { - ctx.getUserAgent().displayError(e); - } - - return superCreateGraphicsNode(ctx, imageElement, purl); - } - - /** - * Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode. - * @param ctx the bridge context - * @param imageElement the image element - * @param purl the parsed URL - * @return the newly created graphics node - * @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element) - */ - protected GraphicsNode superCreateGraphicsNode - (BridgeContext ctx, Element imageElement, ParsedURL purl) { - return super.createImageGraphicsNode(ctx, imageElement, purl); - } - - - /** - * An image node for natively handled Image instance. - * This holds a natively handled image so that it can be drawn into - * the PDFGraphics2D. - */ - public class LoaderImageNode extends AbstractGraphicsNode { - - private Image image; - private BridgeContext ctx; - private Element imageElement; - private ParsedURL purl; - private GraphicsNode origGraphicsNode = null; - - /** - * Create a new image node for drawing natively handled images - * into PDF graphics. - * @param image the JPEG image - * @param ctx the bridge context - * @param imageElement the SVG image element - * @param purl the URL to the image - */ - public LoaderImageNode(Image image, BridgeContext ctx, - Element imageElement, ParsedURL purl) { - this.image = image; - this.ctx = ctx; - this.imageElement = imageElement; - this.purl = purl; - } - - /** {@inheritDoc} */ - public Shape getOutline() { - return getPrimitiveBounds(); - } - - /** {@inheritDoc} */ - public void primitivePaint(Graphics2D g2d) { - if (g2d instanceof PDFGraphics2D) { - PDFGraphics2D pdfg = (PDFGraphics2D) g2d; - float x = 0; - float y = 0; - try { - float width = image.getSize().getWidthPx(); - float height = image.getSize().getHeightPx(); - pdfg.addNativeImage(image, x, y, width, height); - } catch (Exception e) { - ctx.getUserAgent().displayError(e); - } - } else { - // Not going directly into PDF so use - // original implementation so filters etc work. - if (origGraphicsNode == null) { - // Haven't constructed baseclass Graphics Node, - // so do so now. - origGraphicsNode - = PDFImageElementBridge.this.superCreateGraphicsNode - (ctx, imageElement, purl); - } - origGraphicsNode.primitivePaint(g2d); - } - } - - /** {@inheritDoc} */ - public Rectangle2D getGeometryBounds() { - return getPrimitiveBounds(); - } - - /** {@inheritDoc} */ - public Rectangle2D getPrimitiveBounds() { - return new Rectangle2D.Double(0, 0, - image.getSize().getWidthPx(), - image.getSize().getHeightPx()); - } - - /** {@inheritDoc} */ - public Rectangle2D getSensitiveBounds() { - //No interactive features, just return primitive bounds - return getPrimitiveBounds(); - } - - } - - /** - * A node that holds a Graphics2D image. - */ - public class Graphics2DNode extends AbstractGraphicsNode { - - private ImageGraphics2D image; - - /** - * Create a new Graphics2D node. - * @param g2d the Graphics2D image - */ - public Graphics2DNode(ImageGraphics2D g2d) { - this.image = g2d; - } - - /** {@inheritDoc} */ - public Shape getOutline() { - return getPrimitiveBounds(); - } - - /** {@inheritDoc} */ - public void primitivePaint(Graphics2D g2d) { - int width = image.getSize().getWidthPx(); - int height = image.getSize().getHeightPx(); - Rectangle2D area = new Rectangle2D.Double(0, 0, width, height); - image.getGraphics2DImagePainter().paint(g2d, area); - } - - /** {@inheritDoc} */ - public Rectangle2D getGeometryBounds() { - return getPrimitiveBounds(); - } - - /** {@inheritDoc} */ - public Rectangle2D getPrimitiveBounds() { - return new Rectangle2D.Double(0, 0, - image.getSize().getWidthPx(), - image.getSize().getHeightPx()); - } - - /** {@inheritDoc} */ - public Rectangle2D getSensitiveBounds() { - //No interactive features, just return primitive bounds - return getPrimitiveBounds(); - } + /** {@inheritDoc} */ + protected ImageFlavor[] getSupportedFlavours() { + return supportedFlavors; } } diff --git a/src/java/org/apache/fop/svg/PDFTextElementBridge.java b/src/java/org/apache/fop/svg/PDFTextElementBridge.java index 4c11aa97e..c983d2b45 100644 --- a/src/java/org/apache/fop/svg/PDFTextElementBridge.java +++ b/src/java/org/apache/fop/svg/PDFTextElementBridge.java @@ -19,13 +19,7 @@ package org.apache.fop.svg; -import org.apache.batik.bridge.BridgeContext; -import org.apache.batik.bridge.SVGTextElementBridge; -import org.apache.batik.gvt.GraphicsNode; -import org.apache.batik.gvt.TextNode; import org.apache.batik.gvt.TextPainter; -import org.apache.fop.fonts.FontInfo; -import org.w3c.dom.Element; /** * Bridge class for the <text> element. @@ -34,41 +28,15 @@ import org.w3c.dom.Element; * * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> */ -public class PDFTextElementBridge extends SVGTextElementBridge { - - private PDFTextPainter pdfTextPainter; +public class PDFTextElementBridge extends AbstractFOPTextElementBridge { /** * Constructs a new bridge for the <text> element. - * @param fi the font information - */ - public PDFTextElementBridge(FontInfo fi) { - pdfTextPainter = new PDFTextPainter(fi); - } - - /** - * Create a text element bridge. - * This set the text painter on the node if the text is simple. - * @param ctx the bridge context - * @param e the svg element - * @return the text graphics node created by the super class + * + * @param textPainter the text painter to use */ - public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) { - GraphicsNode node = super.createGraphicsNode(ctx, e); - if (node != null) { - //Set our own text painter - ((TextNode)node).setTextPainter(getTextPainter()); - } - return node; + public PDFTextElementBridge(TextPainter textPainter) { + super(textPainter); } - - /** - * Returns the TextPainter instance used by this bridge. - * @return the text painter - */ - public TextPainter getTextPainter() { - return pdfTextPainter; - } - } diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java index 06fea54cc..8a0feb3a2 100644 --- a/src/java/org/apache/fop/svg/PDFTextPainter.java +++ b/src/java/org/apache/fop/svg/PDFTextPainter.java @@ -43,7 +43,6 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter; import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; import org.apache.batik.gvt.text.TextPaintInfo; import org.apache.batik.gvt.text.TextSpanLayout; - import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; @@ -63,8 +62,8 @@ public class PDFTextPainter extends StrokingTextPainter { private static final boolean DEBUG = false; - private boolean strokeText = false; - private FontInfo fontInfo; + private final boolean strokeText = false; + private final FontInfo fontInfo; /** * Create a new PDF text painter with the given font information. @@ -280,7 +279,7 @@ public class PDFTextPainter extends StrokingTextPainter { Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE); String style = ((posture != null) && (posture.floatValue() > 0.0)) - ? "italic" : "normal"; + ? Font.STYLE_ITALIC : Font.STYLE_NORMAL; int weight = ((taWeight != null) && (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL; diff --git a/src/java/org/apache/fop/util/AbstractPaintingState.java b/src/java/org/apache/fop/util/AbstractPaintingState.java new file mode 100644 index 000000000..4fb6b173c --- /dev/null +++ b/src/java/org/apache/fop/util/AbstractPaintingState.java @@ -0,0 +1,531 @@ +/* + * 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.Color; +import java.awt.geom.AffineTransform; +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +/** + * A base class which holds information about the current painting state. + */ +public abstract class AbstractPaintingState implements Cloneable, Serializable { + + private static final long serialVersionUID = 5998356138437094188L; + + /** current state data */ + private AbstractData data = null; + + /** the state stack */ + private StateStack/*<AbstractData>*/ stateStack = new StateStack/*<AbstractData>*/(); + + /** + * Instantiates a new state data object + * + * @return a new state data object + */ + protected abstract AbstractData instantiateData(); + + /** + * Instantiates a new state object + * + * @return a new state object + */ + protected abstract AbstractPaintingState instantiate(); + + /** + * Returns the currently valid state + * + * @return the currently valid state + */ + public AbstractData getData() { + if (data == null) { + data = instantiateData(); + } + return data; + } + + /** + * Set the current color. + * Check if the new color is a change and then set the current color. + * + * @param col the color to set + * @return true if the color has changed + */ + public boolean setColor(Color col) { + if (!col.equals(getData().color)) { + getData().color = col; + return true; + } + return false; + } + + /** + * Get the color. + * + * @return the color + */ + public Color getColor() { + if (getData().color == null) { + getData().color = Color.black; + } + return getData().color; + } + + /** + * Get the background color. + * + * @return the background color + */ + public Color getBackColor() { + if (getData().backColor == null) { + getData().backColor = Color.white; + } + return getData().backColor; + } + + /** + * Set the current background color. + * Check if the new background color is a change and then set the current background color. + * + * @param col the background color to set + * @return true if the color has changed + */ + public boolean setBackColor(Color col) { + if (!col.equals(getData().backColor)) { + getData().backColor = col; + return true; + } + return false; + } + + /** + * Set the current font name + * + * @param internalFontName the internal font name + * @return true if the font name has changed + */ + public boolean setFontName(String internalFontName) { + if (!internalFontName.equals(getData().fontName)) { + getData().fontName = internalFontName; + return true; + } + return false; + } + + /** + * Gets the current font name + * + * @return the current font name + */ + public String getFontName() { + return getData().fontName; + } + + /** + * Gets the current font size + * + * @return the current font size + */ + public int getFontSize() { + return getData().fontSize; + } + + /** + * Set the current font size. + * Check if the font size is a change and then set the current font size. + * + * @param size the font size to set + * @return true if the font size has changed + */ + public boolean setFontSize(int size) { + if (size != getData().fontSize) { + getData().fontSize = size; + return true; + } + return false; + } + + /** + * Set the current line width. + * + * @param width the line width in points + * @return true if the line width has changed + */ + public boolean setLineWidth(float width) { + if (getData().lineWidth != width) { + getData().lineWidth = width; + return true; + } + return false; + } + + /** + * Returns the current line width + * + * @return the current line width + */ + public float getLineWidth() { + return getData().lineWidth; + } + + /** + * Sets the dash array (line type) for the current basic stroke + * + * @param dash the line dash array + * @return true if the dash array has changed + */ + public boolean setDashArray(float[] dash) { + if (!Arrays.equals(dash, getData().dashArray)) { + getData().dashArray = dash; + return true; + } + return false; + } + + /** + * Get the current transform. + * This gets the combination of all transforms in the + * current state. + * + * @return the calculate combined transform for the current state + */ + public AffineTransform getTransform() { + AffineTransform at = new AffineTransform(); + for (Iterator iter = stateStack.iterator(); iter.hasNext();) { + AbstractData data = (AbstractData)iter.next(); + AffineTransform stackTrans = data.getTransform(); + at.concatenate(stackTrans); + } + AffineTransform currentTrans = getData().getTransform(); + at.concatenate(currentTrans); + return at; + } + + /** + * Check the current transform. + * The transform for the current state is the combination of all + * transforms in the current state. The parameter is compared + * against this current transform. + * + * @param tf the transform the check against + * @return true if the new transform is different then the current transform + */ + public boolean checkTransform(AffineTransform tf) { + return !tf.equals(getData().getTransform()); + } + + /** + * Get a copy of the base transform for the page. Used to translate + * IPP/BPP values into X,Y positions when positioning is "fixed". + * + * @return the base transform, or null if the state stack is empty + */ + public AffineTransform getBaseTransform() { + if (stateStack.isEmpty()) { + return null; + } else { + AbstractData baseData = (AbstractData)stateStack.get(0); + return (AffineTransform) baseData.getTransform().clone(); + } + } + + /** + * Concatenates the given AffineTransform to the current one. + * + * @param at the transform to concatenate to the current level transform + */ + public void concatenate(AffineTransform at) { + getData().concatenate(at); + } + + /** + * Resets the current AffineTransform to the Base AffineTransform. + */ + public void resetTransform() { + getData().setTransform(getBaseTransform()); + } + + /** + * Clears the current AffineTransform to the Identity AffineTransform + */ + public void clearTransform() { + getData().clearTransform(); + } + + + /** + * Save the current painting state. + * This pushes the current painting state onto the stack. + * This call should be used when the Q operator is used + * so that the state is known when popped. + */ + public void save() { + AbstractData copy = (AbstractData)getData().clone(); + stateStack.push(copy); + } + + /** + * Restore the current painting state. + * This pops the painting state from the stack and sets current values to popped state. + * + * @return the restored state, null if the stack is empty + */ + public AbstractData restore() { + if (!stateStack.isEmpty()) { + setData((AbstractData)stateStack.pop()); + return this.data; + } else { + return null; + } + } + + /** + * Save all painting state data. + * This pushes all painting state data in the given list to the stack + * + * @param dataList a state data list + */ + public void saveAll(List/*<AbstractData>*/ dataList) { + Iterator it = dataList.iterator(); + while (it.hasNext()) { + // save current data on stack + save(); + setData((AbstractData)it.next()); + } + } + + /** + * Restore all painting state data. + * This pops all painting state data from the stack + * + * @return a list of state data popped from the stack + */ + public List/*<AbstractData>*/ restoreAll() { + List/*<AbstractData>*/ dataList = new java.util.ArrayList/*<AbstractData>*/(); + AbstractData data; + while (true) { + data = getData(); + if (restore() == null) { + break; + } + // insert because of stack-popping + dataList.add(0, data); + } + return dataList; + } + + /** + * Sets the current state data + * + * @param currentData state data + */ + protected void setData(AbstractData data) { + this.data = data; + } + + /** + * Clears the state stack + */ + public void clear() { + stateStack.clear(); + setData(null); + } + + /** + * Return the state stack + * + * @return the state stack + */ + protected Stack/*<AbstractData>*/ getStateStack() { + return this.stateStack; + } + + /** {@inheritDoc} */ + public Object clone() { + AbstractPaintingState state = instantiate(); + state.stateStack = new StateStack(this.stateStack); + state.data = (AbstractData)this.data.clone(); + return state; + } + + /** {@inheritDoc} */ + public String toString() { + return ", stateStack=" + stateStack + + ", currentData=" + data; + } + + + /** + * A stack implementation which holds state objects + */ + public class StateStack extends java.util.Stack { + + private static final long serialVersionUID = 4897178211223823041L; + + /** + * Default constructor + */ + public StateStack() { + super(); + } + + /** + * Copy constructor + * + * @param c initial contents of stack + */ + public StateStack(Collection c) { + elementCount = c.size(); + // 10% for growth + elementData = new Object[ + (int)Math.min((elementCount * 110L) / 100, Integer.MAX_VALUE)]; + c.toArray(elementData); + } + } + + + /** + * A base painting state data holding object + */ + public abstract class AbstractData implements Cloneable, Serializable { + + private static final long serialVersionUID = 5208418041189828624L; + + /** The current color */ + protected Color color = null; + + /** The current background color */ + protected Color backColor = null; + + /** The current font name */ + protected String fontName = null; + + /** The current font size */ + protected int fontSize = 0; + + /** The current line width */ + protected float lineWidth = 0; + + /** The dash array for the current basic stroke (line type) */ + protected float[] dashArray = null; + + /** The current transform */ + protected AffineTransform transform = null; + + /** + * Returns a newly create data object + * + * @return a new data object + */ + protected abstract AbstractData instantiate(); + + /** + * Concatenate the given AffineTransform with the current thus creating + * a new viewport. Note that all concatenation operations are logged + * so they can be replayed if necessary (ex. for block-containers with + * "fixed" positioning. + * + * @param at Transformation to perform + */ + public void concatenate(AffineTransform at) { + getTransform().concatenate(at); + } + + /** + * Get the current AffineTransform. + * + * @return the current transform + */ + public AffineTransform getTransform() { + if (transform == null) { + transform = new AffineTransform(); + } + return transform; + } + + /** + * Sets the current AffineTransform. + */ + public void setTransform(AffineTransform baseTransform) { + this.transform = baseTransform; + } + + /** + * Resets the current AffineTransform. + */ + public void clearTransform() { + transform = new AffineTransform(); + } + + /** + * Returns the derived rotation from the current transform + * + * @return the derived rotation from the current transform + */ + public int getDerivedRotation() { + AffineTransform at = getTransform(); + double sx = at.getScaleX(); + double sy = at.getScaleY(); + double shx = at.getShearX(); + double shy = at.getShearY(); + int rotation = 0; + if (sx == 0 && sy == 0 && shx > 0 && shy < 0) { + rotation = 270; + } else if (sx < 0 && sy < 0 && shx == 0 && shy == 0) { + rotation = 180; + } else if (sx == 0 && sy == 0 && shx < 0 && shy > 0) { + rotation = 90; + } else { + rotation = 0; + } + return rotation; + } + + /** {@inheritDoc} */ + public Object clone() { + AbstractData data = instantiate(); + data.color = this.color; + data.backColor = this.backColor; + data.fontName = this.fontName; + data.fontSize = this.fontSize; + data.lineWidth = this.lineWidth; + data.dashArray = this.dashArray; + data.transform = new AffineTransform(this.transform); + return data; + } + + /** {@inheritDoc} */ + public String toString() { + return "color=" + color + + ", backColor=" + backColor + + ", fontName=" + fontName + + ", fontSize=" + fontSize + + ", lineWidth=" + lineWidth + + ", dashArray=" + dashArray + + ", transform=" + transform; + } + } +} diff --git a/status.xml b/status.xml index 23dc66b39..0f139fba7 100644 --- a/status.xml +++ b/status.xml @@ -53,6 +53,18 @@ <changes> <release version="FOP Trunk" date="TBD"> + <action context="Renderers" dev="AC" importance="high" type="add"> + AFP Output: An AFPGraphics2D implementation which provides the ability to use Batik to drive the production of AFP Graphics (GOCA) output from SVG. + </action> + <action context="Renderers" dev="AC" importance="high" type="add"> + AFP Output: Resource group leveling, external streaming, and de-duplication of images and graphics using IncludeObject and ResourceGroup. + </action> + <action context="Renderers" dev="AC" importance="high" type="add"> + AFP Output: Native image embedding support (e.g. JPEG, GIF, TIFF) using ObjectContainer and a MOD:CA Registry implementation. + </action> + <action context="Fonts" dev="AC" type="fix"> + More robust AFP font parsing, although it is still in need of some rework in the future. + </action> <action context="Images" dev="JM" type="add" fixes-bug="41657"> Added support for SVG 1.2 functionality inside fo:instream-foreign-object. </action> @@ -156,10 +168,6 @@ offer an implementation for addCharacters() should take care to make similar modifications in their code !!</em> </action> - <!-- change reverted, to be added back later - <action context="Renderers" dev="AC" importance="high" type="add"> - Added SVG support for AFP (GOCA). - </action --> <action context="Renderers" dev="JM" type="add" fixes-bug="45115" due-to="Martin Edge"> Added a PCL-specific extension attribute on simple-page-master for controlling the simplex/duplex mode. diff --git a/test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml b/test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml new file mode 100644 index 000000000..e6131308a --- /dev/null +++ b/test/layoutengine/standard-testcases/table-row_keep-with-previous_2.xml @@ -0,0 +1,254 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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$ --> +<testcase> + <info> + <p> + This test checks that keep-with-previous works on table-row. + </p> + </info> + <fo> + <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <fo:layout-master-set> + <fo:simple-page-master master-name="page" page-height="3in" page-width="5in" + margin="0.5in"> + <fo:region-body background-color="#F0F0F0"/> + </fo:simple-page-master> + </fo:layout-master-set> + + <!-- table 1 --> + <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt"> + <fo:flow flow-name="xsl-region-body"> + <fo:block space-after="106pt">1. Before the table</fo:block> + <fo:table width="100%" table-layout="fixed" + border-collapse="separate" border="4pt solid black"> + <fo:table-column number-columns-repeated="2" + column-width="proportional-column-width(1)"/> + <fo:table-body> + <fo:table-row> + <fo:table-cell border="2pt solid blue"> + <fo:block>Cell 1.1 Line 1</fo:block> + <fo:block>Cell 1.1 Line 2</fo:block> + </fo:table-cell> + <fo:table-cell border="2pt solid teal"> + <fo:block>Cell 1.2 Line 1</fo:block> + <fo:block>Cell 1.2 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row keep-with-previous="always"> + <fo:table-cell border="2pt solid green"> + <fo:block>Cell 2.1 Line 1</fo:block> + <fo:block>Cell 2.1 Line 2</fo:block> + </fo:table-cell> + <fo:table-cell border="2pt solid olive"> + <fo:block>Cell 3.1 Line 1</fo:block> + <fo:block>Cell 3.1 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + <fo:block>After the table</fo:block> + </fo:flow> + </fo:page-sequence> + + <!-- table 2 --> + <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt"> + <fo:flow flow-name="xsl-region-body"> + <fo:block space-after="106pt">2. Before the table</fo:block> + <fo:table width="100%" table-layout="fixed" + border-collapse="separate" border="4pt solid black"> + <fo:table-column number-columns-repeated="2" + column-width="proportional-column-width(1)"/> + <fo:table-body> + <fo:table-row> + <fo:table-cell border="2pt solid blue"> + <fo:block>Cell 1.1 Line 1</fo:block> + <fo:block>Cell 1.1 Line 2</fo:block> + </fo:table-cell> + <fo:table-cell border="2pt solid teal" number-rows-spanned="2"> + <fo:block>Cell 1.2 Line 1</fo:block> + <fo:block>Cell 1.2 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row keep-with-previous="always"> + <fo:table-cell border="2pt solid green"> + <fo:block>Cell 2.1 Line 1</fo:block> + <fo:block>Cell 2.1 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + <fo:block>After the table</fo:block> + </fo:flow> + </fo:page-sequence> + + <!-- table 3 --> + <fo:page-sequence master-reference="page" font-size="8pt" line-height="10pt"> + <fo:flow flow-name="xsl-region-body"> + <fo:block space-after="124">3. Before the table</fo:block> + <fo:block>Before the table</fo:block> + <fo:table width="100%" table-layout="fixed" + border-collapse="collapse" border="4pt solid black"> + <fo:table-column number-columns-repeated="2" + column-width="proportional-column-width(1)"/> + <fo:table-body> + <fo:table-row keep-with-previous="always"> + <fo:table-cell border="2pt solid blue" number-rows-spanned="2"> + <fo:block>Cell 1.1 Line 1</fo:block> + <fo:block>Cell 1.1 Line 2</fo:block> + </fo:table-cell> + <fo:table-cell border="2pt solid teal"> + <fo:block>Cell 1.2 Line 1</fo:block> + <fo:block>Cell 1.2 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + <fo:table-row> + <fo:table-cell border="2pt solid olive"> + <fo:block>Cell 2.1 Line 1</fo:block> + <fo:block>Cell 2.1 Line 2</fo:block> + </fo:table-cell> + </fo:table-row> + </fo:table-body> + </fo:table> + <fo:block>After the table</fo:block> + </fo:flow> + </fo:page-sequence> + + </fo:root> + </fo> + <checks> + + <!-- table 1 --> + <eval expected="2" xpath="count(//pageSequence[1]/pageViewport)"/> + <!-- page 1 --> + <eval expected="2" xpath="count(//pageViewport[@nr=1]//flow/block)"/> + <eval expected="1. Before the table" xpath="//pageViewport[@nr=1]//flow/block[1]/lineArea"/> + <eval expected="12000" xpath="//pageViewport[@nr=1]//flow/block[2]/@bpd"/> + <eval expected="16000" xpath="//pageViewport[@nr=1]//flow/block[2]/@bpda"/> + <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=1]//flow/block[2]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=1]//flow/block[2]/@border-after"/> + <!-- cell 1.1 --> + <eval expected="10000" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@bpda"/> + <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[1]/block)"/> + <eval expected="Cell 1.1 Line 1" xpath="//pageViewport[@nr=1]//flow/block[2]/block[1]/block/lineArea"/> + <!-- cell 1.2 --> + <eval expected="10000" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@bpda"/> + <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=1]//flow/block[2]/block[2]/block)"/> + <eval expected="Cell 1.2 Line 1" xpath="//pageViewport[@nr=1]//flow/block[2]/block[2]/block/lineArea"/> + <!-- page 2 --> + <eval expected="2" xpath="count(//pageViewport[@nr=2]//flow/block)"/> + <eval expected="After the table" xpath="//pageViewport[@nr=2]//flow/block[2]/lineArea"/> + <eval expected="36000" xpath="//pageViewport[@nr=2]//flow/block[1]/@bpd"/> + <eval expected="40000" xpath="//pageViewport[@nr=2]//flow/block[1]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-before"/> + <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=2]//flow/block[1]/@border-after"/> + <!-- cell 1.1 --> + <eval expected="10000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-before"/> + <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[1]/block)"/> + <eval expected="Cell 1.1 Line 2" xpath="//pageViewport[@nr=2]//flow/block[1]/block[1]/block/lineArea"/> + <!-- cell 1.2 --> + <eval expected="10000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-before"/> + <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=2]//flow/block[1]/block[2]/block)"/> + <eval expected="Cell 1.2 Line 2" xpath="//pageViewport[@nr=2]//flow/block[1]/block[2]/block/lineArea"/> + <!-- cell 2.1 --> + <eval expected="20000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpd"/> + <eval expected="24000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@bpda"/> + <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-before"/> + <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[3]/@border-after"/> + <!-- cell 2.2 --> + <eval expected="20000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpd"/> + <eval expected="24000" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@bpda"/> + <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-before"/> + <eval expected="(solid,#808000,2000)" xpath="//pageViewport[@nr=2]//flow/block[1]/block[4]/@border-after"/> + + <!-- table 2 --> + <eval expected="2" xpath="count(//pageSequence[2]/pageViewport)"/> + <!-- page 1 --> + <eval expected="2" xpath="count(//pageViewport[@nr=3]//flow/block)"/> + <eval expected="2. Before the table" xpath="//pageViewport[@nr=3]//flow/block[1]/lineArea"/> + <eval expected="12000" xpath="//pageViewport[@nr=3]//flow/block[2]/@bpd"/> + <eval expected="16000" xpath="//pageViewport[@nr=3]//flow/block[2]/@bpda"/> + <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=3]//flow/block[2]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=3]//flow/block[2]/@border-after"/> + <!-- cell 1.1 --> + <eval expected="10000" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@bpda"/> + <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[1]/block)"/> + <eval expected="Cell 1.1 Line 1" xpath="//pageViewport[@nr=3]//flow/block[2]/block[1]/block/lineArea"/> + <!-- cell 1.2 --> + <eval expected="10000" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@bpda"/> + <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-before"/> + <eval expected="" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=3]//flow/block[2]/block[2]/block)"/> + <eval expected="Cell 1.2 Line 1" xpath="//pageViewport[@nr=3]//flow/block[2]/block[2]/block/lineArea"/> + <!-- page 2 --> + <eval expected="2" xpath="count(//pageViewport[@nr=4]//flow/block)"/> + <eval expected="After the table" xpath="//pageViewport[@nr=4]//flow/block[2]/lineArea"/> + <eval expected="36000" xpath="//pageViewport[@nr=4]//flow/block[1]/@bpd"/> + <eval expected="40000" xpath="//pageViewport[@nr=4]//flow/block[1]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-before"/> + <eval expected="(solid,#000000,4000)" xpath="//pageViewport[@nr=4]//flow/block[1]/@border-after"/> + <!-- cell 1.1 --> + <eval expected="10000" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpd"/> + <eval expected="12000" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-before"/> + <eval expected="(solid,#0000ff,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[1]/block)"/> + <eval expected="Cell 1.1 Line 2" xpath="//pageViewport[@nr=4]//flow/block[1]/block[1]/block/lineArea"/> + <!-- cell 2.1 --> + <eval expected="20000" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpd"/> + <eval expected="24000" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@bpda"/> + <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-before"/> + <eval expected="(solid,#008000,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[2]/@border-after"/> + <!-- cell 1.2 --> + <eval expected="34000" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpd"/> + <eval expected="36000" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@bpda"/> + <eval expected="" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-before"/> + <eval expected="(solid,#008080,2000)" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/@border-after"/> + <eval expected="1" xpath="count(//pageViewport[@nr=4]//flow/block[1]/block[3]/block)"/> + <eval expected="Cell 1.2 Line 2" xpath="//pageViewport[@nr=4]//flow/block[1]/block[3]/block/lineArea"/> + + <!-- table 3 --> + <eval expected="2" xpath="count(//pageSequence[3]/pageViewport)"/> + <!-- page 1 --> + <eval expected="1" xpath="count(//pageViewport[@nr=5]//flow/block)"/> + <eval expected="3. Before the table" xpath="//pageViewport[@nr=5]//flow/block[1]/lineArea"/> + <!-- page 2 --> + <eval expected="3" xpath="count(//pageViewport[@nr=6]//flow/block)"/> + <eval expected="Before the table" xpath="//pageViewport[@nr=6]//flow/block[1]/lineArea"/> + <eval expected="46000" xpath="//pageViewport[@nr=6]//flow/block[2]/@bpd"/> + <eval expected="46000" xpath="//pageViewport[@nr=6]//flow/block[2]/@bpda"/> + <eval expected="After the table" xpath="//pageViewport[@nr=6]//flow/block[3]/lineArea"/> + + </checks> +</testcase> |