xhtmlrenderer-0.0~R8.orig/0000700000000000000000000000000011513457774012475 5ustar xhtmlrenderer-0.0~R8.orig/etc/0000755000000000000000000000000011076705610013247 5ustar xhtmlrenderer-0.0~R8.orig/etc/build/0000755000000000000000000000000011172155756014355 5ustar xhtmlrenderer-0.0~R8.orig/etc/build/demo-apps.xml0000644000000000000000000000664711144703646016775 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/preset-defs.xml0000644000000000000000000000427411172155756017327 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/netbeans.xml0000644000000000000000000000344110327031662016666 0ustar This target can only run inside the NetBeans IDE. xhtmlrenderer-0.0~R8.orig/etc/build/upload.xml0000644000000000000000000000746711172200254016361 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/compile.xml0000644000000000000000000000423011172155756016526 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/tests.xml0000644000000000000000000002256311172220300016223 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/docs.xml0000644000000000000000000000342411172162000016006 0ustar
Flying Saucer Project Release ${app.version}
<a href='http://xhtmlrenderer.dev.java.net'>Flying Saucer Project Home</a>
xhtmlrenderer-0.0~R8.orig/etc/build/convert.xml0000644000000000000000000000254511171137074016555 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/properties.xml0000644000000000000000000002046111172215520017260 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/dist.xml0000644000000000000000000002357711172440434016046 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/jars.xml0000644000000000000000000001004011172170724016021 0ustar xhtmlrenderer-0.0~R8.orig/etc/build/build.properties0000644000000000000000000000122410221316352017552 0ustar # Used by Ant to override default properties in Ant build file. # It is read automatically every time an Ant target is called # for the project. # # This is a *shared* properties file, do not modify unless you # are sure the new values will work for other developers. # Example #build.compiler = jikes # # $Id: build.properties,v 1.1 2005/03/26 12:03:30 pdoubleya Exp $ # # $Log: build.properties,v $ # Revision 1.1 2005/03/26 12:03:30 pdoubleya # Added to CVS. # # Revision 1.2 2004/10/18 10:10:27 pdoubleya # Changed to be sample only, no properties set--moved to build2.xml. # # Revision 1.1 2004/10/15 13:07:24 pdoubleya # Added to CVS. # # xhtmlrenderer-0.0~R8.orig/etc/build/clean.xml0000644000000000000000000000107310221316352016143 0ustar xhtmlrenderer-0.0~R8.orig/README0000644000000000000000000000576211172364504013366 0ustar Flying Saucer Release R8 April 18, 2009 https://xhtmlrenderer.dev.java.net Please see project website for links to CVS, mailing lists, issue tracker, etc. OVERVIEW -------- Flying Saucer is a pure-Java library for rendering arbitrary well-formed XML (or XHTML) using CSS 2.1 for layout and formatting, output to Swing panels, PDF, and images. Comprehensive documentation available in our user's guide, linked from our website at http://xhtmlrenderer.dev.java.net. For information on our development releases (R8preX), please contact us on our mailing lists. If you end up using Flying Saucer for your own projects, please drop us an email and tell us about it; it helps inform where we go next, and is interesting and inspiring to other developers. LICENSE ------- Flying Saucer is distributed under the LGPL.Flying Saucer itself is licensed under the GNU Lesser General Public License, version 2.1 or later, available at http://www.gnu.org/copyleft/lesser.html. You can use Flying Saucer in any way and for any purpose you want as long as you respect the terms of the license. A copy of the LGPL license is included as license-lgpl-2.1.txt in our distributions and in our source tree. Flying Saucer uses a couple of FOSS packages to get the job done. A list of these, along with the license they each have, is listed in the LICENSE file in our distribution. WHAT'S IN THE DISTRIBUTION -------------------------- "BINARY" DISTRIBUTION --------------------- The binary distribution includes only those files you need to *use* Fying Saucer in your own programs. The files are all Java JAR files and just need to be included in the CLASSPATH as described in the User's Guide. * core-renderer.jar: the main file, always in the classpath * itext*.jar: support for generating PDF files as output * core-renderer-minimal.jar: see note at end of this section In principle, for an application using only Swing JPanels for output, you could restrict yourself to using core-renderer.jar; however, we recommend you include core*, itext* and to avoid any linking errors/ClassNotFoundExceptions. When in doubt, contact us via mail. "SOURCE" DISTRIBUTION --------------------- The source distribution includes all the relevant source code, libraries and build scripts to build and extend Flying Saucer. You'll need Ant if you want to use our build scripts. There are some files under source control (notes, some docs) which are not included in the source distribution. You can pull the whole lot from our source tree by visiting our project website (URL at top of this doc) and extracting from source control. GETTING STARTED --------------- Please see the user's guide (URLs listed above) for info on how to get started. At a minimum, you'll need core-renderer.jar in your classpath; itext*.jar for PDF output. Some good entry points (classes) are: org.xhtmlrenderer.simple.XHTMLPanel org.xhtmlrenderer.simple.PDFRenderer org.xhtmlrenderer.simple.ImageRenderer xhtmlrenderer-0.0~R8.orig/src/0000755000000000000000000000000011172434416013263 5ustar xhtmlrenderer-0.0~R8.orig/src/docs/0000755000000000000000000000000011076705622014216 5ustar xhtmlrenderer-0.0~R8.orig/src/docs/index.html0000644000000000000000000000042510136265376016217 0ustar

XHTML Renderer Documentation

slim javadocs for users


full javadocs for developers only
full code

xhtmlrenderer-0.0~R8.orig/src/conf/0000755000000000000000000000000011161571150014203 5ustar xhtmlrenderer-0.0~R8.orig/src/conf/xhtmlrenderer.conf0000644000000000000000000003543111161571150017743 0ustar # Configuration file for XHTMLRenderer core # # Follows formatting specified in JavaDoc for java.util.Properties # key = value # # If you define a key in this file, the later one will be used # Comments are ignored, start the line with a # sign. # Feel free to comment liberally # # Naming convention: prefix all keys with # xr. # e.g. xr.render-speed = SUPER_FAST # CSS / CASCADE # # Location of user-agent "default" CSS for renderer xr.css.user-agent-default-css = /resources/css/ # TESTS # # Location of hamlet (large XHTML file) xr.test.files.hamlet = /demos/browser/xhtml/hamlet.xhtml # Format for logging when XRSimpleLogFormatter is used as the log output # formatter. The format string for this key follows # java.text.MessageFormat. The following replaceable parameters are # substituted into the output message string; you can use one, all--at a # minimum, you probably want the log record message. A newline is # automatically added at the end of each message. # # {0} String.valueOf(record.getMillis()), # {1} record.getLoggerName(), # {2} record.getLevel().toString(), # {3} record.getSourceClassName(), # {4} record.getSourceMethodName(), # {5} record.getMessage() # {6} record.getThrown().getName() # {7} record.getThrown().getMessage() # {8} record.getThrown() stack trace # # Two formats, for with and without exception xr.simple-log-format = {1} {2}:: {5} xr.simple-log-format-throwable = {1} {2}:: {5} # Values used for testing Configuration, do not modify xr.test-config-byte = 8 xr.test-config-short = 16 xr.test-config-int = 100 xr.test-config-long = 2000 xr.test-config-float = 3000.25F xr.test-config-double = 4000.50D xr.test-config-boolean = true # XR logging behavior. Follows conventions in # java.util.logging.LogManager. See there for details. # # The prefix for all entries here should be # xr.util-logging. # # ENABLE OR DISABLE ALL LOGGING # set to false to turn all Flying Saucer logging off, regardless of # other settings; corresponds to static method XRLog.setLoggingEnabled(bool); # xr.util-logging.loggingEnabled=false # Handlers # See JDK documentation for the Logging API; this is a space-separated list of class names that extend the # java.util.logging.Handler class. Each class named here will be instantiated and assigned to the each FS # logger (not the root logger, as the JDK log-properties load mechanism would do it). xr.util-logging.handlers=java.util.logging.ConsoleHandler # Whether our loggers should send their log messages to their parent's handlers as well # In our case, we don't want this, because our log messages will be sent to the handlers # of the root logger, which will log the message as well xr.util-logging.use-parent-handler=false # Log level--you can assign a log level to the handler which processes log messages. # By default, we assign a level to the console handler we attach to our loggers. # See the JDK Logging API documentation. # # The default logging level for new ConsoleHandler instances xr.util-logging.java.util.logging.ConsoleHandler.level=INFO # Log formatter--you can assign a class to format the output of log messages. # Each instance is assigned to a log Handler *which must be one of those listed in the handlers property # above. # # The default formatter for new ConsoleHandler instances. # Default for the JDK, uncomment to use. # java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter # XR log formatter xr.util-logging.java.util.logging.ConsoleHandler.formatter=org.xhtmlrenderer.util.XRSimpleLogFormatter # Log levels # NOTE: the name of this property is .level in the logging spec, hence the two .. xr.util-logging.org.xhtmlrenderer.level = ALL xr.util-logging.org.xhtmlrenderer.config.level = ALL xr.util-logging.org.xhtmlrenderer.exception.level = ALL xr.util-logging.org.xhtmlrenderer.general.level = ALL xr.util-logging.org.xhtmlrenderer.init.level = ALL xr.util-logging.org.xhtmlrenderer.load.level = ALL xr.util-logging.org.xhtmlrenderer.load.xml-entities.level = ALL xr.util-logging.org.xhtmlrenderer.match.level = ALL xr.util-logging.org.xhtmlrenderer.cascade.level = ALL xr.util-logging.org.xhtmlrenderer.css-parse.level = ALL xr.util-logging.org.xhtmlrenderer.layout.level = ALL xr.util-logging.org.xhtmlrenderer.render.level = ALL # resource loading # full classname for the SAX parser to use; should be an implementation # of org.xml.sax.XMLReader # leave blank or "default" to use JDK default parser # # piccolo: com.bluecast.xml.Piccolo # tagsoup: org.ccil.cowan.tagsoup.Parser xr.load.xml-reader=default # : parser features # # not all features are supported by all parsers. if the feature is not supported # , but you request it, the parser will throw an exception and FS will just log that # and keep going. check logs to see if you need to turn these features off. you can # skip all features by setting configure-features to false # whether features should be set at all xr.load.configure-features=false # whether pages should be validated against DTD or schema # ! careful: this will be very picky; pages will be rejected # NOTE! Piccolo will throw an error if validation is on--not supported xr.load.validation=false # whether parser should try to use string.intern # this is experimental, currently only for developers # NOTE!: Piccolo will throw an error if interning is set to true--strings auto-intern'd xr.load.string-interning=false # namespace support works such that one of the two features must be true, and the other false # # whether parser should pass namespace info in during parsing # this is experimental, currently only for developers xr.load.namespaces=false # whether parser should pass namespace attributes declaration attributes during parsing # this is experimental, currently only for developers xr.load.namespace-prefixes=false # layout controls xr.layout.whitespace.experimental = true xr.layout.bad-sizing-hack = false # rendering controls xr.renderer.viewport-repaint=true xr.renderer.draw.backgrounds = true xr.renderer.draw.borders = true xr.renderer.debug.box-outlines = false # text rendering controls using Java2D renderer (default when rendering to Swing panels) # scaling factor for rendering text; 1.25 would be "25% larger than default" xr.text.scale=1.0 # at what font-size should AA kick in. for older JVMs AA is very expensive and slow--set this to # a high value (like 25); for JDK 6, smoke tests show that AA is basically low-cost for Flying Saucer # we set it to a high value for the benefit of users still on JDK 1.4 xr.text.aa-fontsize-threshhold=25 # when using Java2D for rendering, hint to renderer for AA algorithm to use xr.text.aa-rendering-hint=RenderingHints.VALUE_TEXT_ANTIALIAS_HGRB # whether or not to cache stylesheets # note that there is currently no way to remove # stylesheets from the cache xr.cache.stylesheets=false ### a bunch of properties used to turn on and off the incremental ###layout features xr.incremental.enabled=false # use lazy asynchronous image resources instead of normal synchronous ones xr.incremental.lazyimage = false # adds a per block delay of N milleseconds xr.incremental.debug.layoutdelay=0 # prints how long each repaint takes xr.incremental.repaint.print-timing=false # whether or not the threads be used # if false, xr.incremental.enabled is also # implicitly false xr.use.threads=false # whether or not link and hover listeners will be used. xr.use.listeners=true # if BufferedImage should be use # Note: On VMs and platforms with the most up-to-date acceleration techniques, # BufferedImage performs better, but there were serious performance # regressions due to differences in when/if images are accelerated or # not by the VM. In particular, we observed some serious regressions on # Windows even on simple pages like our splash screen. See # https://xhtmlrenderer.dev.java.net/servlets/ReadMsg?list=dev&msgNo=3307 # defaults to false xr.image.buffered=false # image loading # on loading images that need to be scaled # on scaling, whether to use LOW, MID or HIGH-quality process. defaults to HIGH xr.image.scale=LOW # on scaling, what rendering hints to use; must be one of the rendering hints that corresponds to # RenderingHints.KEY_INTERPOLATION (e.g. RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR # VALUE_INTERPOLATION_BILINEAR or VALUE_INTERPOLATION_BICUBIC. Defaults to NEAREST_NEIGHBOR xr.image.render-quality=java.awt.RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR # CVS auto-expanded keywords # $Id: xhtmlrenderer.conf,v 1.49 2009/03/22 15:13:23 pdoubleya Exp $ # # $Log: xhtmlrenderer.conf,v $ # Revision 1.49 2009/03/22 15:13:23 pdoubleya # Follow up for removing Minium AA: font "smoothing level" now deprecated. Changed to use font smoothing threshold alone. Remove corresponding property from configuration file. # # Revision 1.48 2009/03/22 12:27:37 pdoubleya # Remove Minium anti-aliasing library as sources are not available. Removed jar and all references to it. For R8 release. # # Revision 1.47 2008/01/27 16:40:29 pdoubleya # Issues 186 and 130: fix configuration so that logging setup does not override any current settings for JDK logging classes. Disable logging by default. # # Revision 1.46 2007/11/23 07:03:30 pdoubleya # Applied patch from N. Barozzi to allow either toolkit or buffered images to be used, see https://xhtmlrenderer.dev.java.net/servlets/ReadMsg?list=dev&msgNo=3847 # # Revision 1.45 2007/06/20 12:09:07 pdoubleya # re-added missing text AA properties # # Revision 1.44 2007/05/23 16:50:17 peterbrant # Remove obsolete comment # # Revision 1.42 2007/04/10 21:40:28 pdoubleya # Support for varied scaling routines for images; fix image caching-bug; add some way to handle missing images. # # Revision 1.41 2007/04/07 15:22:47 pdoubleya # New image scaling properties # # Revision 1.40 2006/08/03 14:11:03 pdoubleya # Comments # # Revision 1.39 2006/07/17 22:15:58 pdoubleya # Added loggingEnabled switch to XRLog and config file; default logging to off there and in Configuration. Fix for Issue Tracker #123. # # Revision 1.38 2006/02/22 02:20:18 peterbrant # Links and hover work again # # Revision 1.37 2005/11/11 01:37:12 peterbrant # Turn threads back on (xr.use.threads=false committed by mistake) # # Revision 1.36 2005/11/11 01:32:50 peterbrant # Add option to turn off stylesheet caching # # Revision 1.35 2005/11/05 18:43:49 peterbrant # Disable incremental rendering for now # # Revision 1.34 2005/10/23 22:16:41 tobega # Preparation for StackingContext rendering # # Revision 1.33 2005/10/20 22:51:38 peterbrant # Add non-threaded rendering mode # # Revision 1.32 2005/10/16 23:57:14 tobega # Starting experiment with flat representation of render tree # # Revision 1.31 2005/10/02 21:29:57 tobega # Fixed a lot of concurrency (and other) issues from incremental rendering. Also some house-cleaning. # # Revision 1.30 2005/09/29 21:34:01 joshy # minor updates to a lot of files. pulling in more incremental rendering code. # fixed another resize bug # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.29 2005/09/28 00:03:29 joshy # removed cruft from BasicPanel # turned of incremental layout and lazy images by default # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.28 2005/09/27 23:48:38 joshy # first merge of basicpanel reworking and incremental layout. more to come. # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.27 2005/07/15 23:39:49 joshy # updates to try to fix the resize issue # # Revision 1.26 2005/06/26 15:48:09 tobega # Converted to almost standard html4 default css, which shook out a bug: position should not inherit # # Revision 1.25 2005/06/16 18:34:09 joshy # support for clear:right # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.24 2005/06/15 17:54:13 pdoubleya # Default to not configure parser features. # # Revision 1.23 2005/04/20 19:13:16 tobega # Fixed vertical align. Middle works and all look pretty much like in firefox # # Revision 1.22 2005/04/07 16:36:04 pdoubleya # Added level for config. # # Revision 1.21 2005/03/27 18:37:50 pdoubleya # Added logging control for entity resolution. # # Revision 1.20 2005/02/05 17:18:56 pdoubleya # Added properties for SAX parsing. # # Revision 1.19 2005/02/03 23:13:41 pdoubleya # oops, reset parser to default. # # Revision 1.18 2005/02/03 23:13:10 pdoubleya # added support for parser selection. # # Revision 1.17 2005/01/29 12:41:38 pdoubleya # Added css-parse log entry. # # Revision 1.16 2004/12/13 15:15:56 joshy # fixed bug where inlines would pick up parent styles when they aren't supposed to # fixed extra Xx's in printed text # added conf boolean to turn on box outlines # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.15 2004/12/01 01:57:00 joshy # more updates for float support. # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.14 2004/11/30 21:23:18 joshy # updated the unit tests # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.13 2004/11/23 15:30:30 joshy # turned on new whitespace handler # # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.12 2004/11/22 21:34:03 joshy # created new whitespace handler. # new whitespace routines only work if you set a special property. it's # off by default. # # turned off fractional font metrics # # fixed some bugs in u and x # # - j # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.11 2004/11/16 15:38:42 joshy # removed background printing which speeds it up considerably # added boolean in conf to turn off backgrounds for testing # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.10 2004/11/15 14:39:33 joshy # changed default for viewport rendering to true # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.9 2004/11/10 17:28:54 joshy # initial support for anti-aliased text w/ minium # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.8 2004/10/27 14:03:37 joshy # added initial viewport repainting support # # Issue number: # Obtained from: # Submitted by: # Reviewed by: # # Revision 1.7 2004/10/18 17:10:58 pdoubleya # Added entry for hamlet demo file location. # # Revision 1.6 2004/10/18 12:31:39 pdoubleya # Added logging properties, and removed some unused old logging config at the top. # # Revision 1.5 2004/10/14 15:43:56 pdoubleya # Added location of default.css. # # Revision 1.4 2004/10/14 15:05:37 pdoubleya # Added testing properties for Configuration. # # Revision 1.3 2004/10/14 12:54:11 pdoubleya # Additional message parameters for logging message format. # # Revision 1.2 2004/10/14 11:09:29 pdoubleya # Added logging properties and comments. # # Revision 1.1 2004/10/13 23:01:09 pdoubleya # Added to CVS. # xhtmlrenderer-0.0~R8.orig/src/css/0000755000000000000000000000000011076705622014056 5ustar xhtmlrenderer-0.0~R8.orig/src/css/XhtmlNamespaceHandler.css0000644000000000000000000000753211060630524020775 0ustar html, address, blockquote, body, dd, div, dl, dt, fieldset, form, frame, frameset, h1, h2, h3, h4, h5, h6, noframes, ol, p, ul, center, dir, hr, menu, pre, object { display: block } li { display: list-item } head, script { display: none } body { margin: 8px } h1 { font-size: 2em; margin: .67em 0 } h2 { font-size: 1.5em; margin: .75em 0 } h3 { font-size: 1.17em; margin: .83em 0 } h4, p, blockquote, ul, fieldset, ol, dl, dir, menu { margin: 1.12em 0 } h5 { font-size: .83em; margin: 1.5em 0 } h6 { font-size: .75em; margin: 1.67em 0 } h1, h2, h3, h4, h5, h6, b, strong { font-weight: bold; } blockquote { margin-left: 40px; margin-right: 40px } i, cite, em, var, address { font-style: italic } pre, tt, code, kbd, samp { font-family: monospace } pre { white-space: pre } button, textarea, input, select { display: inline-block } big { font-size: 1.17em } small { font-size: .83em } s, strike, del { text-decoration: line-through } ol, ul, dir, menu { padding-left: 40px } dd { margin-left: 40px } ol { list-style-type: decimal } ol ul, ul ol, ul ul, ol ol { margin-top: 0; margin-bottom: 0 } u, ins { text-decoration: underline } br:before { content: "\A"; white-space: pre-line; } /* :before, :after { white-space: pre-line } */ center { text-align: center } a:link { cursor: pointer } a:link, a:visited { text-decoration: underline } /* :focus { outline: thin dotted invert } */ /* @media print { h1 { page-break-before: always } h1, h2, h3, h4, h5, h6 { page-break-after: avoid } ul, ol, dl { page-break-before: avoid } } */ @page { margin: 0.5in; } /* Flying Saucer overrides, usually compensate for unimplemented stuff */ /* don't handle all replaced things yet, besides xml should do this via entities!*/ img { display: inline-block; border-width: 1px 1px 1px 1px; margin: 0px; padding: 0px; } a { color: #0000ff; } h5, h6, b, strong { font-weight: bold; } /* Match default behavior of Firefox and Opera */ pre { margin: 1em 0; } /* Various table related rules taken from Firefox's html.css */ table { display: table; border-spacing: 2px; border-collapse: separate; margin-top: 0; margin-bottom: 0; text-indent: 0; } /* table[rules]:not([rules="none"]) { border-collapse: collapse; } */ /* caption inherits from table not table-outer */ caption { display: table-caption; text-align: center; } table[align="center"] > caption { margin-left: auto; margin-right: auto; } table[align="center"] > caption[align="left"] { margin-right: 0; } table[align="center"] > caption[align="right"] { margin-left: 0; } tr { display: table-row; vertical-align: inherit; } col { display: table-column; } colgroup { display: table-column-group; } tbody { display: table-row-group; vertical-align: middle; } thead { display: table-header-group; vertical-align: middle; } tfoot { display: table-footer-group; vertical-align: middle; } /* for XHTML tables without tbody */ table > tr { vertical-align: middle; } td { display: table-cell; vertical-align: inherit; text-align: inherit; padding: 1px; } th { display: table-cell; vertical-align: inherit; font-weight: bold; padding: 1px; } /* Modified version of equivalent FF definitions */ sub { vertical-align: sub; font-size: 0.83em; line-height: normal; } sup { vertical-align: super; font-size: 0.83em; line-height: normal; } hr { display: block; border: 1px inset; margin: 0.5em auto 0.5em auto; } hr[size="1"] { border-width: 1px 0 0 0; border-style: solid none none none; } /* Quirk: give form margin for compat (b=41806) (from Firefox) */ form{ margin: 0 0 1em 0; } xhtmlrenderer-0.0~R8.orig/src/images/0000755000000000000000000000000011076705622014533 5ustar xhtmlrenderer-0.0~R8.orig/src/images/.keepalive0000644000000000000000000000000010607502416016462 0ustar xhtmlrenderer-0.0~R8.orig/src/xhtml/0000755000000000000000000000000011076705640014422 5ustar xhtmlrenderer-0.0~R8.orig/src/xhtml/issues/0000755000000000000000000000000011076705640015735 5ustar xhtmlrenderer-0.0~R8.orig/src/xhtml/issues/issue_95_layout_2col_menu.xhtml0000644000000000000000000000301010267650562024015 0ustar Flying Saucer: 2 Column Layout with Menu

logo image goes here

website byline, or maybe a nav menu bar

Content

Content laid out using XHTML 1.0 und CSS2/ Tableless

Description of the layout...

xhtmlrenderer-0.0~R8.orig/src/packaging/0000755000000000000000000000000011172164716015212 5ustar xhtmlrenderer-0.0~R8.orig/src/packaging/aboutbox/0000755000000000000000000000000011154340062017023 5ustar xhtmlrenderer-0.0~R8.orig/src/packaging/aboutbox/aboutbox_demo.jnlp0000644000000000000000000000170211172174710022544 0ustar XHTML About Box Demo Flying Saucer Flying Saucer About Box Demo A demonstration of the Flying Saucer XHTML renderer. This demo shows off a simple About Box Flying Saucer About Box xhtmlrenderer-0.0~R8.orig/src/packaging/apache-jnlp-config.htaccess0000644000000000000000000000072011155100312022334 0ustar # Return the right mime type for JARs AddType application/x-java-archive .jar # Enable type maps AddHandler application/x-type-map .var Options +MultiViews # Tweak MultiViews - this line is for # APACHE 2.0 ONLY! MultiViewsMatch Any # Enable the Content-Encoding header for .jar.pack.gz files AddEncoding pack200-gzip .jar # Stop mod_gzip from messing with the Content-Encoding # response for these files RemoveEncoding .gz xhtmlrenderer-0.0~R8.orig/src/packaging/flyingsaucer.png0000644000000000000000000010102710135303616020404 0ustar PNG  IHDR!C pHYs  gAMA|Q cHRMz%u0`:o_FIDATxbVQ0 F(? @,m4,F(i4F( e4F!_0\8ӳ _>f57$:1Hy2 j0022( vF.pI[2ܼ #3?3?? 77 ''  ;3Thb/-FVOM3]X0002 3323 1 !Vv6VVV&&P xE2D"Ѥ5 Bة0cD6ޱQ&T eH4y0#4.#Kh +Cc" ~[qt$EO"1Q~0wf-mx3[@Œ  b,V /'b@V;#+%?#ÿ mcUP; -F ظn&Ö30 !q 0aaV>>`,|Yء 1 \1eLLNeXFw`4:E? c 5W9x! Q`!$" (, Ѭ,tbvŀ?3p8jU ~_ Qh!4 ϟ Ku1Xps1012 00 1 ^^f&`!fddA@V 0a`dh@ @(v2;XppWXc <\ *|46#ZA[IYΌ(4Zp+h,-!FpwXp F`)? 0 -Xr 5wFBh0<{ţ ,388 1Pk46 &ffP,x? gDN .z\g`b4G Bh0\pۗ Lm q NH׌\1R@R9R1x@l0*(ue4G Bh0\tܐB +5 T0k B[?l f #1Oh CԌB :QmH Z1[=!Pcfl B/*` u̐.X-E a{8h!4Bϟ;[NJˑPܣ/ i1B @o 54Ig~C "o2>wAw4"F@A(#ђHlR  *ca-`'of3 MDb-^e{xU5>gF㤃u 40qli/XPHNN'TKj51q{18\ g(񗁙7x o6L]3fp#`XBb;#g^[ ϋ000Ȼ0F9c UQ$,hXy"! 9`e#V!6j5kN.]aA*tؐ0t /@S`W(/ /.@[7@ Ak86t  .@;c z)`wyC@ mO#0>y@v&A Fruo{{ZDDԧP{1Ir@haVnum7YyF11zh+‰6cF% 8 uDSy߹#ZU)* .ejGBC| 1|~PaC*pmiv-"H!b3B:UyFf 8f/fbf @[M bOʃ xA1Ab~P1B $ X@HH1G3ōQ!@_޽c7w.Þ)S>?zQp >hl6$18@Bt\a7Z1B HA-[: keCW1gb wɠDbHK300 &!^h!4͛562<9{A.d8Dj7 -@]҂/^8]LL]ab ˆ &\  *b.yTt@P[ tJKG.h" k/]ʸAƜPq.`3!]/xR0AKpa킵Ya%cd@tZFdM#v[E50ҿhdP0nq1hB@B ݽҍbRpB d1v=d> R1A[5h 7 11 |H!@ 7cE.vBK!ɀ9͂TW@AcA Z|0BxZ`=*5ĄL3 b\? >V鞁iPAZ[:8 2'OC #P!욚 m iB4Z BuT ߼AJ!~@K9+t`#R+1hA^Hg1[=kRK B1 ZCB ~|ڍFn_&X 2fYG9D ?` IAA-!a4A B F A̰aǔ)ggNBDmBw&8?4E/t+Ɔ)fhw j*kW{L>릁!Юd0T'Ϡ잱&AZh!4Hgf3Z]0Fl FV |› //&^&. B K^AՀvv _# 3gcMM.Aф7 !-\?q/.(+_Hc@ȅ4ƌV|Z!(-BBxD m U #5#j!k-!A^F3 )1uꪁg?Opk?<^_h$@Bn>].'R F!q Z@h R!Ȁܻ4F, 0V d\R8cPaЛ8AH_4!B FopYΨ(y BBk ς03ZkB*nPͨ h|a#2r+4BneBWÈ ـ|FfNff. fba{ra!˗G 4Z<~/);(aqci!"~Fk `Dـ܀Z30`Cb`@M, kP-BQРδA ( +@X  5 Ҝ@ ĠjE'`<4Z<?5K(Lry"_ Vz_m0"@/4!,>#zECψ-d@;cH  /T !pTqin`Amk55 _?MhG^F^^!/Bdg@~g ChH9?r I - d XZF06XL>6`83DLL<$PT13 "`1h_`t(@Y 7mBA߈ʅ6惾녭ÈAgQ|Х 1bR2Y/A€%ňC>&)3"H :N*!0zͮ.j F !:u'29^Z=\ Gu >Dh˄gRπk<2Èۅ>6 ĈR&4G >\#)Aj "& 6X1Kb121{'D@=O&Ofxh3B s**~}uZ}_-Bň"bDtljPl#E6\Q6@a< eJKM=##lFhK |d- 0#A' lp磉 F !߾1Lex|*Y>q}A/hc) FrXZ GjA1b:(kvrhcHLG #JP7@G2BÏ '3fȬ'h{ 7[~>h2{6ÉM0Ɓg̀!DM3"gpaEB{m<IA*kh]?Fi~8# lllME113g@yfAf_`xzh"BS K@Ƃ1+R!ČŌV:!qy 2#Z1ɈWW}%je~J#x"bΜA %VFHA#=>åK F !jwþ~eS][V1C&4G2j Ǧ ^QؠQ!c1?zs W+ɈZ2ADld U YG )X>bx0ah F !*3f0߳e+- b&0Gs%+p^`WI3!b[\GB. gƐdž\ĈTXǤmN, !#Y^3 fBuD?N`x|h1Bk +{{ivSя_EϏLxy0Ybqqh-JG4scm 11bٿ|+bG"L-̓5^.XetM@BT~fXs bc +#Z ^0bN DW`5#@7J?oǝ">"Mw3@ !7oMϟDN#@;_ҕbEBo!fD1h'0&44@e9#`h7 ÈTP!wZXfdiDB3vh"qbwȀ55ol`do/CF9@BT_>~d[_/ ǃtXк]q&́k/ e? jc*,/gak[]h]1tuĈ?fQ"BBh݌+ǁxHEـ'S0y4h!DkR/W4`B?0B|C7paf1,,wŰcoulqB{v5KuB*p͛ /7mM44ZQ>~ͰzDVyV ZÎ6>^!ɇ؆ 0ьh-qu1b3pπZC7V "X!1!2(@-"ܫE~{7 hl&̧n[AئY0h#70ɷ8pjx:ut3. кwf\gm-?n)?2 ,t@GvC,ELH-C!G=@B7Ϟ1>e0}V [À KO@Lp`-pA2.##fAZ1 iBW yf?)H[ ]2hAj "P !H ?_MT4ZQ2Lޅ$h+c8)ذ BJdROf/nKzCrccas(0_ 77X4i]r.Ae1b A ׼No 9!. jŽ} FqMt&t ZSL DK)seeJ%NN2<`M}v2XScmh"u@zV_\u@=<d\- Bkr=fP1 CBbDm=!O㜎X|\h VC`?T71:]2P=j@]`Bw~SgM16]et w}ݮn%m&8yIހ<Ys@pGԘ2O#h!Dx|Í3gPZ3LX͆11`? W7?B? H^0AZD|Dp@ZuEn=Dzi }-xAA*Yp?f?D[j1z R#f~^A޹PF ;5zq6=2 AC~FlƯ{84i b1se<P(QKu *YjS{?T4i4(KꨈԥSv"ٶ3VI="zƤPꨈ>\7>ll"IڻbH @Z" [r Cqz?.J VIWFJ5dsxO1]/ SCPMu?@͛  BC !hA;ӧG3 F !bZvrnhl&#lьD`mjE!_fyF$4Pn@Ɨ[, {*Bytu;]e40?>zk_3\8rL 1F A/lu #bG1a5VFHgc@_PyAhFdw?q4aNLj6Hx%OkT!>ypiS5>;00pp01(33hw69@~?%+čhmRZ,&E|L^g^'![uuǛvĽ8l(ʜ~~/L8MۉC6[`'Tc$cnu6B4ےժL՜:ԕohM3﵃XZ1agչx׆v@ϒnѤ/) JΙʧDJ=/ KDj1O p0NE)fNMoh 5j7ȩU/FCKS ,d^ /o&,t߇ Ow yT( x~ f1S;}u*Ā\V}ԡQb&dCIND*wFVàBR5mgEھcQ&ó;n5Ok&$ucs^G+%n jdzɟ^M2E7POߗ ~&?pw+0NY6тO!| Ap"s8]c[KՃ'=dil|ӴC(T`[mOT^P3%Rdbi$A: #q?MfŢʈP>fWF.&:2㝔HUdR6`TP3d/˄IvQl'~:J )_Iz ``!.nȓ)$ 0Q'y ]ίAgj*=HA&Ysͩki  =wFNQ~D?ߨڂINé)g%TL(Ͱ=7p3Jkg[_#mӂ g 9IA}>J]tA UNQda?y BB`Fg|U ʉBW:t6,S(h 88wTMM![W4om*oɪ5st+^A:=];$n7GyE/T6L4 (>#YhSljBƲ0bY=N -+t KOpeck3`diG 1ܹuƵ} o_]al#Dv89! 3+ɂ<Й*Fq)7pp hj{4exZPrc"c2h(Al5h] Cky3XCPZEZD1X2;B!| 0ff& Py_&xk cb/Ç , B6!x R}գ W.dx$P3#,,x8x#<+b ʡm-_?9xZΈ;yR+1lݾH#.ȭ,Eq~0A԰.|#b`J z:"FC:v6@daL# 6F0-X%ZJ $xOV3+WB ?_i/N1|xm#d'dJ.@QTݻs ng//38L <, 2fAёҡ} F]//RGL5VDfTő?|q9!ڬ,@64 ۪Ȁ CAv$-#xV Y5xGKY)eC?(Nc0Ǟ5 Z(ACoL$_>>;,8Dx(gh; ϤYx5|^tc9 vi:xP曝ٟ!^ lK8A'h6)AH/0R&sm,s|M8Vjg\߿ؒ jɰ {O!@`*e1eȍ_dٲd0y3|tS`9XJf p~"D:B2XBѸ4@F!kNXcSW0uQD nX?rTSB:Bv]@zYy椎b¹ ,fxx8%ii^V`X0[>̐ńxVp ւz g?Z-3͂[Ԉo{ޱcDu$XshS{0ƫЛy(6'<Q##̜` c ?&i WDNDLa[T`ݠ2z:|AkFv?1"|F?h2 H|q( %l6fac#Afe쮝c"×  \D B߿aؾe!Þ]AX h4a 433 ||ĀV$Mymro 'AmcBǵjVA^lP B>eBny.ĈjV<Ѩ{C)x Sݰyx h  *Z$EB! bA L\kIAR T=O%ҕD.j;fbN…RH yof BV9l RZ-L #@v2۳g=#SYEGaA @|sAk؈ t `jBIJ;B'%)Q ݴ[ jE `mP "o҂ BH lg=vF6=D耈){7 cFm7(`DO#A)gp0 뿶k!t9Yӫ^hu@]0q16q`!v@|@ 1H>H/ VA?h-!e:AjѻV^F^DŽ6`1D_PrU< +1F\fD?Fŀ1 b P+G:t. 4 b@ VPv  & B [9(ތV#+ß'><}'Qa"N= ;P/Glmm6v'-ct{IH^R!w WK8 3 !XFFX!t` u^6~w >r"g|591Bd-5X FGx`ɣ.R,xAa9_ֆv Y7V׆+M4"§ mD l.$M68-RgctHJY5jS?<GIN>*r`Mt͌@۶16#P aq s6䲇 =t,tGc7Hݤ6-q4㟒Q _ =R(€ PS/Tdt>ܦ 9Ct/Tɪ ]=ѱ}Jw W./,p-!;h ^%~+ݯ!Ny0]]n/pm WI3c:b, Tc )&!1csAϏfIJ۲e, ](*a!u"!c78[g3|P!?Y^Ж.t @c( @>`:6o`HaPqAjH񜨂v ̌??1|KC@jgaCa 'ŖK6qп6?$tF W*ptGgs?s[zctxté㈼o_tLYG jADpCUTϩRG6$ŒBd pCUA q+yJ.jTugHmP&'L8 6Á"ʲ ΅y1PW dBJqZޒl/9kaC-*yUJ %€l%+"=y0S8K[ů^3+(#hX[W6f3&ٶ|>8sbD#NmmcK>-&mnѺʚ;zT &/I 8j7VA"zR(ewWGlH¦sM٤G5HGm 0 EBR8* tˮRP+$N@N'>UN3U1ERx墾[3FGjQ "ZimY۴j8>j J?VጳB%(84UpqPH.+iF`RChpj߈){GD˅ov֨g΀%#vǙJ!p }"~&6RZCL, o;i7ǰŇB&$Z"lw dX hf ϐGA|N65(a;y?;hSSeܪAZσX/dws06p݂fόA5c.Dux<2<Ÿ9jĆTG=:?jlXB\wawn#ԁiF]W3h2,a B|i|0|BPrB^,LjVРwqJ(#h+Jd5{]i U A C7+ + TcDO? A "hg`de0`LaVt[b (\]76G4'womJcq8x0(QRAZAZPQr<;tQ|u4} W;^3 -Cf 3Ra+\ؐ fCR NJf3ZĂbUv 5 &Y 6}n^(VѮ[f@q!b#@ TajNEv0ԕZn` Fq к `/hpɳ21020*q [?!G00,F F1F P !-Vjd | aV 16)`aZ1-&+^- YBfhH_>au3]yp fĂT":Hz!\LX &&,#V43ZK 5z*ڂm ?Ja}& FD`*>m1ado*PP&!4p>EVԵ]-GAZAEABeH:Z4XD 5EVC:NYA@SUmHm.Cuҍ}W3|}g‚fQ1~X fn>41lgl3O0&]rN> 3"X[ .Gp0`يcw.YunKq=^q`3 b lz B/`80"mk!X16>O?3ܾͯ _v:hEll]1l72(ǐZDhcH 1`z FB>*t`ЌeK-p>l ۪h`5, VTbeaq BwhZE_NKb6 dhdA)zró駷2?/@ UÌPa1،k`[a>u<Ä>`m=#H$Z+?deFqψ:ilxu& :%ߺ Dv`eea6>N!U. - 8 J |F?ʥ+ ??@-`P3~qM0>7O0z O/~2tIYX[:Z>8 #.ch"ňAC,l, +A( l {Bjy.4$^4l|B]QԞ7&3>94v:<4>% * ʿpT1'<&s#+N) U-P$Efw4֒L4Y6k@g)yGZ-jpwv;0o_<Ո $o6hv,!Z{VCgkt렊N)~&⽘VLDhTU<[DMNj}d Lu\=w><|ta%X@D` |XC'XrAq#|DV?6X+߆〴lR_>=Ʌ2v/7u4 %ȧ XvN*%F^ (*`凼<φ凣`PFaCJCȝ(Gn0_~"4*x@3^4@QB] *5У`†p+tV3^hHoZ)\ ^!< 7cxp8ó'g~ J ^ƌ@U`WƬGR811 %|hP`eACnC8% f2: 71 ;x( /Y!eɣ H> V `w@4hYP )@GR l6N΂i0-TW!C_Hz!dk(@13p[;@s_DB H 101|vW %; Pb̰H`bv8KA1 R„P} |b Z٬?TBWOOP]m@ H! }; /^ex Ϗ}y 2fu۠@pC % ^(1G)@4Z@ Bd0*p`-xAY,b1x@&ef`f:R \Z@ͫ#5@ B=|v>~%70{û ?XCC#Ə`4++uLVd] 3Z%dr #ï5Z?,Bn I hPu/Υɭ+!  tB e! |  ; ?b5#6VXk-A #66Hub2 +P (z!+[kj(2IÁAj l wc:)sf~FfV`aɭg`cj T!`[ ?d~z,d~ JYƘ( )pXA/PWc@?1 |f/j!@=m' l\ 2,2c`e8|!А/p'wOs`!{[`m/4 i- ƔqA]<&&Dw;g3"6 +_Ā}ץsد-d{@hXaC[]څd` Rw :Lg`jXU[إd- ZOx!ATEj?Q hL"-Vx&Mc|L? Ш)%2N";g{|U/U07jM^f7x7|)='d&@ +7`y}{}B򨁌VNSM[M)1;8Gܻz\4rKId0JOxr@#"W _N}} ,2ܻ~+7 %f`3rn k5!X z]<.Fwym[e+|@ ‹‰Ѣ | +R0`vL#W kQ)P/ß/~}!&+'  avD(0G3B F !/ð~lOA3uBt-7`y@탷uP8Pȭ)lfvM̂B BwzandE6*DtPEǀ@c4Bt ?fg |HMRA9*A=:[Db4sY`ua I?a] fggAB5:+M.wזk{yoǩq(KǪȊhM.rM\5fېơp0qU4WW"$IxMH! r_?wǽoNh3ee|Oܥ1p*aDin5jy<Ǧa$f.o{UZYhQoI%<.'3 B; B: ,,3?f=/exoЏ۽ڶѭdr {q@IA)DuPB~pE>|mrb - VT*t@6Zu\ސߡ0F?jmYX–Q@ .G5(2%19h"˘g_,N +]BNTM#U]˱,OzBJ gش`C޿|.0t6celxhZt, w!vOW:8bT1N3c`5R D >fZ8Lzs3bt/d(:\] -x]A ?pbx@_Ht)|DmldX89G; !- ݫW]pxf;(`;#]e2`Feg@h F. FPA)wl| Z0¦$ÂG %X)|3h:h~fȒЁAs  +lj`LmZ@ -?@w20(1hi C ȵ5:?BAXú]4P柿 .. S0+)&V:B2rr yx. Pb>V 3B?DF+TXbwϊbRC/C woA4 [] c:N~LP!@ &p \8 \@s?ʆ@3s]+_gؠ3X].~߀7n0$0:L3FaRޡ9#{bx ĦV튐""`_N)%rΉoT'B $cm"sc4)@HeM1HĤ/!V3@Ŭ< va&pJ3^(A  A.#z?>#FzN^ewe +{O_4Z 9s 3v VӵSn=pI/o2|2BgA ^kVAWUC^ vؿHЖ_KrU3x i0f^tR UX81>6bQP`8UUp|BqvZ$..KG@hl۶m o > &&``k l=vܺpy'ׯ3گ<`; cLKˉfBa + lXM@cCkZ!hؽBRKR B@;;,1H2(31𠄭7Ê+~3 ӧO3ۏ&Z:-ܹ.p 5)FG3 ߽cxp2S`m@;^߽O`k0(ǂ`wܳx 䀜R0B  ,0(>^) cAVaF#|Zg&Х ,  JJdq--NAAN~~f6s+ܜСC8|ׯ- hؿ?͛7gpww'h+0 Ղ&pz!ÛǏ?yS71|}P}?p< SвZ(1ƋA ,5m!kB!lX [. ,T$4 q*A!|ڵ6PWUUMt9a(~(-w=@Or\'ezMMD7]bW H$ }!B⽗_i~:{9 O^0]'U@jB"p4(%LFz`/,dڬIl pj1 Hյ(@09OCD >p2ƈs4?rZ,F !3:u @mZy ^ ;} x C@@ BI% "n'Fu@B47Tgmm͠7$4ZB .28p`4!h!D#M aaaCf.1cBCvPVbhb1B4eZZZ Е 1'''x6e(h!Dp=&! **: JAjB]j~Q@[@ h, >ĬJ Ak@!Y?:@M[@OM' ;֐C@ h(B4%ډyzz2pssuuuq~z4hh2#4 M5@5&4@ ZA}M#@h41ҠBz82hpо9Pkߣ F !*Ѐ+W- ҤBۆZA%((HPh֭[ F !*؁Xh4Gv Xb!Pp2nbŅANNǏ Q@}@ iB+AGv2 E,Xz5xs(.B 4%fP>:PJ___'NMT4ZQ"f@40 !.>(LGWA[Ga /^r~l ?Fu@BTn؍7>ClSSÓOyxyyy88(&*" y̞PdW^ ?9t<իWG=@Bh@43F%t`֭cfS&3acewc8؁R(w0q$6ʠWݻw9ehVHs4覇tlIB$6& , ,l@Y;+s !NN?.N._9޿{ǰh"pKq(L+** "BtBG?@B 60B0899 )M6 LBtnZChّ #n`a .[GrIh-Ax@T"@hZ2hV10C "HA[E ˆ2b@kl ZAMhc13Pׯ_ F ! h?ѥKj+A5+++.0;r;3 bP H[FB Tذ[El Xsi ;@`_g# @ {Bu(-WР-!5@p0΅ lI ЛTA#PbP "F,Akp 2@]47Cbr%tӧOj F !2RCt->ʔi_B\ XH,\Iz 4@τ3[L,L,3Ș`bvX'fjЬ(8 (4Z@^j8AGV]:S %H AlB T`11z  @?xQ&>jՁlPh"ΐKEfZ)zԽ@yOx.a5hK|( KKKfc|Qh!DAa!!!B}%hTx2߿ a<~ =FB0ܥvhh!D"pZDCm4f7 T> V`at ~ Pj)L? /_RQQ!fŋ|@ܹs ǎë4 j(saP*tA0n@Z= _~ H.B@({BٲQ@SjQ\[Aѥ/B@2wozh`Z Dhxiq&%-e D|`1wtJ_]B$PmG̀4& P-: /]q`+;@Ai )CCVPUG F !h]˗`=1 ;P{:Cy@@gk%펁b?| j[߾}D@+)@ v V\@]25y F !"h41gHƂx:AU2uMh5Q@<Bu'@}}B@UAW uoooǹy7xE/ bVw0~@[C Y*u544y!Q@<BZFh4ȎB ¶ /V<=_! D*,*eZE5: 4ZifZ硞AVVCoo/dDl4FZ/nV@da"h!!!aX ~~~j\2z5 F !<˗DRgH0ݧ~g1@?9ψW5k.vgb>AT:8q"Caa!|*#7vvy-&)i)9Y9Z#P᥮N~ ma ZR'Iޑ$Ddw{br~)3DҾ93IcA%龠CA2OIhDIvgq)A7CHu,&N4 !xŵנ7.DܟeC $`b> *@:4F:Cq!ZZb%5V%F87@n_}+3.f[BꏄB FhPuʔ)  \z ;+b?VD* ~(+vMIQ;#=%w_}m~=6;;+6Hev9[ݳgo yg V;;|ζzd4,tۤCAC|ł~X_bϚ;<:'F)^޾w՞ન|[[6a2#^X#pT. \Ra(X-m^CI?(Bqkg΄` MI_lFf0~57Dt5E@A^fLތ{1s+LjBE2IȜL.Y8vf̶S(mhDBzS w΂ޟj 1!]F,l[F!Mlvp+@A;A @;@]4JoؠF.K-)ZP$V?]>bEmڼ\QQv`wA r%f #6lliXfZw4@#b*>F(]DŽTA0orAnj ޽e8y$x5 B&Mb+\bԑb'- %)gy iA "hb!cC,.>)/ G]VVV#@ޕ@6RY\xi&NҤÐsIBC,G3egaV-|xC5|Z}+ E`NurgrٸdZfIg39ok_(<_#rɞy`t"Sqd'ÄfM܏sDx)i5~Z!!JI=C+ZjAK@%A;Жk;jfBK PH&n$ BBu> 1*l#o{n_=&az6Y)!cAˊk;'h@9J`܅~O*3mj;ʌGW;&CEiaڇX 9H!;eps a#RDaኁOdUўrY D>]c3 #!?NeW+ 5 p]{<+W>#5mg1:wV=Y0/ղ6UKBTx\,ϧ*;1[m@f Z+WiN7 `jS%4SAY(ϜtLr UؑqiAiiv=p7Y{=Jz^P@#k0j,;rM0oyT6EhOF>KvC8ڞ5`2x qa( ȈHKMS Ƒɤ1^>^k@V{@j¶vl!p2Y̑뽓H}|B~Kgu__~2J L4ެ.`bB;~JY吠ŕz@Re(r:Ј)@L:u C`"`^)a3dY1"4!fP3^^JBFW #ccYLinbfĈ .66,+i\Any!б$O.#B}`|ptAqRi/AW Va` }Dߩhn6j> , m׶ R׭a"xz9lq!2=t +6A،(\%ddr5x(JVH˒iqeyKh"!lB{<:"±RI#*.391Qj "Ѽ1ﵭQ@RZ5$IImΓ5} >$PHT'05=6㾔Fs9F.4"Ϙ4idEPB- ЁՌbG8h!<<> &qB<΂;+F,fHwB*bC2tsHHUp!l*}YW=0|DDfϙC@#eiӦ1TWWc@<`P2PCAa!D/`Aj2vuHMOj\3brw $ak!<4M,j`mܸ!;;|" |^ؙTLУ>F^>^___ ~Јm… 8@f˘3JM -))aF)t`46\ + "l?#c!#vz|g[CZB\J03@ݲR-"B; L\\!ߟa_4z -!FhI @PCC d6: YE k!¶.rѢ7pM*kliVF+Ba: c#:aϞ=x = acuuu~ PǏFAg@hh-hV տ#0ra%m*5?,B zfOV$v xnEq d] aЦUV+1PkAz@i'!1!2"<6 ~h!#B[=AaB 6!0\3^ !Rx()t5&DJo ߦTlF3fƂ " \!w`|= jPyZZg n*Q(hQ r@*x@S 6F.`]1\0B{xw}s%BnAC^|$laE-C!BK a4rS<>>QYh.[D%.T !r!>+b7CNaC I1 ]bllGj:SnWNW1CF[cI/Rd؁4ZEغdr[m BBc<(\vᇭpw=A.` r!+_ჍF7lhaDh!##'HlN[B0B&EB% REo T-EoTx`[s>lcJ; 5t3Zh“p>PeFYZb$"v`dA~8IXi"h!Db^ 1r y& Wm%1L!Nwk{ zkv8@-tp moc:W@c[C(QOx ȅՂ^8k ߸( h"@:^Cňl-q t9\wcSx( h BRh"% nrV/a@i+~ "2?R_b" hwˊ\8 n@>&Y5(9E#@Aǵ1[ov4B fQ@:B=ڝG?7o<=  Eضr-N '|@B84oNvR`'], T31 BRf^\mxvc; =[Hm4@!\'(Ѣn**g!=1l1 A‰Z]u|u1->7s PA;Th\[p*m/z+5DFUBS*hYHak;w[\!(ȇ~t 7gF-к`>%lH]@+a+qa2}&zfŵs0uшɤgN*tpuv1\ B/giPKm4Ze_`ځ\06vbv֣-ե#&w01B|].B-j|~.z7ZhS!wǐ%Fl)_N ROWDak)9gOr"Nx}LAfhAD<B@6^aZ?MNXDav\+q𵈨ٺ!"XW| qYZhX!ܽB/`"dqp-T.,#;B?mUZEw#cDjo|] @vخv?ݱQ@B1!؁X2#i|{^ClH "b $l <@V%ce$籭 V!ˡf?G~@ Z}Bw㻅'F 2L;{up^bõ>h"h!DF :v( uX\wňa׹IO@31 ?kͫkGC׃lz -H!g\]ؚ n%rXASf%P!T(ѪB_WCh}6y31rw }.ۢD\F[A-H(Efl-Pu2#."lS9 _D/|pݦEL+!vs*L6 >BWd70/\3b%6F>FJ umq>B>:[a: h!Dd }@ zX@Km"g͜{,5 !B; up̀a[!m['VhC}@"v]0qƇ`;,}_Yf- lG !8BDئ챩!明: F !*D[_;R +-V$4KFJK[ xSƅp 5GA/x\Z49Zh!D pB/`@0*Z3D!펑WAom &BcshC@ #}k+ R{\)uumhg..7(>BqlNaw"c>pMc؝Fa&2'$~Bv F !Ǖ:Č*|]HMƋO6E-|hQau55WB|b 8|]/BF|_PFl ŠP7Z .@Ǎ񱵎V"tVP!~4'16|ji-|h!D-)B5vS{<~%eW=r: h!4Ə E&Sr`c.9cB vx*~h!{=.}ơ{-@=1gNZ:C0 IENDB`xhtmlrenderer-0.0~R8.orig/src/packaging/template.jar.var0000644000000000000000000000021611170715756020315 0ustar URI: packed/FILENAME.pack.gz Content-Type: x-java-archive Content-Encoding: pack200-gzip URI: unpacked/FILENAME Content-Type: x-java-archive xhtmlrenderer-0.0~R8.orig/src/packaging/docbook/0000755000000000000000000000000011154340062016620 5ustar xhtmlrenderer-0.0~R8.orig/src/packaging/docbook/docbook_demo.jnlp0000644000000000000000000000171111172201614022130 0ustar DocBook XML/CSS Demo Flying Saucer Flying Saucer DocBook XML/CSS Demo A demonstration of the Flying Saucer XHTML renderer with a page containing DocBook XML, rendered using pure CSS. FS DocBook Demo xhtmlrenderer-0.0~R8.orig/src/packaging/manifest0000644000000000000000000000031110135122444016724 0ustar Manifest-Version: 1.0 Created-By: Joshua Marinacci (joshua@marinacci.org) Main-Class: org.xhtmlrenderer.demo.browser.BrowserStartup Class-Path: joshy-common.jar ss_css2.jar core-renderer.jar xalan.jar xhtmlrenderer-0.0~R8.orig/src/packaging/browser/0000755000000000000000000000000011172155764016700 5ustar xhtmlrenderer-0.0~R8.orig/src/packaging/browser/browser_demo.jnlp0000644000000000000000000000213211172174672022251 0ustar XHTML Browser Demo Flying Saucer Flying Saucer Browser Demo A demonstration of the Flying Saucer XHTML renderer. This demo is a simple webbrowser that can load XHTML from the web or it's internal demo files. FS Demo xhtmlrenderer-0.0~R8.orig/src/packaging/manifest.about0000644000000000000000000000030410135122444020037 0ustar Manifest-Version: 1.0 Created-By: Joshua Marinacci (joshua@marinacci.org) Main-Class: org.xhtmlrenderer.demo.aboutbox.AboutBox Class-Path: joshy-common.jar ss_css2.jar core-renderer.jar xalan.jar xhtmlrenderer-0.0~R8.orig/src/packaging/svg/0000755000000000000000000000000011154340062015777 5ustar xhtmlrenderer-0.0~R8.orig/src/packaging/svg/svg_demo.jnlp0000644000000000000000000000203611172202742020472 0ustar XHTML Embedded SVG Demo Flying Saucer Flying Saucer Embedded SVG Demo A demonstration of the Flying Saucer XHTML renderer with a page containing embedded SVG references. This shows a single fixed page rendering SVG content.. FS SVG Demo xhtmlrenderer-0.0~R8.orig/src/log4j/0000755000000000000000000000000011076705634014310 5ustar xhtmlrenderer-0.0~R8.orig/src/log4j/org/0000755000000000000000000000000011076705634015077 5ustar xhtmlrenderer-0.0~R8.orig/src/log4j/org/xhtmlrenderer/0000755000000000000000000000000011076705634017762 5ustar xhtmlrenderer-0.0~R8.orig/src/log4j/org/xhtmlrenderer/log4j/0000755000000000000000000000000011076705634021001 5ustar xhtmlrenderer-0.0~R8.orig/src/log4j/org/xhtmlrenderer/log4j/Log4JXRLogger.java0000644000000000000000000000771310671402124024171 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.log4j; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import org.apache.log4j.Logger; import org.xhtmlrenderer.util.XRLog; import org.xhtmlrenderer.util.XRLogger; public class Log4JXRLogger implements XRLogger { private static final String DEFAULT_LOGGER_NAME = "org.xhtmlrenderer.other"; private static final Map LOGGER_NAME_MAP; static { LOGGER_NAME_MAP = new HashMap(); LOGGER_NAME_MAP.put(XRLog.CONFIG, "org.xhtmlrenderer.config"); LOGGER_NAME_MAP.put(XRLog.EXCEPTION, "org.xhtmlrenderer.exception"); LOGGER_NAME_MAP.put(XRLog.GENERAL, "org.xhtmlrenderer.general"); LOGGER_NAME_MAP.put(XRLog.INIT, "org.xhtmlrenderer.init"); LOGGER_NAME_MAP.put(XRLog.JUNIT, "org.xhtmlrenderer.junit"); LOGGER_NAME_MAP.put(XRLog.LOAD, "org.xhtmlrenderer.load"); LOGGER_NAME_MAP.put(XRLog.MATCH, "org.xhtmlrenderer.match"); LOGGER_NAME_MAP.put(XRLog.CASCADE, "org.xhtmlrenderer.cascade"); LOGGER_NAME_MAP.put(XRLog.XML_ENTITIES, "org.xhtmlrenderer.load.xmlentities"); LOGGER_NAME_MAP.put(XRLog.CSS_PARSE, "org.xhtmlrenderer.cssparse"); LOGGER_NAME_MAP.put(XRLog.LAYOUT, "org.xhtmlrenderer.layout"); LOGGER_NAME_MAP.put(XRLog.RENDER, "org.xhtmlrenderer.render"); } private String _defaultLoggerName = DEFAULT_LOGGER_NAME; private Map _loggerNameMap = LOGGER_NAME_MAP; public void log(String where, Level level, String msg) { Logger.getLogger(getLoggerName(where)).log(toLog4JLevel(level), msg); } public void log(String where, Level level, String msg, Throwable th) { Logger.getLogger(getLoggerName(where)).log(toLog4JLevel(level), msg, th); } private org.apache.log4j.Level toLog4JLevel(Level level) { if (level == Level.SEVERE) { return org.apache.log4j.Level.ERROR; } else if (level == Level.WARNING) { return org.apache.log4j.Level.WARN; } else if (level == Level.INFO) { return org.apache.log4j.Level.INFO; } else if (level == Level.CONFIG) { return org.apache.log4j.Level.INFO; } else if (level == Level.FINE || level == Level.FINER || level == Level.FINEST) { return org.apache.log4j.Level.DEBUG; } else { return org.apache.log4j.Level.INFO; } } private String getLoggerName(String xrLoggerName) { String result = (String)_loggerNameMap.get(xrLoggerName); if (result != null) { return result; } else { return _defaultLoggerName; } } public void setLevel(String logger, Level level) { throw new UnsupportedOperationException("log4j should be not be configured here"); } public Map getLoggerNameMap() { return _loggerNameMap; } public void setLoggerNameMap(Map loggerNameMap) { _loggerNameMap = loggerNameMap; } public String getDefaultLoggerName() { return _defaultLoggerName; } public void setDefaultLoggerName(String defaultLoggerName) { _defaultLoggerName = defaultLoggerName; } } xhtmlrenderer-0.0~R8.orig/src/java/0000755000000000000000000000000011172434416014204 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/0000755000000000000000000000000011172434416014773 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/0000755000000000000000000000000011172434416017656 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/0000755000000000000000000000000011106164736021461 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/TableSectionBox.java0000644000000000000000000002154710664703170025361 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.xhtmlrenderer.layout.LayoutContext; import org.xhtmlrenderer.render.BlockBox; import org.xhtmlrenderer.render.RenderingContext; public class TableSectionBox extends BlockBox { private List _grid = new ArrayList(); private boolean _needCellWidthCalc; private boolean _needCellRecalc; private boolean _footer; private boolean _header; private boolean _capturedOriginalAbsY; private int _originalAbsY; public TableSectionBox() { } public BlockBox copyOf() { TableSectionBox result = new TableSectionBox(); result.setStyle(getStyle()); result.setElement(getElement()); return result; } public List getGrid() { return _grid; } public void setGrid(List grid) { _grid = grid; } public void extendGridToColumnCount(int columnCount) { for (Iterator i = _grid.iterator(); i.hasNext(); ) { RowData row = (RowData)i.next(); row.extendToColumnCount(columnCount); } } public void splitColumn(int pos) { for (Iterator i = _grid.iterator(); i.hasNext(); ) { RowData row = (RowData)i.next(); row.splitColumn(pos); } } public void recalcCells(LayoutContext c) { int cRow = 0; _grid.clear(); ensureChildren(c); for (Iterator i = getChildIterator(); i.hasNext(); cRow++) { TableRowBox row = (TableRowBox)i.next(); row.ensureChildren(c); for (Iterator j = row.getChildIterator(); j.hasNext(); ) { TableCellBox cell = (TableCellBox)j.next(); addCell(row, cell, cRow); } } } public void calcBorders(LayoutContext c) { ensureChildren(c); for (Iterator i = getChildIterator(); i.hasNext(); ) { TableRowBox row = (TableRowBox)i.next(); row.ensureChildren(c); for (Iterator j = row.getChildIterator(); j.hasNext(); ) { TableCellBox cell = (TableCellBox)j.next(); cell.calcCollapsedBorder(c); } } } public TableCellBox cellAt(int row, int col) { return (TableCellBox)((RowData)_grid.get(row)).getRow().get(col); } private void setCellAt(int row, int col, TableCellBox cell) { ((RowData)_grid.get(row)).getRow().set(col, cell); } private void ensureRows(int numRows) { int nRows = _grid.size(); int nCols = getTable().numEffCols(); while (nRows < numRows) { RowData row = new RowData(); row.extendToColumnCount(nCols); _grid.add(row); nRows++; } } private TableBox getTable() { return (TableBox)getParent(); } protected void layoutChildren(LayoutContext c, int contentStart) { if (isNeedCellRecalc()) { recalcCells(c); setNeedCellRecalc(false); } if (isNeedCellWidthCalc()) { setCellWidths(c); setNeedCellWidthCalc(false); } super.layoutChildren(c, contentStart); } private void addCell(TableRowBox row, TableCellBox cell, int cRow) { int rSpan = cell.getStyle().getRowSpan(); int cSpan = cell.getStyle().getColSpan(); List columns = getTable().getColumns(); int nCols = columns.size(); int cCol = 0; ensureRows(cRow + rSpan); while ( cCol < nCols && cellAt(cRow, cCol) != null) { cCol++; } int col = cCol; TableCellBox set = cell; while (cSpan > 0) { int currentSpan; if (cCol >= nCols) { getTable().appendColumn(cSpan); currentSpan = cSpan; } else { ColumnData cData = (ColumnData)columns.get(cCol); if (cSpan < cData.getSpan()) { getTable().splitColumn(cCol, cSpan); } cData = (ColumnData)columns.get(cCol); currentSpan = cData.getSpan(); } int r = 0; while (r < rSpan) { if (cellAt(cRow + r, cCol) == null) { setCellAt(cRow + r, cCol, set); } r++; } cCol++; cSpan -= currentSpan; set = TableCellBox.SPANNING_CELL; } cell.setRow(cRow); cell.setCol(getTable().effColToCol(col)); } public void reset(LayoutContext c) { super.reset(c); _grid.clear(); setNeedCellWidthCalc(true); setNeedCellRecalc(true); setCapturedOriginalAbsY(false); } void setCellWidths(LayoutContext c) { int[] columnPos = getTable().getColumnPos(); for (Iterator i = _grid.iterator(); i.hasNext(); ) { RowData row = (RowData)i.next(); List cols = row.getRow(); int hspacing = getTable().getStyle().getBorderHSpacing(c); for (int j = 0; j < cols.size(); j++) { TableCellBox cell = (TableCellBox)cols.get(j); if (cell == null || cell == TableCellBox.SPANNING_CELL) { continue; } int endCol = j; int cspan = cell.getStyle().getColSpan(); while (cspan > 0 && endCol < cols.size()) { cspan -= getTable().spanOfEffCol(endCol); endCol++; } int w = columnPos[endCol] - columnPos[j] - hspacing; cell.setLayoutWidth(c, w); cell.setX(columnPos[j] + hspacing); } } } public boolean isAutoHeight() { // FIXME Should properly handle absolute heights (%s resolve to auto) return true; } public int numRows() { return _grid.size(); } protected boolean isSkipWhenCollapsingMargins() { return true; } public void paintBorder(RenderingContext c) { // row groups never have borders } public void paintBackground(RenderingContext c) { // painted at the cell level } public TableRowBox getLastRow() { if (getChildCount() > 0) { return (TableRowBox)getChild(getChildCount()-1); } else { return null; } } boolean isNeedCellWidthCalc() { return _needCellWidthCalc; } void setNeedCellWidthCalc(boolean needCellWidthCalc) { _needCellWidthCalc = needCellWidthCalc; } private boolean isNeedCellRecalc() { return _needCellRecalc; } private void setNeedCellRecalc(boolean needCellRecalc) { _needCellRecalc = needCellRecalc; } public void layout(LayoutContext c, int contentStart) { boolean running = c.isPrint() && (isHeader() || isFooter()) && getTable().getStyle().isPaginateTable(); if (running) { c.setNoPageBreak(c.getNoPageBreak()+1); } super.layout(c, contentStart); if (running) { c.setNoPageBreak(c.getNoPageBreak()-1); } } public boolean isFooter() { return _footer; } public void setFooter(boolean footer) { _footer = footer; } public boolean isHeader() { return _header; } public void setHeader(boolean header) { _header = header; } public boolean isCapturedOriginalAbsY() { return _capturedOriginalAbsY; } public void setCapturedOriginalAbsY(boolean capturedOriginalAbsY) { _capturedOriginalAbsY = capturedOriginalAbsY; } public int getOriginalAbsY() { return _originalAbsY; } public void setOriginalAbsY(int originalAbsY) { _originalAbsY = originalAbsY; } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/ColumnData.java0000644000000000000000000000266310577132662024366 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; /** * Instances of this class are effective columns in the table grid. Table * columns are managed in terms of effective columns which ensures that only the * minimum number of columns necessary to manage the grid are created. For * example, a table cell with colspan="1000" will only create a single effective * column unless there are other table cells in other rows which force the * column to be split. */ public class ColumnData { private int _span = 1; public int getSpan() { return _span; } public void setSpan(int span) { _span = span; } }xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/TableBox.java0000644000000000000000000021407711106164736024037 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.logging.Level; import org.xhtmlrenderer.css.constants.CSSName; import org.xhtmlrenderer.css.constants.IdentValue; import org.xhtmlrenderer.css.style.CalculatedStyle; import org.xhtmlrenderer.css.style.CssContext; import org.xhtmlrenderer.css.style.Length; import org.xhtmlrenderer.css.style.derived.BorderPropertySet; import org.xhtmlrenderer.css.style.derived.RectPropertySet; import org.xhtmlrenderer.layout.LayoutContext; import org.xhtmlrenderer.render.BlockBox; import org.xhtmlrenderer.render.Box; import org.xhtmlrenderer.render.ContentLimit; import org.xhtmlrenderer.render.ContentLimitContainer; import org.xhtmlrenderer.render.PageBox; import org.xhtmlrenderer.render.RenderingContext; import org.xhtmlrenderer.util.XRLog; // Much of this code is directly inspired by (and even copied from) // the equivalent code in KHTML (including the idea of "effective columns" to // manage colspans and the details of the table layout algorithms). Many kudos // to the KHTML developers for making such an amazing piece of software! public class TableBox extends BlockBox { private List _columns = new ArrayList(); private int[] _columnPos; private TableLayout _tableLayout; private List _styleColumns; private int _pageClearance; private boolean _marginAreaRoot; private ContentLimitContainer _contentLimitContainer; private int _extraSpaceTop; private int _extraSpaceBottom; public boolean isMarginAreaRoot() { return _marginAreaRoot; } public void setMarginAreaRoot(boolean marginAreaRoot) { _marginAreaRoot = marginAreaRoot; } public BlockBox copyOf() { TableBox result = new TableBox(); result.setStyle(getStyle()); result.setElement(getElement()); return result; } public void addStyleColumn(TableColumn col) { if (_styleColumns == null) { _styleColumns = new ArrayList(); } _styleColumns.add(col); } public List getStyleColumns() { return _styleColumns == null ? Collections.EMPTY_LIST : _styleColumns; } public int[] getColumnPos() { return _columnPos; } private void setColumnPos(int[] columnPos) { _columnPos = columnPos; } public int numEffCols() { return _columns.size(); } public int spanOfEffCol(int effCol) { return ((ColumnData)_columns.get(effCol)).getSpan(); } public int colToEffCol(int col) { int c = 0; int i = 0; while (c < col && i < numEffCols()) { c += spanOfEffCol(i); i++; } return i; } public int effColToCol(int effCol) { int c = 0; for (int i = 0; i < effCol; i++) { c += spanOfEffCol(i); } return c; } public void appendColumn(int span) { ColumnData data = new ColumnData(); data.setSpan(span); _columns.add(data); for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); section.extendGridToColumnCount(_columns.size()); } } public void setStyle(CalculatedStyle style) { super.setStyle(style); if (isMarginAreaRoot()) { _tableLayout = new MarginTableLayout(this); } else if (getStyle().isIdent(CSSName.TABLE_LAYOUT, IdentValue.FIXED)) { _tableLayout = new FixedTableLayout(this); } else { _tableLayout = new AutoTableLayout(this); } } public void calcMinMaxWidth(LayoutContext c) { if (! isMinMaxCalculated()) { recalcSections(c); if (getStyle().isCollapseBorders()) { calcBorders(c); } _tableLayout.calcMinMaxWidth(c); setMinMaxCalculated(true); } } public void splitColumn(int pos, int firstSpan) { ColumnData newColumn = new ColumnData(); newColumn.setSpan(firstSpan); _columns.add(pos, newColumn); ColumnData leftOver = (ColumnData)_columns.get(pos+1); leftOver.setSpan(leftOver.getSpan() - firstSpan); for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); section.splitColumn(pos); } } public int marginsBordersPaddingAndSpacing(CssContext c) { int result = 0; RectPropertySet margin = getMargin(c); result += (int)margin.left() + (int)margin.right(); BorderPropertySet border = getBorder(c); result += (int)border.left() + (int)border.right(); if (! getStyle().isCollapseBorders()) { RectPropertySet padding = getPadding(c); int hSpacing = getStyle().getBorderHSpacing(c); result += padding.left() + padding.right() + (numEffCols()+1) * hSpacing; } return result; } public List getColumns() { return _columns; } private void recalcSections(LayoutContext c) { ensureChildren(c); for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); section.recalcCells(c); } } private void calcBorders(LayoutContext c) { ensureChildren(c); for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); section.calcBorders(c); } } protected boolean isAllowHeightToShrink() { return false; } public void layout(LayoutContext c) { calcMinMaxWidth(c); calcDimensions(c); calcWidth(); calcPageClearance(c); // Recalc to pick up auto margins now that layout has been called on // containing block and the table has a content width if (! isAnonymous()) { setDimensionsCalculated(false); calcDimensions(c, getContentWidth()); } _tableLayout.layout(c); setCellWidths(c); layoutTable(c); } protected void resolveAutoMargins(LayoutContext c, int cssWidth, RectPropertySet padding, BorderPropertySet border) { // If our minimum width is greater than the calculated CSS width, // don't try to allocate any margin space to auto margins. It // will just confuse the issue later when we expand the effective // table width to its minimum width. if (getMinWidth() < cssWidth) { super.resolveAutoMargins(c, cssWidth, padding, border); } else { boolean autoLeft = getStyle().isIdent(CSSName.MARGIN_LEFT, IdentValue.AUTO); if (autoLeft) { setMarginLeft(c, 0); } boolean autoRight = getStyle().isIdent(CSSName.MARGIN_RIGHT, IdentValue.AUTO); if (autoRight) { setMarginRight(c, 0); } } } private void layoutTable(LayoutContext c) { boolean running = c.isPrint() && getStyle().isPaginateTable(); int prevExtraTop = 0; int prevExtraBottom = 0; if (running) { prevExtraTop = c.getExtraSpaceTop(); prevExtraBottom = c.getExtraSpaceBottom(); c.setExtraSpaceTop(c.getExtraSpaceTop() + (int)getPadding(c).top() + (int)getBorder(c).top() + getStyle().getBorderVSpacing(c)); c.setExtraSpaceBottom(c.getExtraSpaceBottom() + (int)getPadding(c).bottom() + (int)getBorder(c).bottom() + getStyle().getBorderVSpacing(c)); } super.layout(c); if (running) { if (isNeedAnalyzePageBreaks()) { analyzePageBreaks(c); setExtraSpaceTop(0); setExtraSpaceBottom(0); } else { setExtraSpaceTop(c.getExtraSpaceTop() - prevExtraTop); setExtraSpaceBottom(c.getExtraSpaceBottom() - prevExtraBottom); } c.setExtraSpaceTop(prevExtraTop); c.setExtraSpaceBottom(prevExtraBottom); } } protected void layoutChildren(LayoutContext c, int contentStart) { ensureChildren(c); // If we have a running footer, we need its dimensions right away boolean running = c.isPrint() && getStyle().isPaginateTable(); if (running) { int headerHeight = layoutRunningHeader(c); int footerHeight = layoutRunningFooter(c); int spacingHeight = footerHeight == 0 ? 0 : getStyle().getBorderVSpacing(c); PageBox first = c.getRootLayer().getFirstPage(c, this); if (getAbsY() + getTy() + headerHeight + footerHeight + spacingHeight > first.getBottom()) { // XXX Performance problem here. This forces the table // to move to the next page (which we want), but the initial // table layout run still completes (which we don't) setNeedPageClear(true); } } super.layoutChildren(c, contentStart); } private int layoutRunningHeader(LayoutContext c) { int result = 0; if (getChildCount() > 0) { TableSectionBox section = (TableSectionBox)getChild(0); if (section.isHeader()) { c.setNoPageBreak(c.getNoPageBreak() + 1); section.initContainingLayer(c); section.layout(c); c.setExtraSpaceTop(c.getExtraSpaceTop() + section.getHeight()); result = section.getHeight(); section.reset(c); c.setNoPageBreak(c.getNoPageBreak() - 1); } } return result; } private int layoutRunningFooter(LayoutContext c) { int result = 0; if (getChildCount() > 0) { TableSectionBox section = (TableSectionBox)getChild(getChildCount()-1); if (section.isFooter()) { c.setNoPageBreak(c.getNoPageBreak() + 1); section.initContainingLayer(c); section.layout(c); c.setExtraSpaceBottom(c.getExtraSpaceBottom() + section.getHeight() + getStyle().getBorderVSpacing(c)); result = section.getHeight(); section.reset(c); c.setNoPageBreak(c.getNoPageBreak() - 1); } } return result; } private boolean isNeedAnalyzePageBreaks() { Box b = getParent(); while (b != null) { if (b.getStyle().isTable() && b.getStyle().isPaginateTable()) { return false; } b = b.getParent(); } return true; } private void analyzePageBreaks(LayoutContext c) { analyzePageBreaks(c, null); } public void analyzePageBreaks(LayoutContext c, ContentLimitContainer container) { _contentLimitContainer = new ContentLimitContainer(c, getAbsY()); _contentLimitContainer.setParent(container); if (container != null) { container.updateTop(c, getAbsY()); container.updateBottom(c, getAbsY() + getHeight()); } for (Iterator i = getChildIterator(); i.hasNext(); ) { Box b = (Box)i.next(); b.analyzePageBreaks(c, _contentLimitContainer); } if (container != null && _contentLimitContainer.isContainsMultiplePages() && (getExtraSpaceTop() > 0 || getExtraSpaceBottom() > 0)) { propagateExtraSpace(c, container, _contentLimitContainer, getExtraSpaceTop(), getExtraSpaceBottom()); } } public void paintBackground(RenderingContext c) { if (_contentLimitContainer == null) { super.paintBackground(c); } else if (getStyle().isVisible()) { c.getOutputDevice().paintBackground( c, getStyle(), getContentLimitedBorderEdge(c), getPaintingBorderEdge(c)); } } public void paintBorder(RenderingContext c) { if (_contentLimitContainer == null) { super.paintBorder(c); } else if (getStyle().isVisible()) { c.getOutputDevice().paintBorder(c, getStyle(), getContentLimitedBorderEdge(c), getBorderSides()); } } private Rectangle getContentLimitedBorderEdge(RenderingContext c) { Rectangle result = getPaintingBorderEdge(c); ContentLimit limit = _contentLimitContainer.getContentLimit(c.getPageNo()); if (limit == null) { XRLog.layout(Level.WARNING, "No content limit found"); return result; } else { if (limit.getTop() == ContentLimit.UNDEFINED || limit.getBottom() == ContentLimit.UNDEFINED) { return result; } RectPropertySet padding = getPadding(c); BorderPropertySet border = getBorder(c); int top; if (c.getPageNo() == _contentLimitContainer.getInitialPageNo()) { top = result.y; } else { top = limit.getTop() - (int)padding.top() - (int)border.top() - getStyle().getBorderVSpacing(c); if (getChildCount() > 0) { TableSectionBox section = (TableSectionBox)getChild(0); if (section.isHeader()) { top -= section.getHeight(); } } } int bottom; if (c.getPageNo() == _contentLimitContainer.getLastPageNo()) { bottom = result.y + result.height; } else { bottom = limit.getBottom() + (int)padding.bottom() + (int)border.bottom() + getStyle().getBorderVSpacing(c); if (getChildCount() > 0) { TableSectionBox section = (TableSectionBox)getChild(getChildCount()-1); if (section.isFooter()) { bottom += section.getHeight(); } } } result.y = top; result.height = bottom - top; return result; } } public void updateHeaderFooterPosition(RenderingContext c) { ContentLimit limit = _contentLimitContainer.getContentLimit(c.getPageNo()); if (limit != null) { updateHeaderPosition(c, limit); updateFooterPosition(c, limit); } } private void updateHeaderPosition(RenderingContext c, ContentLimit limit) { if (limit.getTop() != ContentLimit.UNDEFINED || c.getPageNo() == _contentLimitContainer.getInitialPageNo()) { if (getChildCount() > 0) { TableSectionBox section = (TableSectionBox)getChild(0); if (section.isHeader()) { if (! section.isCapturedOriginalAbsY()) { section.setOriginalAbsY(section.getAbsY()); section.setCapturedOriginalAbsY(true); } int newAbsY; if (c.getPageNo() == _contentLimitContainer.getInitialPageNo()) { newAbsY = section.getOriginalAbsY(); } else { newAbsY = limit.getTop() - getStyle().getBorderVSpacing(c) - section.getHeight(); } int diff = newAbsY - section.getAbsY(); if (diff != 0) { section.setY(section.getY() + diff); section.calcCanvasLocation(); section.calcChildLocations(); section.calcPaintingInfo(c, false); } } } } } private void updateFooterPosition(RenderingContext c, ContentLimit limit) { if (limit.getBottom() != ContentLimit.UNDEFINED || c.getPageNo() == _contentLimitContainer.getLastPageNo()) { if (getChildCount() > 0) { TableSectionBox section = (TableSectionBox)getChild(getChildCount()-1); if (section.isFooter()) { if (! section.isCapturedOriginalAbsY()) { section.setOriginalAbsY(section.getAbsY()); section.setCapturedOriginalAbsY(true); } int newAbsY; if (c.getPageNo() == _contentLimitContainer.getLastPageNo()) { newAbsY = section.getOriginalAbsY(); } else { newAbsY = limit.getBottom(); } int diff = newAbsY - section.getAbsY(); if (diff != 0) { section.setY(section.getY() + diff); section.calcCanvasLocation(); section.calcChildLocations(); section.calcPaintingInfo(c, false); } } } } } private void calcPageClearance(LayoutContext c) { if (c.isPrint() && getStyle().isCollapseBorders()) { PageBox page = c.getRootLayer().getFirstPage(c, this); TableRowBox row = getFirstRow(); if (row != null) { int spill = 0; for (Iterator i = row.getChildIterator(); i.hasNext(); ) { TableCellBox cell = (TableCellBox)i.next(); BorderPropertySet collapsed = cell.getCollapsedPaintingBorder(); int tmp = (int)collapsed.top() / 2; if (tmp > spill) { spill = tmp; } } int borderTop = getAbsY() + (int)getMargin(c).top() - spill; int delta = page.getTop() - borderTop; if (delta > 0) { setY(getY() + delta); setPageClearance(delta); calcCanvasLocation(); c.translate(0, delta); } } } } private void calcWidth() { if (getMinWidth() > getWidth()) { setContentWidth(getContentWidth() + getMinWidth() - getWidth()); } else if (getStyle().isIdent(CSSName.WIDTH, IdentValue.AUTO) && getMaxWidth() < getWidth()) { setContentWidth(getContentWidth() - (getWidth() - getMaxWidth())); } } public TableRowBox getFirstRow() { for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); if (section.getChildCount() > 0) { return (TableRowBox)section.getChild(0); } } return null; } public TableRowBox getFirstBodyRow() { for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); if (section.isHeader() || section.isFooter()) { continue; } if (section.getChildCount() > 0) { return (TableRowBox)section.getChild(0); } } return null; } private void setCellWidths(LayoutContext c) { for (Iterator i = getChildIterator(); i.hasNext(); ) { BlockBox box = (BlockBox)i.next(); if (box.getStyle().isTableSection()) { ((TableSectionBox)box).setCellWidths(c); } } } protected void calcLayoutHeight(LayoutContext c, BorderPropertySet border, RectPropertySet margin, RectPropertySet padding) { super.calcLayoutHeight(c, border, margin, padding); if (getChildCount() > 0) { setHeight(getHeight() + getStyle().getBorderVSpacing(c)); } } public void reset(LayoutContext c) { super.reset(c); _contentLimitContainer = null; _tableLayout.reset(); } protected int getCSSWidth(CssContext c) { if (getStyle().isAutoWidth()) { return -1; } else { // XHTML 1.0 specifies that a table width refers to the border // width. This can be removed if/when we support the box-sizing // property. int result = (int)getStyle().getFloatPropertyProportionalWidth( CSSName.WIDTH, getContainingBlock().getContentWidth(), c); BorderPropertySet border = getBorder(c); result -= (int)border.left() + (int)border.right(); if (! getStyle().isCollapseBorders()) { RectPropertySet padding = getPadding(c); result -= (int)padding.left() + (int)padding.right(); } return result >= 0 ? result : -1; } } public TableColumn colElement(int col) { List styleColumns = getStyleColumns(); if (styleColumns.size() == 0) { return null; } int cCol = 0; for (Iterator i = styleColumns.iterator(); i.hasNext();) { TableColumn colElem = (TableColumn)i.next(); int span = colElem.getStyle().getColSpan(); cCol += span; if (cCol > col) { return colElem; } } return null; } public Rectangle getColumnBounds(CssContext c, int col) { int effCol = colToEffCol(col); int hspacing = getStyle().getBorderHSpacing(c); int vspacing = getStyle().getBorderVSpacing(c); Rectangle result = getContentAreaEdge(getAbsX(), getAbsY(), c); result.y += vspacing; result.height -= vspacing*2; result.x += _columnPos[effCol] + hspacing; return result; } public BorderPropertySet getBorder(CssContext cssCtx) { if (getStyle().isCollapseBorders()) { return BorderPropertySet.EMPTY_BORDER; } else { return super.getBorder(cssCtx); } } public int calcFixedHeightRowBottom(CssContext c) { if (! isAnonymous()) { int cssHeight = getCSSHeight(c); if (cssHeight != -1) { return getAbsY() + cssHeight - (int)getBorder(c).bottom() - (int)getPadding(c).bottom() - getStyle().getBorderVSpacing(c); } } return -1; } protected boolean isMayCollapseMarginsWithChildren() { return false; } protected TableSectionBox sectionAbove( TableSectionBox section, boolean skipEmptySections) { TableSectionBox prevSection = (TableSectionBox)section.getPreviousSibling(); if (prevSection == null) { return null; } while (prevSection != null) { if (prevSection.numRows() > 0 || !skipEmptySections) { break; } prevSection = (TableSectionBox)prevSection.getPreviousSibling(); } return prevSection; } protected TableSectionBox sectionBelow( TableSectionBox section, boolean skipEmptySections) { TableSectionBox nextSection = (TableSectionBox)section.getNextSibling(); if (nextSection == null) { return null; } while (nextSection != null) { if (nextSection.numRows() > 0 || !skipEmptySections) { break; } nextSection = (TableSectionBox)nextSection.getNextSibling(); } return nextSection; } protected TableCellBox cellAbove(TableCellBox cell) { // Find the section and row to look in int r = cell.getRow(); TableSectionBox section = null; int rAbove = 0; if (r > 0) { // cell is not in the first row, so use the above row in its own // section section = cell.getSection(); rAbove = r - 1; } else { section = sectionAbove(cell.getSection(), true); if (section != null) { rAbove = section.numRows() - 1; } } // Look up the cell in the section's grid, which requires effective col // index if (section != null) { int effCol = colToEffCol(cell.getCol()); TableCellBox aboveCell; // If we hit a span back up to a real cell. do { aboveCell = section.cellAt(rAbove, effCol); effCol--; } while (aboveCell == TableCellBox.SPANNING_CELL && effCol >= 0); return (aboveCell == TableCellBox.SPANNING_CELL) ? null : aboveCell; } else { return null; } } protected TableCellBox cellBelow(TableCellBox cell) { // Find the section and row to look in int r = cell.getRow() + cell.getStyle().getRowSpan() - 1; TableSectionBox section = null; int rBelow = 0; if (r < cell.getSection().numRows() - 1) { // The cell is not in the last row, so use the next row in the // section. section = cell.getSection(); rBelow = r + 1; } else { section = sectionBelow(cell.getSection(), true); if (section != null) rBelow = 0; } // Look up the cell in the section's grid, which requires effective col // index if (section != null) { int effCol = colToEffCol(cell.getCol()); TableCellBox belowCell; // If we hit a colspan back up to a real cell. do { belowCell = section.cellAt(rBelow, effCol); effCol--; } while (belowCell == TableCellBox.SPANNING_CELL && effCol >= 0); return (belowCell == TableCellBox.SPANNING_CELL) ? null : belowCell; } else { return null; } } protected TableCellBox cellLeft(TableCellBox cell) { TableSectionBox section = cell.getSection(); int effCol = colToEffCol(cell.getCol()); if (effCol == 0) { return null; } // If we hit a colspan back up to a real cell. TableCellBox prevCell; do { prevCell = section.cellAt(cell.getRow(), effCol - 1); effCol--; } while (prevCell == TableCellBox.SPANNING_CELL && effCol >= 0); return (prevCell == TableCellBox.SPANNING_CELL) ? null : prevCell; } protected TableCellBox cellRight(TableCellBox cell) { int effCol = colToEffCol(cell.getCol() + cell.getStyle().getColSpan()); if (effCol >= numEffCols()) { return null; } TableCellBox result = cell.getSection().cellAt(cell.getRow(), effCol); return (result == TableCellBox.SPANNING_CELL) ? null : result; } public int calcInlineBaseline(CssContext c) { int result = 0; boolean found = false; OUTER: for (Iterator i = getChildIterator(); i.hasNext(); ) { TableSectionBox section = (TableSectionBox)i.next(); for (Iterator j = section.getChildIterator(); j.hasNext(); ) { TableRowBox row = (TableRowBox)j.next(); found = true; result = row.getAbsY() + row.getBaseline() - getAbsY(); break OUTER; } } if (! found) { result = getHeight(); } return result; } protected int getPageClearance() { return _pageClearance; } protected void setPageClearance(int pageClearance) { _pageClearance = pageClearance; } public boolean hasContentLimitContainer() { return _contentLimitContainer != null; } public int getExtraSpaceTop() { return _extraSpaceTop; } public void setExtraSpaceTop(int extraSpaceTop) { _extraSpaceTop = extraSpaceTop; } public int getExtraSpaceBottom() { return _extraSpaceBottom; } public void setExtraSpaceBottom(int extraSpaceBottom) { _extraSpaceBottom = extraSpaceBottom; } private interface TableLayout { public void calcMinMaxWidth(LayoutContext c); public void layout(LayoutContext c); public void reset(); } /** * A specialization of AutoTableLayout used for laying out the * tables used to approximate the margin box layout algorithm from CSS3 * GCPM. */ private static class MarginTableLayout extends AutoTableLayout { public MarginTableLayout(TableBox table) { super(table); } protected int getMinColWidth() { return 0; } public void calcMinMaxWidth(LayoutContext c) { super.calcMinMaxWidth(c); Layout[] layoutStruct = getLayoutStruct(); if (layoutStruct.length == 3) { Layout center = layoutStruct[1]; if (! (center.width().isVariable() && center.maxWidth() == 0)) { if (layoutStruct[0].minWidth() > layoutStruct[2].minWidth()) { layoutStruct[2] = layoutStruct[0]; } else if (layoutStruct[2].minWidth() > layoutStruct[0].minWidth()) { layoutStruct[0] = layoutStruct[2]; } else { Layout l = new Layout(); l.setMinWidth(Math.max(layoutStruct[0].minWidth(), layoutStruct[2].minWidth())); l.setEffMinWidth(l.minWidth()); l.setMaxWidth(Math.max(layoutStruct[0].maxWidth(), layoutStruct[2].maxWidth())); l.setEffMaxWidth(l.maxWidth()); layoutStruct[0] = l; layoutStruct[2] = l; } } } } } private static class FixedTableLayout implements TableLayout { private TableBox _table; private List _widths; public FixedTableLayout(TableBox table) { _table = table; } public void reset() { _widths = null; } private void initWidths() { _widths = new ArrayList(_table.numEffCols()); for (int i = 0; i < _table.numEffCols(); i++) { _widths.add(new Length()); } } private int calcWidthArray(LayoutContext c) { initWidths(); TableBox table = _table; int cCol = 0; int nEffCols = table.numEffCols(); int usedWidth = 0; for (Iterator j = table.getStyleColumns().iterator(); j.hasNext();) { TableColumn col = (TableColumn) j.next(); int span = col.getStyle().getColSpan(); Length w = col.getStyle().asLength(c, CSSName.WIDTH); if (w.isVariable() && col.getParent() != null) { w = col.getParent().getStyle().asLength(c, CSSName.WIDTH); } long effWidth = 0; if (w.isFixed() && w.value() > 0) { effWidth = w.value(); effWidth = Math.min(effWidth, Length.MAX_WIDTH); } int usedSpan = 0; int i = 0; while (usedSpan < span) { if (cCol + i >= nEffCols) { table.appendColumn(span - usedSpan); nEffCols++; _widths.add(new Length()); } int eSpan = table.spanOfEffCol(cCol + i); if ((w.isFixed() || w.isPercent()) && w.value() > 0) { _widths.set(cCol + i, new Length(w.value() * eSpan, w.type())); usedWidth += effWidth * eSpan; } usedSpan += eSpan; i++; } cCol += i; } cCol = 0; TableRowBox firstRow = _table.getFirstRow(); if (firstRow != null) { for (Iterator j = firstRow.getChildIterator(); j.hasNext();) { TableCellBox cell = (TableCellBox) j.next(); Length w = cell.getOuterStyleWidth(c); int span = cell.getStyle().getColSpan(); long effWidth = 0; if (w.isFixed() && w.value() > 0) { effWidth = w.value(); } int usedSpan = 0; int i = 0; while (usedSpan < span) { int eSpan = _table.spanOfEffCol(cCol + i); Length columnWidth = (Length) _widths.get(cCol + i); // only set if no col element has already set it. if (columnWidth.isVariable() && !w.isVariable()) { _widths.set(cCol + i, new Length(w.value() * eSpan, w.type())); usedWidth += effWidth * eSpan; } usedSpan += eSpan; i++; } cCol += i; } } return usedWidth; } public void calcMinMaxWidth(LayoutContext c) { int bs = _table.marginsBordersPaddingAndSpacing(c); _table.calcDimensions(c); // Reset to allow layout to have another crack at this. If we're // participating in a nested max/min-width calculation, the values // calculated above may be wrong and may need updating once our // parent has a width. _table.setDimensionsCalculated(false); int mw = calcWidthArray(c) + bs; _table.setMinWidth(Math.max(mw, _table.getWidth())); _table.setMaxWidth(_table.getMinWidth()); boolean haveNonFixed = false; for (int i = 0; i < _widths.size(); i++) { Length w = (Length)_widths.get(i); if (! w.isFixed()) { haveNonFixed = true; break; } } if (haveNonFixed) { _table.setMaxWidth(Length.MAX_WIDTH); } } public void layout(LayoutContext c) { int tableWidth = _table.getWidth() - _table.marginsBordersPaddingAndSpacing(c); int available = tableWidth; int nEffCols = _table.numEffCols(); long[] calcWidth = new long[nEffCols]; for (int i = 0; i < calcWidth.length; i++) { calcWidth[i] = -1; } // first assign fixed width for ( int i = 0; i < nEffCols; i++ ) { Length l = (Length)_widths.get(i); if ( l.isFixed() ) { calcWidth[i] = l.value(); available -= l.value(); } } // assign percent width if ( available > 0 ) { int totalPercent = 0; for ( int i = 0; i < nEffCols; i++ ) { Length l = (Length)_widths.get(i); if ( l.isPercent() ) { totalPercent += l.value(); } } // calculate how much to distribute to percent cells. int base = tableWidth * totalPercent / 100; if (base > available) { base = available; } for ( int i = 0; available > 0 && i < nEffCols; i++ ) { Length l = (Length)_widths.get(i); if ( l.isPercent() ) { long w = base * l.value() / totalPercent; available -= w; calcWidth[i] = w; } } } // assign variable width if ( available > 0 ) { int totalVariable = 0; for ( int i = 0; i < nEffCols; i++ ) { Length l = (Length)_widths.get(i); if ( l.isVariable() ) { totalVariable++; } } for ( int i = 0; available > 0 && i < nEffCols; i++ ) { Length l = (Length)_widths.get(i); if ( l.isVariable() ) { int w = available / totalVariable; available -= w; calcWidth[i] = w; totalVariable--; } } } for ( int i = 0; i < nEffCols; i++ ) { if ( calcWidth[i] < 0 ) { calcWidth[i] = 0; // IE gives min 1 px... } } // spread extra space over columns if ( available > 0 ) { int total = nEffCols; // still have some width to spread int i = nEffCols; while ( i-- > 0 ) { int w = available / total; available -= w; total--; calcWidth[i] += w; } } int pos = 0; int hspacing = _table.getStyle().getBorderHSpacing(c); int[] columnPos = new int[nEffCols+1]; for ( int i = 0; i < nEffCols; i++ ) { columnPos[i] = pos; pos += calcWidth[i] + hspacing; } columnPos[columnPos.length-1] = pos; _table.setColumnPos(columnPos); } } private static class AutoTableLayout implements TableLayout { private TableBox _table; private Layout[] _layoutStruct; private List _spanCells; public AutoTableLayout(TableBox table) { _table = table; } public void reset() { _layoutStruct = null; _spanCells = null; } protected Layout[] getLayoutStruct() { return _layoutStruct; } private void fullRecalc(LayoutContext c) { _layoutStruct = new Layout[_table.numEffCols()]; for (int i = 0; i < _layoutStruct.length; i++) { _layoutStruct[i] = new Layout(); _layoutStruct[i].setMinWidth(getMinColWidth()); _layoutStruct[i].setMaxWidth(getMinColWidth()); } _spanCells = new ArrayList(); TableBox table = _table; int nEffCols = table.numEffCols(); int cCol = 0; for (Iterator j = table.getStyleColumns().iterator(); j.hasNext();) { TableColumn col = (TableColumn) j.next(); int span = col.getStyle().getColSpan(); Length w = col.getStyle().asLength(c, CSSName.WIDTH); if (w.isVariable() && col.getParent() != null) { w = col.getParent().getStyle().asLength(c, CSSName.WIDTH); } if ((w.isFixed() && w.value() == 0) || (w.isPercent() && w.value() == 0)) { w = new Length(); } int cEffCol = table.colToEffCol(cCol); if (!w.isVariable() && span == 1 && cEffCol < nEffCols) { if (table.spanOfEffCol(cEffCol) == 1) { _layoutStruct[cEffCol].setWidth(w); if (w.isFixed() && _layoutStruct[cEffCol].maxWidth() < w.value()) { _layoutStruct[cEffCol].setMaxWidth(w.value()); } } } cCol += span; } for (int i = 0; i < nEffCols; i++) { recalcColumn(c, i); } } protected int getMinColWidth() { return 1; } private void recalcColumn(LayoutContext c, int effCol) { Layout l = _layoutStruct[effCol]; // first we iterate over all rows. for (Iterator j = _table.getChildIterator(); j.hasNext();) { TableSectionBox section = (TableSectionBox) j.next(); int numRows = section.numRows(); for (int i = 0; i < numRows; i++) { TableCellBox cell = section.cellAt(i, effCol); if (cell == TableCellBox.SPANNING_CELL || cell == null) { continue; } if (cell.getStyle().getColSpan() == 1) { // A cell originates in this column. Ensure we have // a min/max width of at least 1px for this column now. l.setMinWidth(Math.max(l.minWidth(), getMinColWidth())); l.setMaxWidth(Math.max(l.maxWidth(), getMinColWidth())); cell.calcMinMaxWidth(c); if (cell.getMinWidth() > l.minWidth()) { l.setMinWidth(cell.getMinWidth()); } if (cell.getMaxWidth() > l.maxWidth()) { l.setMaxWidth(cell.getMaxWidth()); } Length w = cell.getOuterStyleOrColWidth(c); w.setValue(Math.min(Length.MAX_WIDTH, Math.max(0, w.value()))); switch (w.type()) { case Length.FIXED: if (w.value() > 0 && !l.width().isPercent()) { if (l.width().isFixed()) { if (w.value() > l.width().value()) { l.width().setValue(w.value()); } } else { l.setWidth(w); } if (w.value() > l.maxWidth()) { l.setMaxWidth(w.value()); } } break; case Length.PERCENT: if (w.value() > 0 && (!l.width().isPercent() || w.value() > l.width().value())) { l.setWidth(w); break; } } } else { if (effCol == 0 || section.cellAt(i, effCol - 1) != cell) { // This spanning cell originates in this column. // Ensure we have a min/max width of at least 1px for this column now. l.setMinWidth(Math.max(l.minWidth(), getMinColWidth())); l.setMaxWidth(Math.max(l.maxWidth(), getMinColWidth())); _spanCells.add(cell); } } } } l.setMaxWidth(Math.max(l.maxWidth(), l.minWidth())); } /* * This method takes care of colspans. effWidth is the same as width for * cells without colspans. If we have colspans, they get modified. */ private long calcEffectiveWidth(LayoutContext c) { long tMaxWidth = 0; Layout[] layoutStruct = _layoutStruct; int nEffCols = layoutStruct.length; int hspacing = _table.getStyle().getBorderHSpacing(c); for (int i = 0; i < nEffCols; i++ ) { layoutStruct[i].setEffWidth(layoutStruct[i].width()); layoutStruct[i].setEffMinWidth(layoutStruct[i].minWidth()); layoutStruct[i].setEffMaxWidth(layoutStruct[i].maxWidth()); } Collections.sort(_spanCells, new Comparator() { public int compare(Object o1, Object o2) { TableCellBox c1 = (TableCellBox)o1; TableCellBox c2 = (TableCellBox)o2; return c1.getStyle().getColSpan() - c2.getStyle().getColSpan(); } }); for (Iterator i = _spanCells.iterator(); i.hasNext(); ) { TableCellBox cell = (TableCellBox)i.next(); cell.calcMinMaxWidth(c); int span = cell.getStyle().getColSpan(); Length w = cell.getOuterStyleOrColWidth(c); if (w.value() == 0) { w = new Length(); // make it Variable } int col = _table.colToEffCol(cell.getCol()); int lastCol = col; int cMinWidth = cell.getMinWidth() + hspacing; int cMaxWidth = cell.getMaxWidth() + hspacing; int totalPercent = 0; int minWidth = 0; int maxWidth = 0; boolean allColsArePercent = true; boolean allColsAreFixed = true; boolean haveVariable = false; int fixedWidth = 0; while (lastCol < nEffCols && span > 0) { switch (layoutStruct[lastCol].width().type()) { case Length.PERCENT: totalPercent += layoutStruct[lastCol].width().value(); allColsAreFixed = false; break; case Length.FIXED: if (layoutStruct[lastCol].width().value() > 0) { fixedWidth += layoutStruct[lastCol].width().value(); allColsArePercent = false; break; } // fall through case Length.VARIABLE: haveVariable = true; // fall through default: // If the column is a percentage width, do not let the spanning cell overwrite the // width value. This caused a mis-rendering on amazon.com. // Sample snippet: // < // // //
12-3
12-3
if (!layoutStruct[lastCol].effWidth().isPercent()) { layoutStruct[lastCol].setEffWidth(new Length()); allColsArePercent = false; } else { totalPercent += layoutStruct[lastCol].effWidth().value(); } allColsAreFixed = false; } span -= _table.spanOfEffCol(lastCol); minWidth += layoutStruct[lastCol].effMinWidth(); maxWidth += layoutStruct[lastCol].effMaxWidth(); lastCol++; cMinWidth -= hspacing; cMaxWidth -= hspacing; } // adjust table max width if needed if (w.isPercent()) { if (totalPercent > w.value() || allColsArePercent) { // can't satify this condition, treat as variable w = new Length(); } else { int spanMax = Math.max(maxWidth, cMaxWidth); tMaxWidth = Math.max(tMaxWidth, spanMax * 100 / w.value()); // all non percent columns in the span get percent // values to sum up correctly. long percentMissing = w.value() - totalPercent; int totalWidth = 0; for (int pos = col; pos < lastCol; pos++) { if (!(layoutStruct[pos].width().isPercent())) { totalWidth += layoutStruct[pos].effMaxWidth(); } } for (int pos = col; pos < lastCol && totalWidth > 0; pos++) { if (!(layoutStruct[pos].width().isPercent())) { long percent = percentMissing * layoutStruct[pos].effMaxWidth() / totalWidth; totalWidth -= layoutStruct[pos].effMaxWidth(); percentMissing -= percent; if (percent > 0) { layoutStruct[pos].setEffWidth(new Length(percent, Length.PERCENT)); } else { layoutStruct[pos].setEffWidth(new Length()); } } } } } // make sure minWidth and maxWidth of the spanning cell are honoured if (cMinWidth > minWidth) { if (allColsAreFixed) { for (int pos = col; fixedWidth > 0 && pos < lastCol; pos++) { long cWidth = Math.max(layoutStruct[pos].effMinWidth(), cMinWidth * layoutStruct[pos].width().value() / fixedWidth); fixedWidth -= layoutStruct[pos].width().value(); cMinWidth -= cWidth; layoutStruct[pos].setEffMinWidth(cWidth); } } else if (allColsArePercent) { int maxw = maxWidth; int minw = minWidth; int cminw = cMinWidth; for (int pos = col; maxw > 0 && pos < lastCol; pos++) { if (layoutStruct[pos].effWidth().isPercent() && layoutStruct[pos].effWidth().value() > 0 && fixedWidth <= cMinWidth) { long cWidth = layoutStruct[pos].effMinWidth(); cWidth = Math.max(cWidth, cminw * layoutStruct[pos].effWidth().value() / totalPercent); cWidth = Math.min(layoutStruct[pos].effMinWidth() + (cMinWidth - minw), cWidth); maxw -= layoutStruct[pos].effMaxWidth(); minw -= layoutStruct[pos].effMinWidth(); cMinWidth -= cWidth; layoutStruct[pos].setEffMinWidth(cWidth); } } } else { int maxw = maxWidth; int minw = minWidth; // Give min to variable first, to fixed second, and to // others third. for (int pos = col; maxw > 0 && pos < lastCol; pos++) { if (layoutStruct[pos].width().isFixed() && haveVariable && fixedWidth <= cMinWidth) { long cWidth = Math.max(layoutStruct[pos].effMinWidth(), layoutStruct[pos].width().value()); fixedWidth -= layoutStruct[pos].width().value(); minw -= layoutStruct[pos].effMinWidth(); maxw -= layoutStruct[pos].effMaxWidth(); cMinWidth -= cWidth; layoutStruct[pos].setEffMinWidth(cWidth); } } for (int pos = col; maxw > 0 && pos < lastCol && minw < cMinWidth; pos++) { if (!(layoutStruct[pos].width().isFixed() && haveVariable && fixedWidth <= cMinWidth)) { long cWidth = Math.max(layoutStruct[pos].effMinWidth(), cMinWidth * layoutStruct[pos].effMaxWidth() / maxw); cWidth = Math.min(layoutStruct[pos].effMinWidth() + (cMinWidth - minw), cWidth); maxw -= layoutStruct[pos].effMaxWidth(); minw -= layoutStruct[pos].effMinWidth(); cMinWidth -= cWidth; layoutStruct[pos].setEffMinWidth(cWidth); } } } } if (!w.isPercent()) { if (cMaxWidth > maxWidth) { for (int pos = col; maxWidth > 0 && pos < lastCol; pos++) { long cWidth = Math.max(layoutStruct[pos].effMaxWidth(), cMaxWidth * layoutStruct[pos].effMaxWidth() / maxWidth); maxWidth -= layoutStruct[pos].effMaxWidth(); cMaxWidth -= cWidth; layoutStruct[pos].setEffMaxWidth(cWidth); } } } else { for (int pos = col; pos < lastCol; pos++) { layoutStruct[pos].setMaxWidth(Math.max(layoutStruct[pos].maxWidth(), layoutStruct[pos].minWidth())); } } } return tMaxWidth; } private boolean shouldScaleColumns(TableBox table) { return true; } public void calcMinMaxWidth(LayoutContext c) { TableBox table = _table; fullRecalc(c); Layout[] layoutStruct = _layoutStruct; long spanMaxWidth = calcEffectiveWidth(c); long minWidth = 0; long maxWidth = 0; long maxPercent = 0; long maxNonPercent = 0; int remainingPercent = 100; for (int i = 0; i < layoutStruct.length; i++) { minWidth += layoutStruct[i].effMinWidth(); maxWidth += layoutStruct[i].effMaxWidth(); if (layoutStruct[i].effWidth().isPercent()) { long percent = Math.min(layoutStruct[i].effWidth().value(), remainingPercent); long pw = (layoutStruct[i].effMaxWidth() * 100) / Math.max(percent, 1); remainingPercent -= percent; maxPercent = Math.max(pw, maxPercent); } else { maxNonPercent += layoutStruct[i].effMaxWidth(); } } if (shouldScaleColumns(table)) { maxNonPercent = (maxNonPercent * 100 + 50) / Math.max(remainingPercent, 1); maxWidth = Math.max(maxNonPercent, maxWidth); maxWidth = Math.max(maxWidth, maxPercent); } maxWidth = Math.max(maxWidth, spanMaxWidth); int bs = table.marginsBordersPaddingAndSpacing(c); minWidth += bs; maxWidth += bs; Length tw = table.getStyle().asLength(c, CSSName.WIDTH); if (tw.isFixed() && tw.value() > 0) { table.calcDimensions(c); int width = table.getWidth(); minWidth = Math.max(minWidth, width); maxWidth = minWidth; } table.setMaxWidth((int)Math.min(maxWidth, Length.MAX_WIDTH)); table.setMinWidth((int)Math.min(minWidth, Length.MAX_WIDTH)); } public void layout(LayoutContext c) { TableBox table = _table; // table layout based on the values collected in the layout // structure. int tableWidth = table.getWidth() - table.marginsBordersPaddingAndSpacing(c); int available = tableWidth; int nEffCols = table.numEffCols(); boolean havePercent = false; int numVariable = 0; int numFixed = 0; int totalVariable = 0; int totalFixed = 0; int totalPercent = 0; int allocVariable = 0; Layout[] layoutStruct = _layoutStruct; // fill up every cell with it's minWidth for (int i = 0; i < nEffCols; i++) { long w = layoutStruct[i].effMinWidth(); layoutStruct[i].setCalcWidth(w); available -= w; Length width = layoutStruct[i].effWidth(); switch (width.type()) { case Length.PERCENT: havePercent = true; totalPercent += width.value(); break; case Length.FIXED: numFixed++; totalFixed += layoutStruct[i].effMaxWidth(); // fall through break; case Length.VARIABLE: numVariable++; totalVariable += layoutStruct[i].effMaxWidth(); allocVariable += w; } } // allocate width to percent cols if (available > 0 && havePercent) { for (int i = 0; i < nEffCols; i++) { Length width = layoutStruct[i].effWidth(); if (width.isPercent()) { long w = Math.max(layoutStruct[i].effMinWidth(), width.minWidth(tableWidth)); available += layoutStruct[i].calcWidth() - w; layoutStruct[i].setCalcWidth(w); } } if (totalPercent > 100) { // remove overallocated space from the last columns int excess = tableWidth * (totalPercent - 100) / 100; for (int i = nEffCols - 1; i >= 0; i--) { if (layoutStruct[i].effWidth().isPercent()) { long w = layoutStruct[i].calcWidth(); long reduction = Math.min(w, excess); // the lines below might look inconsistent, but // that's the way it's handled in mozilla excess -= reduction; long newWidth = Math.max(layoutStruct[i].effMinWidth(), w - reduction); available += w - newWidth; layoutStruct[i].setCalcWidth(newWidth); // qDebug("col %d: reducing to %d px // (reduction=%d)", i, newWidth, reduction ); } } } } // then allocate width to fixed cols if (available > 0) { for (int i = 0; i < nEffCols; ++i) { Length width = layoutStruct[i].effWidth(); if (width.isFixed() && width.value() > layoutStruct[i].calcWidth()) { available += layoutStruct[i].calcWidth() - width.value(); layoutStruct[i].setCalcWidth(width.value()); } } } // now satisfy variable if (available > 0 && numVariable > 0) { available += allocVariable; // this gets redistributed // qDebug("redistributing %dpx to %d variable columns. // totalVariable=%d", available, numVariable, totalVariable ); for (int i = 0; i < nEffCols; i++) { Length width = layoutStruct[i].effWidth(); if (width.isVariable() && totalVariable != 0) { long w = Math.max(layoutStruct[i].calcWidth(), available * layoutStruct[i].effMaxWidth() / totalVariable); available -= w; totalVariable -= layoutStruct[i].effMaxWidth(); layoutStruct[i].setCalcWidth(w); } } } // spread over fixed colums if (available > 0 && numFixed > 0) { // still have some width to spread, distribute to fixed columns for (int i = 0; i < nEffCols; i++) { Length width = layoutStruct[i].effWidth(); if (width.isFixed()) { long w = available * layoutStruct[i].effMaxWidth() / totalFixed; available -= w; totalFixed -= layoutStruct[i].effMaxWidth(); layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + w); } } } // spread over percent colums if (available > 0 && havePercent && totalPercent < 100) { // still have some width to spread, distribute weighted to // percent columns for (int i = 0; i < nEffCols; i++) { Length width = layoutStruct[i].effWidth(); if (width.isPercent()) { long w = available * width.value() / totalPercent; available -= w; totalPercent -= width.value(); layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + w); if (available == 0 || totalPercent == 0) { break; } } } } // spread over the rest if (available > 0) { int total = nEffCols; // still have some width to spread int i = nEffCols; while (i-- > 0) { int w = available / total; available -= w; total--; layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + w); } } // if we have overallocated, reduce every cell according to the // difference between desired width and minwidth // this seems to produce to the pixel exaxt results with IE. Wonder // is some of this also holds for width distributing. if (available < 0) { // Need to reduce cells with the following prioritization: // (1) Variable // (2) Relative // (3) Fixed // (4) Percent // This is basically the reverse of how we grew the cells. if (available < 0) { int mw = 0; for (int i = nEffCols - 1; i >= 0; i--) { Length width = layoutStruct[i].effWidth(); if (width.isVariable()) mw += layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth(); } for (int i = nEffCols - 1; i >= 0 && mw > 0; i--) { Length width = layoutStruct[i].effWidth(); if (width.isVariable()) { long minMaxDiff = layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth(); long reduce = available * minMaxDiff / mw; layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + reduce); available -= reduce; mw -= minMaxDiff; if (available >= 0) break; } } } if (available < 0) { int mw = 0; for (int i = nEffCols - 1; i >= 0; i--) { Length width = layoutStruct[i].effWidth(); if (width.isFixed()) mw += layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth(); } for (int i = nEffCols - 1; i >= 0 && mw > 0; i--) { Length width = layoutStruct[i].effWidth(); if (width.isFixed()) { long minMaxDiff = layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth(); long reduce = available * minMaxDiff / mw; layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + reduce); available -= reduce; mw -= minMaxDiff; if (available >= 0) break; } } } if (available < 0) { int mw = 0; for (int i = nEffCols - 1; i >= 0; i--) { Length width = layoutStruct[i].effWidth(); if (width.isPercent()) mw += layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth(); } for (int i = nEffCols - 1; i >= 0 && mw > 0; i--) { Length width = layoutStruct[i].effWidth(); if (width.isPercent()) { long minMaxDiff = layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth(); long reduce = available * minMaxDiff / mw; layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + reduce); available -= reduce; mw -= minMaxDiff; if (available >= 0) break; } } } } int pos = 0; int hspacing = _table.getStyle().getBorderHSpacing(c); int[] columnPos = new int[nEffCols + 1]; for (int i = 0; i < nEffCols; i++) { columnPos[i] = pos; pos += layoutStruct[i].calcWidth() + hspacing; } columnPos[columnPos.length - 1] = pos; _table.setColumnPos(columnPos); } protected static class Layout { private Length _width = new Length(); private Length _effWidth = new Length(); private long _minWidth = 1; private long _maxWidth = 1; private long _effMinWidth = 0; private long _effMaxWidth = 0; private long _calcWidth = 0; public Layout() { } public Length width() { return _width; } public void setWidth(Length l) { _width = l; } public Length effWidth() { return _effWidth; } public void setEffWidth(Length l) { _effWidth = l; } public long minWidth() { return _minWidth; } public void setMinWidth(long i) { _minWidth = i; } public long maxWidth() { return _maxWidth; } public void setMaxWidth(long i) { _maxWidth = i; } public long effMinWidth() { return _effMinWidth; } public void setEffMinWidth(long i) { _effMinWidth = i; } public long effMaxWidth() { return _effMaxWidth; } public void setEffMaxWidth(long i) { _effMaxWidth = i; } public long calcWidth() { return _calcWidth; } public void setCalcWidth(long i) { _calcWidth = i; } }; } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/TableColumn.java0000644000000000000000000000363510577132662024544 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import org.w3c.dom.Element; import org.xhtmlrenderer.css.style.CalculatedStyle; import org.xhtmlrenderer.layout.Styleable; /** * An object representing an element with display: table-column or * display: table-column-group. */ public class TableColumn implements Styleable { private Element _element; private CalculatedStyle _style; private TableColumn _parent; public TableColumn() { } public TableColumn(Element element, CalculatedStyle style) { _element = element; _style = style; } public Element getElement() { return _element; } public String getPseudoElementOrClass() { return null; } public CalculatedStyle getStyle() { return _style; } public void setElement(Element e) { _element = e; } public void setStyle(CalculatedStyle style) { _style = style; } public TableColumn getParent() { return _parent; } public void setParent(TableColumn parent) { _parent = parent; } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/RowData.java0000644000000000000000000000352010577132662023671 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import java.util.ArrayList; import java.util.List; /** * A row in the table grid. The list of cells it maintains is always large * enough to set a table cell at every position in the row. If there are no * colspans, rowspans, or missing cells, the grid row will exactly correspond * to the row in the original markup. On the other hand, colspans may force * spanning cells to be inserted, rowspans will mean cells appear in more than * one grid row, and positions may be null if no cell occupies that * position in the grid. */ public class RowData { private List _row = new ArrayList(); public List getRow() { return _row; } public void extendToColumnCount(int columnCount) { while (_row.size() < columnCount) { _row.add(null); } } public void splitColumn(int pos) { TableCellBox current = (TableCellBox)_row.get(pos); _row.add(pos+1, current == null ? null : TableCellBox.SPANNING_CELL); } }xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/TableRowBox.java0000644000000000000000000004533011106164736024521 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import java.awt.Rectangle; import java.io.IOException; import java.io.Writer; import java.util.Iterator; import java.util.List; import org.xhtmlrenderer.css.constants.CSSName; import org.xhtmlrenderer.css.constants.IdentValue; import org.xhtmlrenderer.css.style.CssContext; import org.xhtmlrenderer.css.style.derived.BorderPropertySet; import org.xhtmlrenderer.css.style.derived.RectPropertySet; import org.xhtmlrenderer.layout.LayoutContext; import org.xhtmlrenderer.render.BlockBox; import org.xhtmlrenderer.render.Box; import org.xhtmlrenderer.render.ContentLimitContainer; import org.xhtmlrenderer.render.PageBox; import org.xhtmlrenderer.render.RenderingContext; public class TableRowBox extends BlockBox { private int _baseline; private boolean _haveBaseline = false; private int _heightOverride; private ContentLimitContainer _contentLimitContainer; private int _extraSpaceTop; private int _extraSpaceBottom; public TableRowBox() { } public BlockBox copyOf() { TableRowBox result = new TableRowBox(); result.setStyle(getStyle()); result.setElement(getElement()); return result; } public boolean isAutoHeight() { return getStyle().isAutoHeight() || ! getStyle().hasAbsoluteUnit(CSSName.HEIGHT); } private TableBox getTable() { // row -> section -> table return (TableBox)getParent().getParent(); } private TableSectionBox getSection() { return (TableSectionBox)getParent(); } public void layout(LayoutContext c, int contentStart) { boolean running = c.isPrint() && getTable().getStyle().isPaginateTable(); int prevExtraTop = 0; int prevExtraBottom = 0; if (running) { prevExtraTop = c.getExtraSpaceTop(); prevExtraBottom = c.getExtraSpaceBottom(); calcExtraSpaceTop(c); calcExtraSpaceBottom(c); c.setExtraSpaceTop(c.getExtraSpaceTop() + getExtraSpaceTop()); c.setExtraSpaceBottom(c.getExtraSpaceBottom() + getExtraSpaceBottom()); } super.layout(c, contentStart); if (running) { if (isShouldMoveToNextPage(c)) { if (getTable().getFirstBodyRow() == this) { // XXX Performance problem here. This forces the table // to move to the next page (which we want), but the initial // table layout run still completes (which we don't) getTable().setNeedPageClear(true); } else { setNeedPageClear(true); } } c.setExtraSpaceTop(prevExtraTop); c.setExtraSpaceBottom(prevExtraBottom); } } private boolean isShouldMoveToNextPage(LayoutContext c) { PageBox page = c.getRootLayer().getFirstPage(c, this); if (getAbsY() + getHeight() < page.getBottom()) { return false; } for (Iterator i = getChildIterator(); i.hasNext(); ) { TableCellBox cell = (TableCellBox)i.next(); int baseline = cell.calcBlockBaseline(c); if (baseline != BlockBox.NO_BASELINE && baseline < page.getBottom()) { return false; } } return true; } public void analyzePageBreaks(LayoutContext c, ContentLimitContainer container) { if (getTable().getStyle().isPaginateTable()) { _contentLimitContainer = new ContentLimitContainer(c, getAbsY()); _contentLimitContainer.setParent(container); if (container != null) { container.updateTop(c, getAbsY()); container.updateBottom(c, getAbsY() + getHeight()); } for (Iterator i = getChildIterator(); i.hasNext(); ) { Box b = (Box)i.next(); b.analyzePageBreaks(c, _contentLimitContainer); } if (container != null && _contentLimitContainer.isContainsMultiplePages()) { propagateExtraSpace(c, container, _contentLimitContainer, getExtraSpaceTop(), getExtraSpaceBottom()); } } else { super.analyzePageBreaks(c, container); } } private void calcExtraSpaceTop(LayoutContext c) { int maxBorderAndPadding = 0; for (Iterator i = getChildIterator(); i.hasNext(); ) { TableCellBox cell = (TableCellBox)i.next(); int borderAndPadding = (int)cell.getPadding(c).top() + (int)cell.getBorder(c).top(); if (borderAndPadding > maxBorderAndPadding) { maxBorderAndPadding = borderAndPadding; } } _extraSpaceTop = maxBorderAndPadding; } private void calcExtraSpaceBottom(LayoutContext c) { int maxBorderAndPadding = 0; int cRow = getIndex(); int totalRows = getSection().getChildCount(); List grid = getSection().getGrid(); if (grid.size() > 0) { List row = ((RowData)grid.get(cRow)).getRow(); for (int cCol = 0; cCol < row.size(); cCol++) { TableCellBox cell = (TableCellBox)row.get(cCol); if (cell == null || cell == TableCellBox.SPANNING_CELL) { continue; } if (cRow < totalRows - 1 && getSection().cellAt(cRow+1, cCol) == cell) { continue; } int borderAndPadding = (int)cell.getPadding(c).bottom() + (int)cell.getBorder(c).bottom(); if (borderAndPadding > maxBorderAndPadding) { maxBorderAndPadding = borderAndPadding; } } } _extraSpaceBottom = maxBorderAndPadding; } protected void layoutChildren(LayoutContext c, int contentStart) { setState(Box.CHILDREN_FLUX); ensureChildren(c); TableSectionBox section = getSection(); if (section.isNeedCellWidthCalc()) { section.setCellWidths(c); section.setNeedCellWidthCalc(false); } if (getChildrenContentType() != CONTENT_EMPTY) { int cCol = 0; for (Iterator i = getChildIterator(); i.hasNext(); ) { TableCellBox cell = (TableCellBox)i.next(); layoutCell(c, cell, 0); cCol++; } } setState(Box.DONE); } private void alignBaselineAlignedCells(LayoutContext c) { int[] baselines = new int[getChildCount()]; int lowest = Integer.MIN_VALUE; boolean found = false; for (int i = 0; i < getChildCount(); i++) { TableCellBox cell = (TableCellBox)getChild(i); if (cell.getVerticalAlign() == IdentValue.BASELINE) { int baseline = cell.calcBaseline(c); baselines[i] = baseline; if (baseline > lowest) { lowest = baseline; } found = true; } } for (int i = 0; i < getChildCount(); i++) { TableCellBox cell = (TableCellBox)getChild(i); if (cell.getVerticalAlign() == IdentValue.BASELINE) { int deltaY = lowest - baselines[i]; if (deltaY != 0) { if (c.isPrint() && cell.isPageBreaksChange(c, deltaY)) { relayoutCell(c, cell, deltaY); } else { cell.moveContent(c, deltaY); cell.setHeight(cell.getHeight() + deltaY); } } } } if (found) { setBaseline(lowest - getAbsY()); setHaveBaseline(true); } } private boolean alignMiddleAndBottomAlignedCells(LayoutContext c) { boolean needRowHeightRecalc = false; int cRow = getIndex(); int totalRows = getSection().getChildCount(); List grid = getSection().getGrid(); if (grid.size() > 0) { List row = ((RowData)grid.get(cRow)).getRow(); for (int cCol = 0; cCol < row.size(); cCol++) { TableCellBox cell = (TableCellBox)row.get(cCol); if (cell == null || cell == TableCellBox.SPANNING_CELL) { continue; } if (cRow < totalRows - 1 && getSection().cellAt(cRow+1, cCol) == cell) { continue; } IdentValue val = cell.getVerticalAlign(); if (val == IdentValue.MIDDLE || val == IdentValue.BOTTOM) { int deltaY = calcMiddleBottomDeltaY(cell, val); if (deltaY > 0) { if (c.isPrint() && cell.isPageBreaksChange(c, deltaY)) { int oldCellHeight = cell.getHeight(); relayoutCell(c, cell, deltaY); if (oldCellHeight + deltaY != cell.getHeight()) { needRowHeightRecalc = true; } } else { cell.moveContent(c, deltaY); // Set a provisional height in case we need to calculate // a default baseline cell.setHeight(cell.getHeight() + deltaY); } } } } } return needRowHeightRecalc; } private int calcMiddleBottomDeltaY(TableCellBox cell, IdentValue verticalAlign) { int result; if (cell.getStyle().getRowSpan() == 1) { result = getHeight() - cell.getChildrenHeight(); } else { result = getAbsY() + getHeight() - (cell.getAbsY() + cell.getChildrenHeight()); } if (verticalAlign == IdentValue.MIDDLE) { return result / 2; } else { /* verticalAlign == IdentValue.BOTTOM */ return result; } } protected void calcLayoutHeight( LayoutContext c, BorderPropertySet border, RectPropertySet margin, RectPropertySet padding) { if (getHeightOverride() > 0) { setHeight(getHeightOverride()); } alignBaselineAlignedCells(c); calcRowHeight(c); boolean recalcRowHeight = alignMiddleAndBottomAlignedCells(c); if (recalcRowHeight) { calcRowHeight(c); } if (! isHaveBaseline()) { calcDefaultBaseline(c); } setCellHeights(c); } private void calcRowHeight(CssContext c) { int y1 = getAbsY(); int y2; if (getHeight() != 0) { y2 = y1 + getHeight(); } else { y2 = y1; } if (isLastRow()) { int bottom = getTable().calcFixedHeightRowBottom(c); if (bottom > 0 && bottom > y2) { y2 = bottom; } } int cRow = getIndex(); int totalRows = getSection().getChildCount(); List grid = getSection().getGrid(); if (grid.size() > 0) { List row = ((RowData)grid.get(cRow)).getRow(); for (int cCol = 0; cCol < row.size(); cCol++) { TableCellBox cell = (TableCellBox)row.get(cCol); if (cell == null || cell == TableCellBox.SPANNING_CELL) { continue; } if (cRow < totalRows - 1 && getSection().cellAt(cRow+1, cCol) == cell) { continue; } int bottomCellEdge = cell.getAbsY() + cell.getHeight(); if (bottomCellEdge > y2) { y2 = bottomCellEdge; } } } setHeight(y2 - y1); } private boolean isLastRow() { TableBox table = getTable(); TableSectionBox section = getSection(); if (table.sectionBelow(section, true) == null) { return section.getChild(section.getChildCount()-1) == this; } else { return false; } } private void calcDefaultBaseline(LayoutContext c) { int lowestCellEdge = 0; int cRow = getIndex(); int totalRows = getSection().getChildCount(); List grid = getSection().getGrid(); if (grid.size() > 0) { List row = ((RowData)grid.get(cRow)).getRow(); for (int cCol = 0; cCol < row.size(); cCol++) { TableCellBox cell = (TableCellBox)row.get(cCol); if (cell == null || cell == TableCellBox.SPANNING_CELL) { continue; } if (cRow < totalRows - 1 && getSection().cellAt(cRow+1, cCol) == cell) { continue; } Rectangle contentArea = cell.getContentAreaEdge(cell.getAbsX(), cell.getAbsY(), c); int bottomCellEdge = contentArea.y + contentArea.height; if (bottomCellEdge > lowestCellEdge) { lowestCellEdge = bottomCellEdge; } } } if (lowestCellEdge > 0) { setBaseline(lowestCellEdge - getAbsY()); } setHaveBaseline(true); } private void setCellHeights(LayoutContext c) { int cRow = getIndex(); int totalRows = getSection().getChildCount(); List grid = getSection().getGrid(); if (grid.size() > 0) { List row = ((RowData)grid.get(cRow)).getRow(); for (int cCol = 0; cCol < row.size(); cCol++) { TableCellBox cell = (TableCellBox)row.get(cCol); if (cell == null || cell == TableCellBox.SPANNING_CELL) { continue; } if (cRow < totalRows - 1 && getSection().cellAt(cRow+1, cCol) == cell) { continue; } if (cell.getStyle().getRowSpan() == 1) { cell.setHeight(getHeight()); } else { cell.setHeight(getAbsY() + getHeight() - cell.getAbsY()); } } } } private void relayoutCell(LayoutContext c, TableCellBox cell, int contentStart) { int width = cell.getWidth(); cell.reset(c); cell.setLayoutWidth(c, width); layoutCell(c, cell, contentStart); } private void layoutCell(LayoutContext c, TableCellBox cell, int contentStart) { cell.initContainingLayer(c); cell.calcCanvasLocation(); cell.layout(c, contentStart); } public void initStaticPos(LayoutContext c, BlockBox parent, int childOffset) { setX(0); TableBox table = getTable(); setY(parent.getHeight() + table.getStyle().getBorderVSpacing(c)); c.translate(0, getY()-childOffset); } public int getBaseline() { return _baseline; } public void setBaseline(int baseline) { _baseline = baseline; } protected boolean isSkipWhenCollapsingMargins() { return true; } public void paintBorder(RenderingContext c) { // rows never have borders } public void paintBackground(RenderingContext c) { // painted at the cell level } public void reset(LayoutContext c) { super.reset(c); setHaveBaseline(false); getSection().setNeedCellWidthCalc(true); setContentLimitContainer(null); } public boolean isHaveBaseline() { return _haveBaseline; } public void setHaveBaseline(boolean haveBaseline) { _haveBaseline = haveBaseline; } protected String getExtraBoxDescription() { if (isHaveBaseline()) { return "(baseline=" + getBaseline() + ") "; } else { return ""; } } public int getHeightOverride() { return _heightOverride; } public void setHeightOverride(int heightOverride) { _heightOverride = heightOverride; } public void exportText(RenderingContext c, Writer writer) throws IOException { if (getTable().isMarginAreaRoot()) { super.exportText(c, writer); } else { int yPos = getAbsY(); if (yPos >= c.getPage().getBottom() && isInDocumentFlow()) { exportPageBoxText(c, writer, yPos); } for (Iterator i = getChildIterator(); i.hasNext(); ) { TableCellBox cell = (TableCellBox)i.next(); StringBuffer buffer = new StringBuffer(); cell.collectText(c, buffer); writer.write(buffer.toString().trim()); int cSpan = cell.getStyle().getColSpan(); for (int j = 0; j < cSpan; j++) { writer.write('\t'); } } writer.write(LINE_SEPARATOR); } } public ContentLimitContainer getContentLimitContainer() { return _contentLimitContainer; } public void setContentLimitContainer(ContentLimitContainer contentLimitContainer) { _contentLimitContainer = contentLimitContainer; } public int getExtraSpaceTop() { return _extraSpaceTop; } public void setExtraSpaceTop(int extraSpaceTop) { _extraSpaceTop = extraSpaceTop; } public int getExtraSpaceBottom() { return _extraSpaceBottom; } public void setExtraSpaceBottom(int extraSpaceBottom) { _extraSpaceBottom = extraSpaceBottom; } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/TableCellBox.java0000644000000000000000000007643311044764142024637 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import java.awt.Rectangle; import java.util.List; import java.util.Set; import org.xhtmlrenderer.css.constants.CSSName; import org.xhtmlrenderer.css.constants.IdentValue; import org.xhtmlrenderer.css.style.CalculatedStyle; import org.xhtmlrenderer.css.style.CssContext; import org.xhtmlrenderer.css.style.Length; import org.xhtmlrenderer.css.style.derived.BorderPropertySet; import org.xhtmlrenderer.css.style.derived.RectPropertySet; import org.xhtmlrenderer.layout.CollapsedBorderSide; import org.xhtmlrenderer.layout.FloatManager; import org.xhtmlrenderer.layout.LayoutContext; import org.xhtmlrenderer.render.BlockBox; import org.xhtmlrenderer.render.BorderPainter; import org.xhtmlrenderer.render.Box; import org.xhtmlrenderer.render.ContentLimit; import org.xhtmlrenderer.render.ContentLimitContainer; import org.xhtmlrenderer.render.PageBox; import org.xhtmlrenderer.render.RenderingContext; public class TableCellBox extends BlockBox { public static final TableCellBox SPANNING_CELL = new TableCellBox(); private int _row; private int _col; private TableBox _table; private TableSectionBox _section; private BorderPropertySet _collapsedLayoutBorder; private BorderPropertySet _collapsedPaintingBorder; private CollapsedBorderValue _collapsedBorderTop; private CollapsedBorderValue _collapsedBorderRight; private CollapsedBorderValue _collapsedBorderBottom; private CollapsedBorderValue _collapsedBorderLeft; // 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'. private static final int[] BORDER_PRIORITIES = new int[IdentValue.getIdentCount()]; static { BORDER_PRIORITIES[IdentValue.DOUBLE.FS_ID] = 1; BORDER_PRIORITIES[IdentValue.SOLID.FS_ID] = 2; BORDER_PRIORITIES[IdentValue.DASHED.FS_ID] = 3; BORDER_PRIORITIES[IdentValue.DOTTED.FS_ID] = 4; BORDER_PRIORITIES[IdentValue.RIDGE.FS_ID] = 5; BORDER_PRIORITIES[IdentValue.OUTSET.FS_ID] = 6; BORDER_PRIORITIES[IdentValue.GROOVE.FS_ID] = 7; BORDER_PRIORITIES[IdentValue.INSET.FS_ID] = 8; } private static final int BCELL = 10; private static final int BROW = 9; private static final int BROWGROUP = 8; private static final int BCOL = 7; private static final int BTABLE = 6; public TableCellBox() { } public BlockBox copyOf() { TableCellBox result = new TableCellBox(); result.setStyle(getStyle()); result.setElement(getElement()); return result; } public BorderPropertySet getBorder(CssContext cssCtx) { if (getTable().getStyle().isCollapseBorders()) { // Should always be non-null, but might not be if layout code crashed return _collapsedLayoutBorder == null ? BorderPropertySet.EMPTY_BORDER : _collapsedLayoutBorder; } else { return super.getBorder(cssCtx); } } public void calcCollapsedBorder(CssContext c) { CollapsedBorderValue top = collapsedTopBorder(c); CollapsedBorderValue right = collapsedRightBorder(c); CollapsedBorderValue bottom = collapsedBottomBorder(c); CollapsedBorderValue left = collapsedLeftBorder(c); _collapsedPaintingBorder = new BorderPropertySet(top, right, bottom, left); // Give the extra pixel to top and left. top.setWidth((top.width()+1)/2); right.setWidth(right.width()/2); bottom.setWidth(bottom.width()/2); left.setWidth((left.width()+1)/2); _collapsedLayoutBorder = new BorderPropertySet(top, right, bottom, left); _collapsedBorderTop = top; _collapsedBorderRight = right; _collapsedBorderBottom = bottom; _collapsedBorderLeft = left; } public int getCol() { return _col; } public void setCol(int col) { _col = col; } public int getRow() { return _row; } public void setRow(int row) { _row = row; } public void layout(LayoutContext c) { super.layout(c); } public TableBox getTable() { // cell -> row -> section -> table if (_table == null) { _table = (TableBox)getParent().getParent().getParent(); } return _table; } protected TableSectionBox getSection() { if (_section == null) { _section = (TableSectionBox)getParent().getParent(); } return _section; } public Length getOuterStyleWidth(CssContext c) { Length result = getStyle().asLength(c, CSSName.WIDTH); if (result.isVariable() || result.isPercent()) { return result; } int bordersAndPadding = 0; BorderPropertySet border = getBorder(c); bordersAndPadding += (int)border.left() + (int)border.right(); RectPropertySet padding = getPadding(c); bordersAndPadding += (int)padding.left() + (int)padding.right(); result.setValue(result.value() + bordersAndPadding); return result; } public Length getOuterStyleOrColWidth(CssContext c) { Length result = getOuterStyleWidth(c); if (getStyle().getColSpan() > 1 || ! result.isVariable()) { return result; } TableColumn col = getTable().colElement(getCol()); if (col != null) { // XXX Need to add in collapsed borders from cell (if collapsing borders) result = col.getStyle().asLength(c, CSSName.WIDTH); } return result; } public void setLayoutWidth(LayoutContext c, int width) { calcDimensions(c); setContentWidth(width - getLeftMBP() - getRightMBP()); } public boolean isAutoHeight() { return getStyle().isAutoHeight() || ! getStyle().hasAbsoluteUnit(CSSName.HEIGHT); } public int calcBaseline(LayoutContext c) { int result = super.calcBaseline(c); if (result != NO_BASELINE) { return result; } else { Rectangle contentArea = getContentAreaEdge(getAbsX(), getAbsY(), c); return (int)contentArea.getY(); } } public int calcBlockBaseline(LayoutContext c) { return super.calcBaseline(c); } public void moveContent(LayoutContext c, final int deltaY) { for (int i = 0; i < getChildCount(); i++) { Box b = getChild(i); b.setY(b.getY() + deltaY); } getPersistentBFC().getFloatManager().performFloatOperation( new FloatManager.FloatOperation() { public void operate(Box floater) { floater.setY(floater.getY() + deltaY); } }); calcChildLocations(); } public boolean isPageBreaksChange(LayoutContext c, int posDeltaY) { if (! c.isPageBreaksAllowed()) { return false; } PageBox page = c.getRootLayer().getFirstPage(c, this); int bottomEdge = getAbsY() + getChildrenHeight(); return bottomEdge >= page.getBottom() - c.getExtraSpaceBottom() || bottomEdge + posDeltaY >= page.getBottom() - c.getExtraSpaceBottom(); } public IdentValue getVerticalAlign() { IdentValue val = getStyle().getIdent(CSSName.VERTICAL_ALIGN); if (val == IdentValue.TOP || val == IdentValue.MIDDLE || val == IdentValue.BOTTOM) { return val; } else { return IdentValue.BASELINE; } } private boolean isPaintBackgroundsAndBorders() { boolean showEmpty = getStyle().isShowEmptyCells(); // XXX Not quite right, but good enough for now // (e.g. absolute boxes will be counted as content here when the spec // says the cell should be treated as empty). return showEmpty || getChildrenContentType() != BlockBox.CONTENT_EMPTY; } public void paintBackground(RenderingContext c) { if (isPaintBackgroundsAndBorders() && getStyle().isVisible()) { Rectangle bounds; if (c.isPrint() && getTable().getStyle().isPaginateTable()) { bounds = getContentLimitedBorderEdge(c); } else { bounds = getPaintingBorderEdge(c); } if (bounds != null) { paintBackgroundStack(c, bounds); } } } private void paintBackgroundStack(RenderingContext c, Rectangle bounds) { Rectangle imageContainer; TableColumn column = getTable().colElement(getCol()); if (column != null) { c.getOutputDevice().paintBackground( c, column.getStyle(), bounds, getTable().getColumnBounds(c, getCol())); } Box row = getParent(); Box section = row.getParent(); CalculatedStyle tableStyle = getTable().getStyle(); CalculatedStyle sectionStyle = section.getStyle(); imageContainer = section.getPaintingBorderEdge(c); imageContainer.y += tableStyle.getBorderVSpacing(c); imageContainer.height -= tableStyle.getBorderVSpacing(c); imageContainer.x += tableStyle.getBorderHSpacing(c); imageContainer.width -= 2*tableStyle.getBorderHSpacing(c); c.getOutputDevice().paintBackground(c, sectionStyle, bounds, imageContainer); CalculatedStyle rowStyle = row.getStyle(); imageContainer = row.getPaintingBorderEdge(c); imageContainer.x += tableStyle.getBorderHSpacing(c); imageContainer.width -= 2*tableStyle.getBorderHSpacing(c); c.getOutputDevice().paintBackground(c, rowStyle, bounds, imageContainer); c.getOutputDevice().paintBackground(c, getStyle(), bounds, getPaintingBorderEdge(c)); } public void paintBorder(RenderingContext c) { if (isPaintBackgroundsAndBorders() && ! hasCollapsedPaintingBorder()) { // Collapsed table borders are painted separately if (c.isPrint() && getTable().getStyle().isPaginateTable() && getStyle().isVisible()) { Rectangle bounds = getContentLimitedBorderEdge(c); if (bounds != null) { c.getOutputDevice().paintBorder(c, getStyle(), bounds, getBorderSides()); } } else { super.paintBorder(c); } } } public void paintCollapsedBorder(RenderingContext c, int side) { c.getOutputDevice().paintCollapsedBorder( c, getCollapsedPaintingBorder(), getCollapsedBorderBounds(c), side); } private Rectangle getContentLimitedBorderEdge(RenderingContext c) { Rectangle result = getPaintingBorderEdge(c); TableSectionBox section = getSection(); if (section.isHeader() || section.isFooter()) { return result; } ContentLimitContainer contentLimitContainer = ((TableRowBox)getParent()).getContentLimitContainer(); ContentLimit limit = contentLimitContainer.getContentLimit(c.getPageNo()); if (limit == null) { return null; } else { if (limit.getTop() == ContentLimit.UNDEFINED || limit.getBottom() == ContentLimit.UNDEFINED) { return result; } int top; if (c.getPageNo() == contentLimitContainer.getInitialPageNo()) { top = result.y; } else { top = limit.getTop() - ((TableRowBox)getParent()).getExtraSpaceTop() ; } int bottom; if (c.getPageNo() == contentLimitContainer.getLastPageNo()) { bottom = result.y + result.height; } else { bottom = limit.getBottom() + ((TableRowBox)getParent()).getExtraSpaceBottom(); } result.y = top; result.height = bottom - top; return result; } } public Rectangle getChildrenClipEdge(RenderingContext c) { if (c.isPrint() && getTable().getStyle().isPaginateTable()) { Rectangle bounds = getContentLimitedBorderEdge(c); if (bounds != null) { BorderPropertySet border = getBorder(c); RectPropertySet padding = getPadding(c); bounds.y += (int)border.top() + (int)padding.top(); bounds.height -= (int)border.height() + (int)padding.height(); return bounds; } } return super.getChildrenClipEdge(c); } protected boolean isFixedWidthAdvisoryOnly() { return getTable().getStyle().isIdent(CSSName.TABLE_LAYOUT, IdentValue.AUTO); } protected boolean isSkipWhenCollapsingMargins() { return true; } // The following rules apply for resolving conflicts and figuring out which // border // to use. // (1) Borders with the 'border-style' of 'hidden' take precedence over all // other conflicting // borders. Any border with this value suppresses all borders at this // location. // (2) Borders with a style of 'none' have the lowest priority. Only if the // border properties of all // the elements meeting at this edge are 'none' will the border be omitted // (but note that 'none' is // the default value for the border style.) // (3) If none of the styles are 'hidden' and at least one of them is not // 'none', then narrow borders // are discarded in favor of wider ones. If several have the same // 'border-width' then styles are preferred // in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', // 'groove', and the lowest: 'inset'. // (4) If border styles differ only in color, then a style set on a cell // wins over one on a row, // which wins over a row group, column, column group and, lastly, table. It // is undefined which color // is used when two elements of the same type disagree. public static CollapsedBorderValue compareBorders( CollapsedBorderValue border1, CollapsedBorderValue border2, boolean returnNullOnEqual) { // Sanity check the values passed in. If either is null, return the other. if (!border2.defined()) { return border1; } if (!border1.defined()) { return border2; } // Rule #1 above. if (border1.style() == IdentValue.HIDDEN) { return border1; } if (border2.style() == IdentValue.HIDDEN) { return border2; } // Rule #2 above. A style of 'none' has lowest priority and always loses // to any other border. if (border2.style() == IdentValue.NONE) { return border1; } if (border1.style() == IdentValue.NONE) { return border2; } // The first part of rule #3 above. Wider borders win. if (border1.width() != border2.width()) { return border1.width() > border2.width() ? border1 : border2; } // The borders have equal width. Sort by border style. if (border1.style() != border2.style()) { return BORDER_PRIORITIES[border1.style().FS_ID] > BORDER_PRIORITIES[border2.style().FS_ID] ? border1 : border2; } // The border have the same width and style. Rely on precedence (cell // over row over row group, etc.) if (returnNullOnEqual && border1.precedence() == border2.precedence()) { return null; } else { return border1.precedence() >= border2.precedence() ? border1 : border2; } } private static CollapsedBorderValue compareBorders( CollapsedBorderValue border1, CollapsedBorderValue border2) { return compareBorders(border1, border2, false); } private CollapsedBorderValue collapsedLeftBorder(CssContext c) { BorderPropertySet border = getStyle().getBorder(c); // For border left, we need to check, in order of precedence: // (1) Our left border. CollapsedBorderValue result = CollapsedBorderValue.borderLeft(border, BCELL); // (2) The previous cell's right border. TableCellBox prevCell = getTable().cellLeft(this); if (prevCell != null) { result = compareBorders( result, CollapsedBorderValue.borderRight(prevCell.getStyle().getBorder(c), BCELL)); if (result.hidden()) { return result; } } else if (getCol() == 0) { // (3) Our row's left border. result = compareBorders( result, CollapsedBorderValue.borderLeft(getParent().getStyle().getBorder(c), BROW)); if (result.hidden()) { return result; } // (4) Our row group's left border. result = compareBorders( result, CollapsedBorderValue.borderLeft(getSection().getStyle().getBorder(c), BROWGROUP)); if (result.hidden()) { return result; } } // (5) Our column's left border. TableColumn colElt = getTable().colElement(getCol()); if (colElt != null) { result = compareBorders( result, CollapsedBorderValue.borderLeft(colElt.getStyle().getBorder(c), BCOL)); if (result.hidden()) { return result; } } // (6) The previous column's right border. if (getCol() > 0) { colElt = getTable().colElement(getCol() - 1); if (colElt != null) { result = compareBorders( result, CollapsedBorderValue.borderRight(colElt.getStyle().getBorder(c), BCOL)); if (result.hidden()) { return result; } } } if (getCol() == 0) { // (7) The table's left border. result = compareBorders( result, CollapsedBorderValue.borderLeft(getTable().getStyle().getBorder(c), BTABLE)); if (result.hidden()) { return result; } } return result; } private CollapsedBorderValue collapsedRightBorder(CssContext c) { TableBox tableElt = getTable(); boolean inLastColumn = false; int effCol = tableElt.colToEffCol(getCol() + getStyle().getColSpan() - 1); if (effCol == tableElt.numEffCols() - 1) { inLastColumn = true; } // For border right, we need to check, in order of precedence: // (1) Our right border. CollapsedBorderValue result = CollapsedBorderValue.borderRight(getStyle().getBorder(c), BCELL); // (2) The next cell's left border. if (!inLastColumn) { TableCellBox nextCell = tableElt.cellRight(this); if (nextCell != null) { result = compareBorders(result, CollapsedBorderValue.borderLeft(nextCell.getStyle().getBorder(c), BCELL)); if (result.hidden()) { return result; } } } else { // (3) Our row's right border. result = compareBorders(result, CollapsedBorderValue.borderRight(getParent().getStyle().getBorder(c), BROW)); if (result.hidden()) { return result; } // (4) Our row group's right border. result = compareBorders(result, CollapsedBorderValue.borderRight(getSection().getStyle().getBorder(c), BROWGROUP)); if (result.hidden()) { return result; } } // (5) Our column's right border. TableColumn colElt = getTable().colElement(getCol() + getStyle().getColSpan() - 1); if (colElt != null) { result = compareBorders(result, CollapsedBorderValue.borderRight(colElt.getStyle().getBorder(c), BCOL)); if (result.hidden()) { return result; } } // (6) The next column's left border. if (!inLastColumn) { colElt = tableElt.colElement(getCol() + getStyle().getColSpan()); if (colElt != null) { result = compareBorders(result, CollapsedBorderValue.borderLeft(colElt.getStyle().getBorder(c), BCOL)); if (result.hidden()) { return result; } } } else { // (7) The table's right border. result = compareBorders(result, CollapsedBorderValue.borderRight(tableElt.getStyle().getBorder(c), BTABLE)); if (result.hidden()) { return result; } } return result; } private CollapsedBorderValue collapsedTopBorder(CssContext c) { // For border top, we need to check, in order of precedence: // (1) Our top border. CollapsedBorderValue result = CollapsedBorderValue.borderTop(getStyle().getBorder(c), BCELL); TableCellBox prevCell = getTable().cellAbove(this); if (prevCell != null) { // (2) A previous cell's bottom border. result = compareBorders(result, CollapsedBorderValue.borderBottom(prevCell.getStyle().getBorder(c), BCELL)); if (result.hidden()) { return result; } } // (3) Our row's top border. result = compareBorders(result, CollapsedBorderValue.borderTop(getParent().getStyle().getBorder(c), BROW)); if (result.hidden()) { return result; } // (4) The previous row's bottom border. if (prevCell != null) { TableRowBox prevRow = null; if (prevCell.getSection() == getSection()) { prevRow = (TableRowBox) getParent().getPreviousSibling(); } else { prevRow = prevCell.getSection().getLastRow(); } if (prevRow != null) { result = compareBorders(result, CollapsedBorderValue.borderBottom(prevRow.getStyle().getBorder(c), BROW)); if (result.hidden()) { return result; } } } // Now check row groups. TableSectionBox currSection = getSection(); if (getRow() == 0) { // (5) Our row group's top border. result = compareBorders(result, CollapsedBorderValue.borderTop(currSection.getStyle().getBorder(c), BROWGROUP)); if (result.hidden()) { return result; } // (6) Previous row group's bottom border. currSection = getTable().sectionAbove(currSection, false); if (currSection != null) { result = compareBorders(result, CollapsedBorderValue.borderBottom(currSection.getStyle().getBorder(c), BROWGROUP)); if (result.hidden()) { return result; } } } if (currSection == null) { // (8) Our column's top border. TableColumn colElt = getTable().colElement(getCol()); if (colElt != null) { result = compareBorders(result, CollapsedBorderValue.borderTop(colElt.getStyle().getBorder(c), BCOL)); if (result.hidden()) { return result; } } // (9) The table's top border. result = compareBorders(result, CollapsedBorderValue.borderTop(getTable().getStyle().getBorder(c), BTABLE)); if (result.hidden()) { return result; } } return result; } private CollapsedBorderValue collapsedBottomBorder(CssContext c) { // For border top, we need to check, in order of precedence: // (1) Our bottom border. CollapsedBorderValue result = CollapsedBorderValue.borderBottom(getStyle().getBorder(c), BCELL); TableCellBox nextCell = getTable().cellBelow(this); if (nextCell != null) { // (2) A following cell's top border. result = compareBorders(result, CollapsedBorderValue.borderTop(nextCell.getStyle().getBorder(c), BCELL)); if (result.hidden()) { return result; } } // (3) Our row's bottom border. (FIXME: Deal with rowspan!) result = compareBorders(result, CollapsedBorderValue.borderBottom(getParent().getStyle().getBorder(c), BROW)); if (result.hidden()) { return result; } // (4) The next row's top border. if (nextCell != null) { result = compareBorders(result, CollapsedBorderValue.borderTop(nextCell.getParent().getStyle().getBorder(c), BROW)); if (result.hidden()) { return result; } } // Now check row groups. TableSectionBox currSection = getSection(); if (getRow() + getStyle().getRowSpan() >= currSection.numRows()) { // (5) Our row group's bottom border. result = compareBorders(result, CollapsedBorderValue.borderBottom(currSection.getStyle().getBorder(c), BROWGROUP)); if (result.hidden()) { return result; } // (6) Following row group's top border. currSection = getTable().sectionBelow(currSection, false); if (currSection != null) { result = compareBorders(result, CollapsedBorderValue.borderTop(currSection.getStyle().getBorder(c), BROWGROUP)); if (result.hidden()) { return result; } } } if (currSection == null) { // (8) Our column's bottom border. TableColumn colElt = getTable().colElement(getCol()); if (colElt != null) { result = compareBorders(result, CollapsedBorderValue.borderBottom(colElt.getStyle().getBorder(c), BCOL)); if (result.hidden()) { return result; } } // (9) The table's bottom border. result = compareBorders(result, CollapsedBorderValue.borderBottom(getTable().getStyle().getBorder(c), BTABLE)); if (result.hidden()) { return result; } } return result; } private Rectangle getCollapsedBorderBounds(CssContext c) { BorderPropertySet border = getCollapsedPaintingBorder(); Rectangle bounds = getPaintingBorderEdge(c); bounds.x -= (int) border.left() / 2; bounds.y -= (int) border.top() / 2; bounds.width += (int) border.left() / 2 + ((int) border.right() + 1) / 2; bounds.height += (int) border.top() / 2 + ((int) border.bottom() + 1) / 2; return bounds; } public Rectangle getPaintingClipEdge(CssContext c) { if (hasCollapsedPaintingBorder()) { return getCollapsedBorderBounds(c); } else { return super.getPaintingClipEdge(c); } } public boolean hasCollapsedPaintingBorder() { return _collapsedPaintingBorder != null; } protected BorderPropertySet getCollapsedPaintingBorder() { return _collapsedPaintingBorder; } public CollapsedBorderValue getCollapsedBorderBottom() { return _collapsedBorderBottom; } public CollapsedBorderValue getCollapsedBorderLeft() { return _collapsedBorderLeft; } public CollapsedBorderValue getCollapsedBorderRight() { return _collapsedBorderRight; } public CollapsedBorderValue getCollapsedBorderTop() { return _collapsedBorderTop; } public void addCollapsedBorders(Set all, List borders) { if (_collapsedBorderTop.exists() && !all.contains(_collapsedBorderTop)) { all.add(_collapsedBorderTop); borders.add(new CollapsedBorderSide(this, BorderPainter.TOP)); } if (_collapsedBorderRight.exists() && !all.contains(_collapsedBorderRight)) { all.add(_collapsedBorderRight); borders.add(new CollapsedBorderSide(this, BorderPainter.RIGHT)); } if (_collapsedBorderBottom.exists() && !all.contains(_collapsedBorderBottom)) { all.add(_collapsedBorderBottom); borders.add(new CollapsedBorderSide(this, BorderPainter.BOTTOM)); } if (_collapsedBorderLeft.exists() && !all.contains(_collapsedBorderLeft)) { all.add(_collapsedBorderLeft); borders.add(new CollapsedBorderSide(this, BorderPainter.LEFT)); } } // Treat height as if it specifies border height (i.e. // box-sizing: border-box in CSS3). There doesn't seem to be any // justification in the spec for this, but everybody does it // (in standards mode) so I guess we will too protected int getCSSHeight(CssContext c) { if (getStyle().isAutoHeight()) { return -1; } else { int result = (int)getStyle().getFloatPropertyProportionalWidth( CSSName.HEIGHT, getContainingBlock().getContentWidth(), c); BorderPropertySet border = getBorder(c); result -= (int)border.top() + (int)border.bottom(); RectPropertySet padding = getPadding(c); result -= (int)padding.top() + (int)padding.bottom(); return result >= 0 ? result : -1; } } protected boolean isAllowHeightToShrink() { return false; } public boolean isNeedsClipOnPaint(RenderingContext c) { boolean result = super.isNeedsClipOnPaint(c); if (result) { return result; } return c.isPrint() && getTable().getStyle().isPaginateTable() && ((TableRowBox)getParent()).getContentLimitContainer().isContainsMultiplePages(); } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/newtable/CollapsedBorderValue.java0000644000000000000000000000654611044764142026376 0ustar /* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.newtable; import org.xhtmlrenderer.css.constants.IdentValue; import org.xhtmlrenderer.css.parser.FSColor; import org.xhtmlrenderer.css.style.derived.BorderPropertySet; /** * This class encapsulates all information related to a particular border side * along with an overall precedence (e.g. cell borders take precendence over * row borders). It is used when comparing overlapping borders when calculating * collapsed borders. */ public class CollapsedBorderValue { private IdentValue _style; private int _width; private FSColor _color; private int _precedence; public CollapsedBorderValue(IdentValue style, int width, FSColor color, int precedence) { _style = style; _width = width; _color = color; _precedence = precedence; } public FSColor color() { return _color; } public void setColor(FSColor color) { _color = color; } public IdentValue style() { return _style; } public void setStyle(IdentValue style) { _style = style; } public int width() { return _width; } public void setWidth(int width) { _width = width; } public int precedence() { return _precedence; } public void setPrecedence(int precedence) { _precedence = precedence; } public boolean defined() { return _style != null; } public boolean exists() { return _style != null && _style != IdentValue.NONE && _style != IdentValue.HIDDEN; } public boolean hidden() { return _style == IdentValue.HIDDEN; } public static CollapsedBorderValue borderLeft(BorderPropertySet border, int precedence) { return new CollapsedBorderValue( border.leftStyle(), (int)border.left(), border.leftColor(), precedence); } public static CollapsedBorderValue borderRight(BorderPropertySet border, int precedence) { return new CollapsedBorderValue( border.rightStyle(), (int)border.right(), border.rightColor(), precedence); } public static CollapsedBorderValue borderTop(BorderPropertySet border, int precedence) { return new CollapsedBorderValue( border.topStyle(), (int)border.top(), border.topColor(), precedence); } public static CollapsedBorderValue borderBottom(BorderPropertySet border, int precedence) { return new CollapsedBorderValue( border.bottomStyle(), (int)border.bottom(), border.bottomColor(), precedence); } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/0000755000000000000000000000000011172434416021147 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/Graphics2DRenderer.java0000644000000000000000000002643510767636540025454 0ustar /* * {{{ header & license * Copyright (c) 2004, 2005 Joshua Marinacci * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.simple; import org.w3c.dom.Document; import org.xhtmlrenderer.layout.SharedContext; import java.awt.*; import java.awt.image.BufferedImage; /** *

* Graphics2DRenderer supports headless rendering of XHTML documents, and is useful * for rendering documents directly to images.

*

*

Graphics2DRenderer supports the {@link XHTMLPanel#setDocument(Document)}, * {@link XHTMLPanel#layout()}, and {@link XHTMLPanel#render()} methods from * {@link XHTMLPanel}, as well as easy-to-use static utility methods. * For example, to render a document in an image that is 600 pixels wide use the * {@link #renderToImageAutoSize(String,int,int)} method like this:

*
 * BufferedImage img = Graphics2DRenderer.renderToImage( "test.xhtml", width);
 * 
*

*

*

*

* * @author Joshua Marinacci */ public class Graphics2DRenderer { /** * The panel we are using to render the document. */ protected XHTMLPanel panel; /** * Dimensions of the image to render, in pixels. */ protected Dimension dim; /** * Creates a new renderer with no document specified. */ public Graphics2DRenderer() { panel = new XHTMLPanel(); panel.setInteractive(false); } // ASK maybe we could change the graphics2d to be a font rendering context? /** * Lay out the document with the specified dimensions, * without rendering. * * @param g2 the canvas to layout on. * @param dim dimensions of the container for the document */ public void layout(Graphics2D g2, Dimension dim) { this.dim = dim; if (dim != null) { panel.setSize(dim); } panel.doDocumentLayout(g2); } /** * Renders the document to the given canvas. Call layout() first. * * @param g2 Canvas to render to. */ public void render(Graphics2D g2) { if (g2.getClip() == null) { g2.setClip(getMinimumSize()); } panel.paintComponent(g2); } /** * Set the document to be rendered, lays it out, and * renders it. * * @param url the URL for the document to render. */ public void setDocument(String url) { panel.setDocument(url); } /** * Sets the document to render, lays it out, and renders it. * * @param doc the Document to render * @param base_url base URL for relative links within the Document. */ public void setDocument(Document doc, String base_url) { panel.setDocument(doc, base_url); } /** * Sets the SharedContext for rendering. * * @param ctx The new renderingContext value */ public void setSharedContext(SharedContext ctx) { panel.setSharedContext(ctx); } /** * Returns the size image needed to render the document without anything * going off the side. Could be different than the dimensions passed into * layout because of text that couldn't break or a table that's set to be * too big. * * @return A rectangle sized to the minimum size required for the * document. */ public Rectangle getMinimumSize() { if (panel.getPreferredSize() != null) { return new Rectangle(0, 0, (int) panel.getPreferredSize().getWidth(), (int) panel.getPreferredSize().getHeight()); } else { return new Rectangle(0, 0, panel.getWidth(), panel.getHeight()); } } /** * Gets the SharedContext for layout and rendering. * * @return see desc */ public SharedContext getSharedContext() { return panel.getSharedContext(); } /** Returns the panel used internally for rendering. */ public XHTMLPanel getPanel() { return panel; } /** * A static utility method to automatically create an image from a * document; the image supports transparency. To render an image that does not support transparency, * use the overloaded version of this method {@link #renderToImage(String, int, int, int)}. * * @param url URL for the document to render. * @param width Width in pixels of the layout container * @param height Height in pixels of the layout container * @return Returns an Image containing the rendered document. */ public static BufferedImage renderToImage(String url, int width, int height) { return renderToImage(url, width, height, BufferedImage.TYPE_INT_ARGB); } /** * A static utility method to automatically create an image from a * document. The buffered image type must be specified. * * @param url URL for the document to render. * @param width Width in pixels of the layout container * @param height Height in pixels of the layout container * @param bufferedImageType On of the pre-defined image types for a java.awt.image.BufferedImage, such * as TYPE_INT_ARGB or TYPE_INT_RGB. * @return Returns an Image containing the rendered document. */ public static BufferedImage renderToImage(String url, int width, int height, int bufferedImageType) { Graphics2DRenderer g2r = new Graphics2DRenderer(); g2r.setDocument(url); Dimension dim = new Dimension(width, height); BufferedImage buff = new BufferedImage((int) dim.getWidth(), (int) dim.getHeight(), bufferedImageType); Graphics2D g = (Graphics2D) buff.getGraphics(); g2r.layout(g, dim); g2r.render(g); g.dispose(); return buff; } /** * A static utility method to automatically create an image from a * document, where height is determined based on document content. * To estimate a size before rendering, use {@link #setDocument(String)} * and then {@link #getMinimumSize()}. The rendered image supports transparency. * * @param url java.net.URL for the document to render. * @param width Width in pixels of the layout container * @return Returns an java.awt.Image containing the rendered document. */ public static BufferedImage renderToImageAutoSize(String url, int width){ return renderToImageAutoSize(url, width, BufferedImage.TYPE_INT_ARGB); } /** * A static utility method to automatically create an image from a * document, where height is determined based on document content. * To estimate a size before rendering, use {@link #setDocument(String)} * and then {@link #getMinimumSize()}. * * @param url java.net.URL for the document to render. * @param width Width in pixels of the layout container * @param bufferedImageType On of the pre-defined image types for a java.awt.image.BufferedImage, such * as TYPE_INT_ARGB or TYPE_INT_RGB. * @return Returns an java.awt.Image containing the rendered document. */ public static BufferedImage renderToImageAutoSize(String url, int width, int bufferedImageType) { Graphics2DRenderer g2r = new Graphics2DRenderer(); g2r.setDocument(url); Dimension dim = new Dimension(width, 1000); // do layout with temp buffer BufferedImage buff = new BufferedImage((int) dim.getWidth(), (int) dim.getHeight(), bufferedImageType); Graphics2D g = (Graphics2D) buff.getGraphics(); g2r.layout(g, new Dimension(width, 1000)); g.dispose(); // get size Rectangle rect = g2r.getMinimumSize(); // render into real buffer buff = new BufferedImage((int) rect.getWidth(), (int) rect.getHeight(), bufferedImageType); g = (Graphics2D) buff.getGraphics(); g2r.render(g); g.dispose(); // return real buffer return buff; } } /* * $Id: Graphics2DRenderer.java,v 1.22 2008/03/17 22:26:15 pdoubleya Exp $ * * $Log: Graphics2DRenderer.java,v $ * Revision 1.22 2008/03/17 22:26:15 pdoubleya * Issue 225: allow user to specify type for buffered image, instead of just defaulting to transparent image support. * * Revision 1.21 2007/08/19 22:22:54 peterbrant * Merge R8pbrant changes to HEAD * * Revision 1.20.2.1 2007/08/13 22:32:09 peterbrant * Rename doLayout() to doDocumentLayout() to avoid confusion with AWT's doLayout() * * Revision 1.20 2007/05/21 21:58:47 peterbrant * More cleanup (remove experimental threading code) * * Revision 1.19 2007/04/03 13:12:06 peterbrant * Add notification interface for layout and render exceptions / Minor clean up (remove obsolete body expand hack, remove unused API, method name improvements) * * Revision 1.18 2006/05/12 18:18:10 peterbrant * Remove dead code * * Revision 1.17 2006/04/07 07:28:39 pdoubleya * JavaDoc * * Revision 1.16 2006/01/04 19:50:16 peterbrant * More pagination bug fixes / Implement simple pagination for tables * * Revision 1.15 2005/10/27 00:09:07 tobega * Sorted out Context into RenderingContext and LayoutContext * * Revision 1.14 2005/10/26 17:01:44 peterbrant * Allow the "use threads" config property to be set on individual instances of * XHTMLPanel. * * Revision 1.13 2005/09/29 06:15:06 tobega * Patch from Peter Brant: * List of changes: * - Fix extents height calculation * - Small refactoring to Boxing to combine a method * - Make render and layout threads interruptible and add * RootPanel.shutdown() method to shut them down in an orderly manner * - Fix NPE in Graphics2DRenderer. It looks like * BasicPanel.intrinsic_size will always be null anyway? * - Fix NPE in RootPanel when enclosingScrollPane is null. * - Both RenderLoop.collapseRepaintEvents and * LayoutLoop.collapseLayoutEvents will go into an infinite loop if the * next event isn't collapsible. I added a common implementation to * RenderQueue which doesn't have this problem. * * Revision 1.12 2005/09/28 00:25:16 joshy * a bit more cleanup * Issue number: * Obtained from: * Submitted by: * Reviewed by: * * Revision 1.11 2005/09/26 22:40:21 tobega * Applied patch from Peter Brant concerning margin collapsing * * Revision 1.10 2005/06/16 07:24:52 tobega * Fixed background image bug. * Caching images in browser. * Enhanced LinkListener. * Some house-cleaning, playing with Idea's code inspection utility. * * Revision 1.9 2005/06/15 10:56:14 tobega * cleaned up a bit of URL mess, centralizing URI-resolution and loading to UserAgentCallback * * Revision 1.8 2005/06/01 21:36:43 tobega * Got image scaling working, and did some refactoring along the way * * Revision 1.7 2005/03/24 23:11:41 pdoubleya * Comments. * * */ xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/PDFRenderer.java0000644000000000000000000001521211144703726024115 0ustar package org.xhtmlrenderer.simple; import com.lowagie.text.DocumentException; import com.lowagie.text.pdf.PdfWriter; import org.xhtmlrenderer.pdf.ITextRenderer; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Map; import java.util.HashMap; /** *

* PDFRenderer supports headless rendering of XHTML documents, outputting * to PDF format. There are two static utility methods, one for rendering * a {@link java.net.URL}, {@link #renderToPDF(String, String)} and one * for rendering a {@link File}, {@link #renderToPDF(File, String)}

*

You can use this utility from the command line by passing in * the URL or file location as first parameter, and PDF path as second * parameter: *

 * java -cp %classpath% org.xhtmlrenderer.simple.PDFRenderer  
 * 
* * @author Pete Brant * @author Patrick Wright */ public class PDFRenderer { private static final Map versionMap = new HashMap(); static { versionMap.put("1.2", new Character(PdfWriter.VERSION_1_2)); versionMap.put("1.3", new Character(PdfWriter.VERSION_1_3)); versionMap.put("1.4", new Character(PdfWriter.VERSION_1_4)); versionMap.put("1.5", new Character(PdfWriter.VERSION_1_5)); versionMap.put("1.6", new Character(PdfWriter.VERSION_1_6)); versionMap.put("1.7", new Character(PdfWriter.VERSION_1_7)); } /** * Renders the XML file at the given URL as a PDF file * at the target location. * * @param url url for the XML file to render * @param pdf path to the PDF file to create * @throws IOException if the URL or PDF location is * invalid * @throws DocumentException if an error occurred * while building the Document. */ public static void renderToPDF(String url, String pdf) throws IOException, DocumentException { renderToPDF(url, pdf, null); } /** * Renders the XML file at the given URL as a PDF file * at the target location. * * @param url url for the XML file to render * @param pdf path to the PDF file to create * @param pdfVersion version of PDF to output; null uses default version * @throws IOException if the URL or PDF location is * invalid * @throws DocumentException if an error occurred * while building the Document. */ public static void renderToPDF(String url, String pdf, Character pdfVersion) throws IOException, DocumentException { ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(url); if (pdfVersion != null) renderer.setPDFVersion(pdfVersion.charValue()); doRenderToPDF(renderer, pdf); } /** * Renders the XML file as a PDF file at the target location. * * @param file XML file to render * @param pdf path to the PDF file to create * @throws IOException if the file or PDF location is * invalid * @throws DocumentException if an error occurred * while building the Document. */ public static void renderToPDF(File file, String pdf) throws IOException, DocumentException { renderToPDF(file, pdf, null); } /** * Renders the XML file as a PDF file at the target location. * * @param file XML file to render * @param pdf path to the PDF file to create * @param pdfVersion version of PDF to output; null uses default version * @throws IOException if the file or PDF location is * invalid * @throws DocumentException if an error occurred * while building the Document. */ public static void renderToPDF(File file, String pdf, Character pdfVersion) throws IOException, DocumentException { ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(file); if (pdfVersion != null) renderer.setPDFVersion(pdfVersion.charValue()); doRenderToPDF(renderer, pdf); } /** * Internal use, runs the render process * @param renderer * @param pdf * @throws com.lowagie.text.DocumentException * @throws java.io.IOException */ private static void doRenderToPDF(ITextRenderer renderer, String pdf) throws IOException, DocumentException { OutputStream os = null; try { os = new FileOutputStream(pdf); renderer.layout(); renderer.createPDF(os); os.close(); os = null; } finally { if (os != null) { try { os.close(); } catch (IOException e) { // ignore } } } } /** * Renders a file or URL to a PDF. Command line use: first * argument is URL or file path, second * argument is path to PDF file to generate. * * @param args see desc * @throws IOException if source could not be read, or if * PDF path is invalid * @throws DocumentException if an error occurs while building * the document */ public static void main(String[] args) throws IOException, DocumentException { if (args.length < 2) { usage("Incorrect argument list."); } Character pdfVersion = null; if (args.length == 3) { pdfVersion = checkVersion(args[2]); } String url = args[0]; if (url.indexOf("://") == -1) { // maybe it's a file File f = new File(url); if (f.exists()) { PDFRenderer.renderToPDF(f, args[1], pdfVersion); } else { usage("File to render is not found: " + url); } } else { PDFRenderer.renderToPDF(url, args[1], pdfVersion); } } private static Character checkVersion(String version) { final Character val = (Character) versionMap.get(version.trim()); if (val == null) { usage("Invalid PDF version number; use 1.2 through 1.7"); } return val; } /** prints out usage information, with optional error message * @param err */ private static void usage(String err) { if (err != null && err.length() > 0) { System.err.println("==>" + err); } System.err.println("Usage: ... url pdf [version]"); System.err.println(" where version (optional) is between 1.2 and 1.7"); System.exit(1); } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/XHTMLPrintable.java0000644000000000000000000000536011161571156024554 0ustar package org.xhtmlrenderer.simple; import org.xhtmlrenderer.extend.TextRenderer; import org.xhtmlrenderer.util.Uu; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.print.PageFormat; import java.awt.print.Printable; /** *

XHTMLPrintable allows you to print XHTML content to a printer instead of * rendering it to screen. It is an implementation of @see java.awt.print.Printable * so you can use it any where you would use any other Printable object. The constructor * requires an XHTMLPanel, so it's easiest to prepare an XHTMLPanel as normal, and then * wrap a printable around it.ex: *

*

*

 * import org.xhtmlrenderer.simple.*;
 * import java.awt.print.*;
 * // . . . .
 * // xhtml_panel created earlier
 * 

* PrinterJob printJob = PrinterJob.getPrinterJob(); * printJob.setPrintable(new XHTMLPrintable(xhtml_panel)); *

* if(printJob.printDialog()) { * printJob.print(); * } *

*/ public class XHTMLPrintable implements Printable { protected XHTMLPanel panel; protected Graphics2DRenderer g2r = null; /** * Creates a new XHTMLPrintable that will print * the current contents of the passed in XHTMLPanel. * * @param panel the XHTMLPanel to print */ public XHTMLPrintable(XHTMLPanel panel) { this.panel = panel; } /** *

The implementation of the print method * from the @see java.awt.print.Printable interface. */ public int print(Graphics g, PageFormat pf, int page) { try { Graphics2D g2 = (Graphics2D) g; if (g2r == null) { g2r = new Graphics2DRenderer(); g2r.getSharedContext().setPrint(true); g2r.getSharedContext().setInteractive(false); g2r.getSharedContext().setDPI(72f); g2r.getSharedContext().getTextRenderer().setSmoothingThreshold(0); g2r.getSharedContext().setUserAgentCallback(panel.getSharedContext().getUserAgentCallback()); g2r.setDocument(panel.getDocument(), panel.getSharedContext().getUac().getBaseURL()); g2r.getSharedContext().setReplacedElementFactory(panel.getSharedContext().getReplacedElementFactory()); g2r.layout(g2, null); g2r.getPanel().assignPagePrintPositions(g2); } if (page >= g2r.getPanel().getRootLayer().getPages().size()) { return Printable.NO_SUCH_PAGE; } // render the document g2r.getPanel().paintPage(g2, page); return Printable.PAGE_EXISTS; } catch (Exception ex) { Uu.p(ex); return Printable.NO_SUCH_PAGE; } } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/package.html0000644000000000000000000000571610220056246023433 0ustar

Includes those classes you need to render XHTML documents quickly, right out of the box, and with no special setup needed; start here! All the classes in this package are oriented towards ease-of-use. You should be able to render documents on screen, convert them to image files and print them with almost no work at all. We'll document the most important classes here; see the individual class documents for details on how to use them in your programs.

All classes in this package are intended for ease-of-use, with no customization required. To render a document quickly, use {@link org.xhtmlrenderer.simple.XHTMLPanel}--just instantiate the panel, add it to a scroll pane or {@link org.xhtmlrenderer.simple.FSScrollPane}, and call {@link org.xhtmlrenderer.simple.XHTMLPanel#setDocument(Document)}. You can render from a {@link org.w3c.dom.Document}, from a {@link java.net.URL}, from a file, and from an {@link java.io.InputStream}.

The {@link org.xhtmlrenderer.simple.Graphics2DRenderer} allows you to render XHTML right to image files-- without displaying them onscreen at all. You can use any XHTML/XML/CSS combination and dump it straight to a JPEG, GIF, or other file format supported by the Java image APIs.

{@link org.xhtmlrenderer.simple.FSScrollPane} is a JScrollPane with key bindings for scrolling through a document-- just as you would expect from a browsable XHTML document. Drop your {@link org.xhtmlrenderer.simple.XHTMLPanel} in a {@link org.xhtmlrenderer.simple.FSScrollPane} and your users can move up or down by line or page, and jump to the start or end of the document, just as they are used to.

{@link org.xhtmlrenderer.simple.XHTMLPrintable} supports the AWT {@link java.awt.print.Printable} interface, allowing you to print a document without rendering it onscreen first.

Related Documentation

For overviews, tutorials, examples, guides, and tool documentation, please see: xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/0000755000000000000000000000000011146114772022437 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/XhtmlForm.java0000644000000000000000000001622111146114774025226 0ustar /* * {{{ header & license * Copyright (c) 2004, 2005 Torbjrn Gannholm * Copyright (c) 2007 Sean Bright * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.simple.extend; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import javax.swing.AbstractButton; import javax.swing.ButtonGroup; import javax.swing.JComponent; import javax.swing.JRadioButton; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; import org.xhtmlrenderer.extend.UserAgentCallback; import org.xhtmlrenderer.simple.extend.form.FormField; import org.xhtmlrenderer.simple.extend.form.FormFieldFactory; import org.xhtmlrenderer.util.XRLog; /** * Represents a form object * * @author Torbjrn Gannholm * @author Sean Bright */ public class XhtmlForm { private static final String FS_DEFAULT_GROUP = "__fs_default_group_"; public static JComponent HIDDEN_FIELD = new JComponent() { private static final long serialVersionUID = 1L; }; private static int _defaultGroupCount = 1; private UserAgentCallback _userAgentCallback; private Map _componentCache; private Map _buttonGroups; private Element _parentFormElement; private FormSubmissionListener _formSubmissionListener; public XhtmlForm(UserAgentCallback uac, Element e, FormSubmissionListener fsListener) { _userAgentCallback = uac; _buttonGroups = new HashMap(); _componentCache = new LinkedHashMap(); _parentFormElement = e; _formSubmissionListener = fsListener; } public XhtmlForm(UserAgentCallback uac, Element e) { this(uac, e, new DefaultFormSubmissionListener()); } public UserAgentCallback getUserAgentCallback() { return _userAgentCallback; } public void addButtonToGroup(String groupName, AbstractButton button) { if (groupName == null) { groupName = createNewDefaultGroupName(); } ButtonGroupWrapper group = (ButtonGroupWrapper) _buttonGroups.get(groupName); if (group == null) { group = new ButtonGroupWrapper(); _buttonGroups.put(groupName, group); } group.add(button); } private static String createNewDefaultGroupName() { return FS_DEFAULT_GROUP + ++_defaultGroupCount; } private static boolean isFormField(Element e) { String nodeName = e.getNodeName(); if (nodeName.equals("input") || nodeName.equals("select") || nodeName.equals("textarea")) { return true; } return false; } public JComponent addComponent(Element e) { FormField field = null; if (_componentCache.containsKey(e)) { field = (FormField) _componentCache.get(e); } else { if (!isFormField(e)) { return null; } field = FormFieldFactory.create(e, this); if (field == null) { XRLog.layout("Unknown field type: " + e.getNodeName()); return null; } _componentCache.put(e, field); } return field.getComponent(); } public void reset() { Iterator buttonGroups = _buttonGroups.values().iterator(); while (buttonGroups.hasNext()) { ((ButtonGroupWrapper) buttonGroups.next()).clearSelection(); } Iterator fields = _componentCache.values().iterator(); while (fields.hasNext()) { ((FormField) fields.next()).reset(); } } public void submit(JComponent source) { // If we don't have a
to tell us what to do, don't // do anything. if (_parentFormElement == null) { return; } StringBuffer data = new StringBuffer(); String action = _parentFormElement.getAttribute("action"); data.append(action).append("?"); Iterator fields = _componentCache.entrySet().iterator(); boolean first=true; while (fields.hasNext()) { Map.Entry entry = (Map.Entry) fields.next(); FormField field = (FormField) entry.getValue(); if (field.includeInSubmission(source)) { String [] dataStrings = field.getFormDataStrings(); for (int i = 0; i < dataStrings.length; i++) { if (!first) { data.append('&'); } data.append(dataStrings[i]); first=false; } } } if(_formSubmissionListener !=null) _formSubmissionListener.submit(data.toString()); } public static String collectText(Element e) { StringBuffer result = new StringBuffer(); Node node = e.getFirstChild(); if (node != null) { do { short nodeType = node.getNodeType(); if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { Text text = (Text) node; result.append(text.getData()); } } while ((node = node.getNextSibling()) != null); } return result.toString().trim(); } private static class ButtonGroupWrapper { private ButtonGroup _group; private AbstractButton _dummy; public ButtonGroupWrapper() { _group = new ButtonGroup(); _dummy = new JRadioButton(); // We need a dummy button to have the appearance of all of // the radio buttons being in an unselected state. // // From: // http://java.sun.com/j2se/1.5/docs/api/javax/swing/ButtonGroup.html // // "There is no way to turn a button programmatically to 'off', in // order to clear the button group. To give the appearance of 'none // selected', add an invisible radio button to the group and then // programmatically select that button to turn off all the displayed // radio buttons. For example, a normal button with the label 'none' // could be wired to select the invisible radio button. _group.add(_dummy); } public void add(AbstractButton b) { _group.add(b); } public void clearSelection() { _group.setSelected(_dummy.getModel(), true); } } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/FormSubmissionListener.java0000644000000000000000000000257411146113174027772 0ustar /* * {{{ header & license * Copyright (c) 2009 Christophe Marchand * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.simple.extend; /** * FormSubmissionListener is used to receive callbacks when an XhtmlForm has its submit action called. The entire * query string is given over to the {@link #submit(String)} method, which can then be submitted back to the panel * for loading. * * * @author Christophe Marchand */ public interface FormSubmissionListener { /** * Called by XhtmlForm when a form is submitted. * * @param query the entire query string as composed from form elements and the form's action URL */ void submit(String query); }xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/URLUTF8Encoder.java0000644000000000000000000001301610177037126025714 0ustar /** public domain */ package org.xhtmlrenderer.simple.extend; /** * Provides a method to encode any string into a URL-safe form. Non-ASCII * characters are first encoded as sequences of two or three bytes, using the * UTF-8 algorithm, before being encoded as %HH escapes. * * @author Torbjrn Gannholm */ public class URLUTF8Encoder { /** Description of the Field */ final static String[] hex = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27", "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f", "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37", "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f", "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47", "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f", "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57", "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f", "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67", "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f", "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77", "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f", "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af", "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7", "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf", "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf", "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df", "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7", "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef", "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" }; /** * Encode a string to the "x-www-form-urlencoded" form, enhanced with the * UTF-8-in-URL proposal. This is what happens:

* * *

    *
  • * * The ASCII characters 'a' through 'z', 'A' through 'Z', and '0' through * '9' remain the same.

    * * *

  • * * The unreserved characters - _ . ! ~ * ' ( ) remain the same.

    * * *

  • * * The space character ' ' is converted into a plus sign '+'.

    * * *

  • * * All other ASCII characters are converted into the 3-character string * "%xy", where xy is the two-digit hexadecimal representation of the * character code

    * * *

  • * * All non-ASCII characters are encoded in two steps: first to a sequence * of 2 or 3 bytes, using the UTF-8 algorithm; secondly each of these * bytes is encoded as "%xx". *

* * * @param s The string to be encoded * @return The encoded string */ public static String encode( String s ) { StringBuffer sbuf = new StringBuffer(); int len = s.length(); for ( int i = 0; i < len; i++ ) { int ch = s.charAt( i ); append( sbuf, ch ); } return sbuf.toString(); } /** * Description of the Method * * @param chars PARAM * @return Returns */ public static String encode( char[] chars ) { StringBuffer sbuf = new StringBuffer(); int len = chars.length; for ( int i = 0; i < len; i++ ) { int ch = chars[i]; append( sbuf, ch ); } return sbuf.toString(); } /** * Description of the Method * * @param sbuf PARAM * @param ch PARAM */ private static void append( StringBuffer sbuf, int ch ) { if ( 'A' <= ch && ch <= 'Z' ) {// 'A'..'Z' sbuf.append( (char)ch ); } else if ( 'a' <= ch && ch <= 'z' ) {// 'a'..'z' sbuf.append( (char)ch ); } else if ( '0' <= ch && ch <= '9' ) {// '0'..'9' sbuf.append( (char)ch ); } else if ( ch == ' ' ) {// space sbuf.append( '+' ); } else if ( ch == '-' || ch == '_' // unreserved || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\'' || ch == '(' || ch == ')' ) { sbuf.append( (char)ch ); } else if ( ch <= 0x007f ) {// other ASCII sbuf.append( hex[ch] ); } else if ( ch <= 0x07FF ) {// non-ASCII <= 0x7FF sbuf.append( hex[0xc0 | ( ch >> 6 )] ); sbuf.append( hex[0x80 | ( ch & 0x3F )] ); } else {// 0x7FF < ch <= 0xFFFF sbuf.append( hex[0xe0 | ( ch >> 12 )] ); sbuf.append( hex[0x80 | ( ( ch >> 6 ) & 0x3F )] ); sbuf.append( hex[0x80 | ( ch & 0x3F )] ); } } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/XhtmlNamespaceHandler.java0000644000000000000000000002125710671664400027520 0ustar /* * Copyright (c) 2004, 2005 Torbjrn Gannholm * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.xhtmlrenderer.simple.extend; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * Handles xhtml documents, including presentational html attributes (see css 2.1 spec, 6.4.4). * In this class ONLY handling (css equivalents) of presentational properties * (according to css 2.1 spec, section 6.4.4) should be specified. * * @author Torbjrn Gannholm */ public class XhtmlNamespaceHandler extends XhtmlCssOnlyNamespaceHandler { /** * {@inheritDoc} */ public boolean isImageElement(Element e) { return (e != null && e.getNodeName().equalsIgnoreCase("img")); } /** * {@inheritDoc} */ public boolean isFormElement(Element e) { return (e != null && e.getNodeName().equalsIgnoreCase("form")); } public String getImageSourceURI(Element e) { String uri = null; if (e != null) { uri = e.getAttribute("src"); } return uri; } public String getNonCssStyling(Element e) { if (e.getNodeName().equals("table")) { return applyTableStyles(e); } else if (e.getNodeName().equals("td") || e.getNodeName().equals("th")) { return applyTableCellStyles(e); } else if (e.getNodeName().equals("tr")) { return applyTableRowStyles(e); } else if (e.getNodeName().equals("img")) { return applyImgStyles(e); } else if (e.getNodeName().equals("p") || e.getNodeName().equals("div")) { return applyBlockAlign(e); } return ""; } private String applyBlockAlign(Element e) { StringBuffer style = new StringBuffer(); applyTextAlign(e, style); return style.toString(); } private String applyImgStyles(Element e) { StringBuffer style = new StringBuffer(); applyFloatingAlign(e, style); return style.toString(); } private String applyTableCellStyles(Element e) { StringBuffer style = new StringBuffer(); String s; //check for cellpadding Element table = findTable(e); if (table != null) { s = getAttribute(table, "cellpadding"); if (s != null) { style.append("padding: "); style.append(convertToLength(s)); style.append(";"); } s = getAttribute(table, "border"); if (s != null && ! s.equals("0")) { style.append("border: 1px outset black;"); } } s = getAttribute(e, "width"); if (s != null) { style.append("width: "); style.append(convertToLength(s)); style.append(";"); } s = getAttribute(e, "height"); if (s != null) { style.append("height: "); style.append(convertToLength(s)); style.append(";"); } applyTableContentAlign(e, style); s = getAttribute(e, "bgcolor"); if (s != null) { s = s.toLowerCase(); style.append("background-color: "); if (looksLikeAMangledColor(s)) { style.append('#'); style.append(s); } else { style.append(s); } style.append(';'); } s = getAttribute(e, "background"); if (s != null) { style.append("background-image: url("); style.append(s); style.append(");"); } return style.toString(); } private String applyTableStyles(Element e) { StringBuffer style = new StringBuffer(); String s; s = getAttribute(e, "width"); if (s != null) { style.append("width: "); style.append(convertToLength(s)); style.append(";"); } s = getAttribute(e, "border"); if (s != null) { style.append("border: "); style.append(convertToLength(s)); style.append(" inset black;"); } s = getAttribute(e, "cellspacing"); if (s != null) { style.append("border-collapse: separate; border-spacing: "); style.append(convertToLength(s)); style.append(";"); } s = getAttribute(e, "bgcolor"); if (s != null) { s = s.toLowerCase(); style.append("background-color: "); if (looksLikeAMangledColor(s)) { style.append('#'); style.append(s); } else { style.append(s); } style.append(';'); } s = getAttribute(e, "background"); if (s != null) { style.append("background-image: url("); style.append(s); style.append(");"); } applyFloatingAlign(e, style); return style.toString(); } private String applyTableRowStyles(Element e) { StringBuffer style = new StringBuffer(); applyTableContentAlign(e, style); return style.toString(); } private void applyFloatingAlign(Element e, StringBuffer style) { String s; s = getAttribute(e, "align"); if (s != null) { s = s.toLowerCase().trim(); if (s.equals("left")) { style.append("float: left;"); } else if (s.equals("right")) { style.append("float: right;"); } else if (s.equals("center")) { style.append("margin-left: auto; margin-right: auto;"); } } } private void applyTextAlign(Element e, StringBuffer style) { String s; s = getAttribute(e, "align"); if (s != null) { s = s.toLowerCase().trim(); if (s.equals("left") || s.equals("right") || s.equals("center") || s.equals("justify")) { style.append("text-align: "); style.append(s); style.append(";"); } } } private void applyTableContentAlign(Element e, StringBuffer style) { String s; s = getAttribute(e, "align"); if (s != null) { style.append("text-align: "); style.append(s.toLowerCase()); style.append(";"); } s = getAttribute(e, "valign"); if (s != null) { style.append("vertical-align: "); style.append(s.toLowerCase()); style.append(";"); } } private boolean looksLikeAMangledColor(String s) { if (s.length() != 6) { return false; } for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); boolean valid = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'); if (! valid) { return false; } } return true; } private Element findTable(Element cell) { Node n = cell.getParentNode(); Element next; if (n.getNodeType() == Node.ELEMENT_NODE) { next = (Element)n; if (next.getNodeName().equals("tr")) { n = next.getParentNode(); if (n.getNodeType() == Node.ELEMENT_NODE) { next = (Element)n; String name = next.getNodeName(); if (name.equals("table")) { return next; } if (name.equals("tbody") || name.equals("tfoot") || name.equals("thead")) { n = next.getParentNode(); if (n.getNodeType() == Node.ELEMENT_NODE) { next =(Element)n; if (next.getNodeName().equals("table")) { return next; } } } } } } return null; } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/XhtmlCssOnlyNamespaceHandler.java0000644000000000000000000003327711035516172031035 0ustar /* * Copyright (c) 2005 Torbj�rn Gannholm * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.xhtmlrenderer.simple.extend; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.w3c.dom.CharacterData; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xhtmlrenderer.css.extend.StylesheetFactory; import org.xhtmlrenderer.css.sheet.Stylesheet; import org.xhtmlrenderer.css.sheet.StylesheetInfo; import org.xhtmlrenderer.swing.NoNamespaceHandler; import org.xhtmlrenderer.util.Configuration; import org.xhtmlrenderer.util.XRLog; /** * Handles xhtml but only css styling is honored, * no presentational html attributes (see css 2.1 spec, 6.4.4) */ public class XhtmlCssOnlyNamespaceHandler extends NoNamespaceHandler { /** * Description of the Field */ final static String _namespace = "http://www.w3.org/1999/xhtml"; private static StylesheetInfo _defaultStylesheet; private static boolean _defaultStylesheetError = false; /** * Gets the namespace attribute of the XhtmlNamespaceHandler object * * @return The namespace value */ public String getNamespace() { return _namespace; } /** * Gets the class attribute of the XhtmlNamespaceHandler object * * @param e PARAM * @return The class value */ public String getClass(org.w3c.dom.Element e) { return e.getAttribute("class"); } /** * Gets the iD attribute of the XhtmlNamespaceHandler object * * @param e PARAM * @return The iD value */ public String getID(org.w3c.dom.Element e) { String result = e.getAttribute("id").trim(); return result.length() == 0 ? null : result; } protected String convertToLength(String value) { if (isInteger(value)) { return value + "px"; } else { return value; } } protected boolean isInteger(String value) { for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (! (c >= '0' && c <= '9')) { return false; } } return true; } protected String getAttribute(Element e, String attrName) { String result = e.getAttribute(attrName); result = result.trim(); return result.length() == 0 ? null : result; } /** * Gets the elementStyling attribute of the XhtmlNamespaceHandler object * * @param e PARAM * @return The elementStyling value */ public String getElementStyling(org.w3c.dom.Element e) { StringBuffer style = new StringBuffer(); if (e.getNodeName().equals("td") || e.getNodeName().equals("th")) { String s; s = getAttribute(e, "colspan"); if (s != null) { style.append("-fs-table-cell-colspan: "); style.append(s); style.append(";"); } s = getAttribute(e, "rowspan"); if (s != null) { style.append("-fs-table-cell-rowspan: "); style.append(s); style.append(";"); } } else if (e.getNodeName().equals("img")) { String s; s = getAttribute(e, "width"); if (s != null) { style.append("width: "); style.append(convertToLength(s)); style.append(";"); } s = getAttribute(e, "height"); if (s != null) { style.append("height: "); style.append(convertToLength(s)); style.append(";"); } } else if (e.getNodeName().equals("colgroup") || e.getNodeName().equals("col")) { String s; s = getAttribute(e, "span"); if (s != null) { style.append("-fs-table-cell-colspan: "); style.append(s); style.append(";"); } s = getAttribute(e, "width"); if (s != null) { style.append("width: "); style.append(convertToLength(s)); style.append(";"); } } style.append(e.getAttribute("style")); return style.toString(); } /** * Gets the linkUri attribute of the XhtmlNamespaceHandler object * * @param e PARAM * @return The linkUri value */ public String getLinkUri(org.w3c.dom.Element e) { String href = null; if (e.getNodeName().equalsIgnoreCase("a") && e.hasAttribute("href")) { href = e.getAttribute("href"); } return href; } public String getAnchorName(Element e) { if (e != null && e.getNodeName().equalsIgnoreCase("a") && e.hasAttribute("name")) { return e.getAttribute("name"); } return null; } private static String readTextContent(Element element) { StringBuffer result = new StringBuffer(); Node current = element.getFirstChild(); while (current != null) { short nodeType = current.getNodeType(); if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { Text t = (Text)current; result.append(t.getData()); } current = current.getNextSibling(); } return result.toString(); } private static String collapseWhiteSpace(String text) { StringBuffer result = new StringBuffer(); int l = text.length(); for (int i = 0; i < l; i++) { char c = text.charAt(i); if (Character.isWhitespace(c)) { result.append(' '); while (++i < l) { c = text.charAt(i); if (! Character.isWhitespace(c)) { i--; break; } } } else { result.append(c); } } return result.toString(); } /** * Returns the title of the document as located in the contents of /html/head/title, or "" if none could be found. * * @param doc the document to search for a title * @return The document's title, or "" if none found */ public String getDocumentTitle(org.w3c.dom.Document doc) { String title = ""; Element html = doc.getDocumentElement(); Element head = findFirstChild(html, "head"); if (head != null) { Element titleElem = findFirstChild(head, "title"); if (titleElem != null) { title = collapseWhiteSpace(readTextContent(titleElem).trim()); } } return title; } private Element findFirstChild(Element parent, String targetName) { NodeList children = parent.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node n = (Node)children.item(i); if (n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equals(targetName)) { return (Element)n; } } return null; } protected StylesheetInfo readStyleElement(Element style) { String media = style.getAttribute("media"); if ("".equals(media)) { media = "all"; }//default for HTML is "screen", but that is silly and firefox seems to assume "all" StylesheetInfo info = new StylesheetInfo(); info.setMedia(media); info.setType(style.getAttribute("type")); info.setTitle(style.getAttribute("title")); info.setOrigin(StylesheetInfo.AUTHOR); StringBuffer buf = new StringBuffer(); Node current = style.getFirstChild(); while (current != null) { if (current instanceof CharacterData) { buf.append(((CharacterData)current).getData()); } current = current.getNextSibling(); } String css = buf.toString().trim(); if (css.length() > 0) { info.setContent(css.toString()); return info; } else { return null; } } protected StylesheetInfo readLinkElement(Element link) { String rel = link.getAttribute("rel").toLowerCase(); if (rel.indexOf("alternate") != -1) { return null; }//DON'T get alternate stylesheets if (rel.indexOf("stylesheet") == -1) { return null; } String type = link.getAttribute("type"); if (! (type.equals("") || type.equals("text/css"))) { return null; } StylesheetInfo info = new StylesheetInfo(); if (type.equals("")) { type = "text/css"; } // HACK is not entirely correct because default may be set by META tag or HTTP headers info.setType(type); info.setOrigin(StylesheetInfo.AUTHOR); info.setUri(link.getAttribute("href")); String media = link.getAttribute("media"); if ("".equals(media)) { media = "all"; } info.setMedia(media); String title = link.getAttribute("title"); info.setTitle(title); return info; } /** * Gets the stylesheetLinks attribute of the XhtmlNamespaceHandler object * * @param doc PARAM * @return The stylesheetLinks value */ public StylesheetInfo[] getStylesheets(org.w3c.dom.Document doc) { List result = new ArrayList(); //get the processing-instructions (actually for XmlDocuments) result.addAll(Arrays.asList(super.getStylesheets(doc))); //get the link elements Element html = doc.getDocumentElement(); Element head = findFirstChild(html, "head"); if (head != null) { Node current = head.getFirstChild(); while (current != null) { if (current.getNodeType() == Node.ELEMENT_NODE) { Element elem = (Element)current; StylesheetInfo info = null; String elemName = elem.getLocalName(); if (elemName == null) { elemName = elem.getTagName(); } if (elemName.equals("link")) { info = readLinkElement(elem); } else if (elemName.equals("style")) { info = readStyleElement(elem); } if (info != null) { result.add(info); } } current = current.getNextSibling(); } } return (StylesheetInfo[])result.toArray(new StylesheetInfo[result.size()]); } public StylesheetInfo getDefaultStylesheet(StylesheetFactory factory) { synchronized (XhtmlCssOnlyNamespaceHandler.class) { if (_defaultStylesheet != null) { return _defaultStylesheet; } if (_defaultStylesheetError) { return null; } StylesheetInfo info = new StylesheetInfo(); info.setUri(getNamespace()); info.setOrigin(StylesheetInfo.USER_AGENT); info.setMedia("all"); info.setType("text/css"); InputStream is = null; try { is = getDefaultStylesheetStream(); if (_defaultStylesheetError) { return null; } Stylesheet sheet = factory.parse(new InputStreamReader(is), info); info.setStylesheet(sheet); is.close(); is = null; } catch (Exception e) { _defaultStylesheetError = true; XRLog.exception("Could not parse default stylesheet", e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { // ignore } } } _defaultStylesheet = info; return _defaultStylesheet; } } private InputStream getDefaultStylesheetStream() { InputStream stream = null; String defaultStyleSheet = Configuration.valueFor("xr.css.user-agent-default-css") + "XhtmlNamespaceHandler.css"; stream = this.getClass().getResourceAsStream(defaultStyleSheet); if (stream == null) { XRLog.exception("Can't load default CSS from " + defaultStyleSheet + "." + "This file must be on your CLASSPATH. Please check before continuing."); _defaultStylesheetError = true; } return stream; } } ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootxhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/DefaultFormSubmissionListener.javaxhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/DefaultFormSubmissionListener.jav0000644000000000000000000000215011146114774031133 0ustar /* * {{{ header & license * Copyright (c) 2009 Patrick Wright * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.simple.extend; /** * No-op implementation of a FormSubmissionListener; override the submit method in a subclass as needed. */ public class DefaultFormSubmissionListener implements FormSubmissionListener { /** * {@inheritDoc} */ public void submit(String query) { } } xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/form/0000755000000000000000000000000011076705632023405 5ustar xhtmlrenderer-0.0~R8.orig/src/java/org/xhtmlrenderer/simple/extend/form/ButtonField.java0000644000000000000000000000372610622675274026503 0ustar /* * {{{ header & license * Copyright (c) 2007 Sean Bright * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.simple.extend.form; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JOptionPane; import org.w3c.dom.Element; import org.xhtmlrenderer.simple.extend.XhtmlForm; class ButtonField extends InputField { public ButtonField(Element e, XhtmlForm form) { super(e, form); } public JComponent create() { JButton button = new JButton(); if (hasAttribute("value")) { button.setText(getAttribute("value")); } button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog( null, " doesn't make much " + "sense without