All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.openhtmltopdf.render.simplepainter.SimplePainter Maven / Gradle / Ivy

Go to download

Open HTML to PDF is a CSS 2.1 renderer written in Java. This artifact contains the core rendering and layout code.

There is a newer version: 1.0.10
Show newest version
package com.openhtmltopdf.render.simplepainter;

import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.List;
import java.util.Map;

import com.openhtmltopdf.layout.CollapsedBorderSide;
import com.openhtmltopdf.layout.InlinePaintable;
import com.openhtmltopdf.layout.Layer;
import com.openhtmltopdf.newtable.TableCellBox;
import com.openhtmltopdf.render.BlockBox;
import com.openhtmltopdf.render.Box;
import com.openhtmltopdf.render.DisplayListItem;
import com.openhtmltopdf.render.OperatorClip;
import com.openhtmltopdf.render.OperatorSetClip;
import com.openhtmltopdf.render.RenderingContext;
import com.openhtmltopdf.render.displaylist.DisplayListCollector;
import com.openhtmltopdf.render.displaylist.TransformCreator;

public class SimplePainter {
    private final int xTranslate;
    private final int yTranslate;
    
    public SimplePainter(int xtrans, int ytrans) {
        this.xTranslate = xtrans;
        this.yTranslate = ytrans;
    }
    
    private void debugOnly(String msg, Object arg) {
        //System.out.println(msg + " : " + arg);
    }
    
    public void paintLayer(RenderingContext c, Layer layer) {
        Box master = layer.getMaster();
        Rectangle parentClip = layer.getMaster().getParentClipBox(c, layer.getParent());
        
        if (parentClip != null) {
            c.getOutputDevice().pushClip(parentClip);
        }

        if (layer.hasLocalTransform()) {
            AffineTransform transform = c.isInPageMargins() ? 
                    TransformCreator.createPageMarginCoordinatesTransform(c, master, c.getPage(), xTranslate, yTranslate) :
                    TransformCreator.createPageCoordinatesTranform(c, master, c.getPage(), c.getShadowPageNumber());
                    
            c.getOutputDevice().pushTransformLayer(transform);
        }
        
        if (!layer.isInline() && ((BlockBox) master).isReplaced()) {
            paintLayerBackgroundAndBorder(c, master);
            paintReplacedElement(c, (BlockBox) master);
        } else {
            SimpleBoxCollector boxCollector = new SimpleBoxCollector();
            boxCollector.collect(c, layer);
            
            if (!layer.isInline() && master instanceof BlockBox) {
                paintLayerBackgroundAndBorder(c, master);
            }

            if (layer.isRootLayer() || layer.isStackingContext() || master.getStyle().isFixed()) {
                paintLayers(c, layer.getSortedLayers(Layer.NEGATIVE));
            }
            
            Map> collapsedTableBorders = boxCollector.tcells().isEmpty() ? null
                    : DisplayListCollector.collectCollapsedTableBorders(c, boxCollector.tcells());
            
            paintBackgroundsAndBorders(c, boxCollector.blocks(), collapsedTableBorders);
            paintFloats(c, layer.getFloats());
            paintListMarkers(c, boxCollector.listItems());
            paintInlineContent(c, boxCollector.inlines());
            paintReplacedElements(c, boxCollector.replaceds());
            
            if (layer.isRootLayer() || layer.isStackingContext() || master.getStyle().isFixed()) {
                paintLayers(c, layer.collectLayers(Layer.AUTO));
                // TODO z-index: 0 layers should be painted atomically
                paintLayers(c, layer.getSortedLayers(Layer.ZERO));
                paintLayers(c, layer.getSortedLayers(Layer.POSITIVE));
            }
        }

        if (layer.hasLocalTransform()) {
            c.getOutputDevice().popTransformLayer();
        }
        
        if (parentClip != null) {
            c.getOutputDevice().popClip();
        }
    }
    
    private void paintLayerBackgroundAndBorder(RenderingContext c, Box master) {
        master.paintBackground(c);
        master.paintBorder(c);
    }
    
    private void clip(RenderingContext c, OperatorClip clip) {
        debugOnly("clipping", clip.getClip());
        c.getOutputDevice().pushClip(clip.getClip());
    }
    
    private void setClip(RenderingContext c, OperatorSetClip setclip) {
        debugOnly("popping clip", null);
        c.getOutputDevice().popClip();
    }

    private void paintBackgroundsAndBorders(RenderingContext c, List blocks, Map> collapsedTableBorders) {
        for (DisplayListItem dli : blocks) {
            if (dli instanceof OperatorClip) {
                OperatorClip clip = (OperatorClip) dli;
                clip(c, clip);
            } else if (dli instanceof OperatorSetClip) {
                OperatorSetClip setClip = (OperatorSetClip) dli;
                setClip(c, setClip);
            } else {
                BlockBox box = (BlockBox) dli;
                
                debugOnly("painting bg", box);
                box.paintBackground(c);
                box.paintBorder(c);

                if (collapsedTableBorders != null && box instanceof TableCellBox) {
                    TableCellBox cell = (TableCellBox) box;

                    if (cell.hasCollapsedPaintingBorder()) {
                        List borders = collapsedTableBorders.get(cell);

                        if (borders != null) {
                            for (CollapsedBorderSide border : borders) {
                                border.getCell().paintCollapsedBorder(c, border.getSide());
                            }
                        }
                    }
                }
            }
        }
        
    }

    private void paintListMarkers(RenderingContext c, List listItems) {
        for (DisplayListItem dli : listItems) {
            if (dli instanceof OperatorClip) {
                OperatorClip clip = (OperatorClip) dli;
                clip(c, clip);
            } else if (dli instanceof OperatorSetClip) {
                OperatorSetClip setClip = (OperatorSetClip) dli;
                setClip(c, setClip);
            } else {
                debugOnly("Painting list item", dli);
                ((BlockBox) dli).paintListMarker(c);
            }
        }
    }

    private void paintInlineContent(RenderingContext c, List inlines) {
        for (DisplayListItem dli : inlines) {
            if (dli instanceof OperatorClip) {
                OperatorClip clip = (OperatorClip) dli;
                clip(c, clip);
            } else if (dli instanceof OperatorSetClip) {
                OperatorSetClip setClip = (OperatorSetClip) dli;
                setClip(c, setClip);
            } else if (dli instanceof BlockBox) {
                // Inline blocks need to be painted as a layer.
                BlockBox bb = (BlockBox) dli;
                paintAsLayer(c, bb);
            } else {
                InlinePaintable paintable = (InlinePaintable) dli;
                debugOnly("Painting Inline", paintable);
                paintable.paintInline(c);
            }
        }
        
    }
    
    private void paintReplacedElement(RenderingContext c, BlockBox replaced) {
        
        Rectangle contentBounds = replaced.getContentAreaEdge(
                replaced.getAbsX(), replaced.getAbsY(), c);
        
        // Minor hack:  It's inconvenient to adjust for margins, border, padding during
        // layout so just do it here.
        Point loc = replaced.getReplacedElement().getLocation();
        if (contentBounds.x != loc.x || contentBounds.y != loc.y) {
            replaced.getReplacedElement().setLocation(contentBounds.x, contentBounds.y);
        }
        
        c.getOutputDevice().paintReplacedElement(c, replaced);
    }

    private void paintReplacedElements(RenderingContext c, List replaceds) {
        for (DisplayListItem dli : replaceds) {
            if (dli instanceof OperatorClip) {
                OperatorClip clip = (OperatorClip) dli;
                clip(c, clip);
            } else if (dli instanceof OperatorSetClip) {
                OperatorSetClip setClip = (OperatorSetClip) dli;
                setClip(c, setClip);
            } else {
                BlockBox box = (BlockBox) dli;
                paintReplacedElement(c, box);
            }
        }
    }

    private void paintFloats(RenderingContext c, List floaters) {
        for (int i = floaters.size() - 1; i >= 0; i--) {
            paintAsLayer(c, floaters.get(i));
        }
    }
    
    private void paintLayers(RenderingContext c, List layers) {
        for (Layer layer : layers) {
            paintLayer(c, layer);
        }
    }
    
    public void paintAsLayer(RenderingContext c, BlockBox startingPoint) {
        if (startingPoint.getStyle().requiresLayer()) {
            return;
        }
        
        SimpleBoxCollector collector = new SimpleBoxCollector();
        collector.collect(c, startingPoint.getContainingLayer(), startingPoint);

        Map>  collapsedTableBorders = collector.tcells().isEmpty() ? null : DisplayListCollector.collectCollapsedTableBorders(c, collector.tcells());

        paintBackgroundsAndBorders(c, collector.blocks(), collapsedTableBorders);
        paintListMarkers(c, collector.listItems());
        paintInlineContent(c, collector.inlines());
        paintReplacedElements(c, collector.replaceds());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy