Package org.apache.pdfbox.pdmodel.graphics.pattern

Source Code of org.apache.pdfbox.pdmodel.graphics.pattern.TilingPaint

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.pdfbox.pdmodel.graphics.pattern;

import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.PaintContext;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;

import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.rendering.PageDrawer;

/**
* AWT Paint for a tiling pattern, which consists of a small repeating graphical figure.
*
* @author Andreas Lehmk�hler
* @author John Hewson
*/
public class TilingPaint implements Paint
{
    private final PDTilingPattern pattern;
    private final TexturePaint paint;

    /**
     * Creates a new colored tiling Paint.
     *
     * @param drawer renderer to render the page
     * @param pattern tiling pattern dictionary
     *
     * @throws java.io.IOException if something goes wrong while drawing the
     * pattern
     */
    public TilingPaint(PageDrawer drawer, PDTilingPattern pattern, AffineTransform xform)
            throws IOException
    {
        this.paint = new TexturePaint(getImage(drawer, pattern, null, null, xform),
                                      getAnchorRect(pattern));
        this.pattern = pattern;
    }

    /**
     * Creates a new uncolored tiling Paint.
     *
     * @param drawer renderer to render the page
     * @param pattern tiling pattern dictionary
     * @param colorSpace color space for this tiling
     * @param color color for this tiling
     *
     * @throws java.io.IOException if something goes wrong while drawing the pattern
     */
    public TilingPaint(PageDrawer drawer, PDTilingPattern pattern, PDColorSpace colorSpace,
                       PDColor color, AffineTransform xform) throws IOException
    {
        this.paint = new TexturePaint(getImage(drawer, pattern, colorSpace, color, xform),
                                      getAnchorRect(pattern));
        this.pattern = pattern;
    }

    // note: this is not called in TexturePaint subclasses, which is why we wrap TexturePaint
    @Override
    public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds,
                                      AffineTransform xform, RenderingHints hints)
    {
        // todo: use userBounds or deviceBounds to avoid scaling issue with Tracemonkey?
        AffineTransform xformPattern = (AffineTransform)xform.clone();
        xformPattern.concatenate(pattern.getMatrix().createAffineTransform());
        return paint.createContext(cm, deviceBounds, userBounds, xformPattern, hints);
    }

    // gets image in parent stream coordinates
    private static BufferedImage getImage(PageDrawer drawer, PDTilingPattern pattern,
                                          PDColorSpace colorSpace, PDColor color,
                                          AffineTransform xform) throws IOException
    {
        ColorSpace outputCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        ColorModel cm = new ComponentColorModel(outputCS, true, false,
                Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);

        Rectangle2D anchor = getAnchorRect(pattern);
        float width = (float)Math.abs(anchor.getWidth());
        float height = (float)Math.abs(anchor.getHeight());

        // device transform (i.e. DPI)
        width *= (float)xform.getScaleX();
        height *= (float)xform.getScaleY();

        int rasterWidth = Math.max(1, ceiling(width));
        int rasterHeight = Math.max(1, ceiling(height));

        // create raster
        WritableRaster raster = cm.createCompatibleWritableRaster(rasterWidth, rasterHeight);
        BufferedImage image = new BufferedImage(cm, raster, false, null);

        Graphics2D graphics = image.createGraphics();
        graphics.transform(xform); // device transform (i.e. DPI)
        drawer.drawTilingPattern(graphics, pattern, colorSpace, color);
        graphics.dispose();

        return image;
    }

    /**
     * Returns the closest integer which is larger than the given number.
     * Uses BigDecimal to avoid floating point error which would cause gaps in the tiling.
     */
    private static int ceiling(double num)
    {
        BigDecimal decimal = new BigDecimal(num);
        decimal.setScale(5, RoundingMode.CEILING); // 5 decimal places of accuracy
        return decimal.intValue();
    }

    @Override
    public int getTransparency()
    {
        return Transparency.TRANSLUCENT;
    }

    // includes XStep/YStep
    public static Rectangle2D getAnchorRect(PDTilingPattern pattern)
    {
        float xStep = pattern.getXStep();
        if (xStep == 0)
        {
            xStep = pattern.getBBox().getWidth();
        }

        float yStep = pattern.getYStep();
        if (yStep == 0)
        {
            yStep = pattern.getBBox().getHeight();
        }

        PDRectangle anchor = pattern.getBBox();
        return new Rectangle2D.Float(anchor.getLowerLeftX(), anchor.getLowerLeftY(), xStep, yStep);
    }
}
TOP

Related Classes of org.apache.pdfbox.pdmodel.graphics.pattern.TilingPaint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.