# Line.java

    /*
     * Copyright 2014 The Apache Software Foundation.
     *
     * Licensed 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.shading;

    import java.awt.Point;
    import java.util.HashSet;
    import java.util.Set;

    /**
     * This class describes a rasterized line. This was done as part of GSoC2014,
     * Tilman Hausherr is the mentor.
     *
     * @author Shaola Ren
     */
    class Line
    {
        private final Point point0;
        private final Point point1;
        private final float[] color0;
        private final float[] color1;

        protected final Set<Point> linePoints; // all the points in this rasterized line

        /**
         * Constructor of class Line.
         *
         * @param p0 one end of a line
         * @param p1 the other end of the line
         * @param c0 color of point p0
         * @param c1 color of point p1
         */
        Line(Point p0, Point p1, float[] c0, float[] c1)
        {
            point0 = p0;
            point1 = p1;
            color0 = c0.clone();
            color1 = c1.clone();
            linePoints = calcLine(point0.x, point0.y, point1.x, point1.y);
        }

        /**
         * Calculate the points of a line with Bresenham's line algorithm
         * <a
         * href="http://en.wikipedia.org/wiki/Bresenham's_line_algorithm">Bresenham's
         * line algorithm</a>
         *
         * @param x0 coordinate
         * @param y0 coordinate
         * @param x1 coordinate
         * @param y1 coordinate
         * @return all the points on the rasterized line from (x0, y0) to (x1, y1)
         */
        private Set<Point> calcLine(int x0, int y0, int x1, int y1)
        {
            Set<Point> points = new HashSet<>(3);
            int dx = Math.abs(x1 - x0);
            int dy = Math.abs(y1 - y0);
            int sx = x0 < x1 ? 1 : -1;
            int sy = y0 < y1 ? 1 : -1;
            int err = dx - dy;
            while (true)
            {
                points.add(new IntPoint(x0, y0));
                if (x0 == x1 && y0 == y1)
                {
                    break;
                }
                int e2 = 2 * err;
                if (e2 > -dy)
                {
                    err -= dy;
                    x0 += sx;
                }
                if (e2 < dx)
                {
                    err += dx;
                    y0 += sy;
                }
            }
            return points;
        }

        /**
         * Calculate the color of a point on a rasterized line by linear
         * interpolation.
         *
         * @param p target point, p should always be contained in linePoints
         * @return color
         */
        protected float[] calcColor(Point p)
        {
            if (point0.x == point1.x && point0.y == point1.y)
            {
                return color0;
            }
            int numberOfColorComponents = color0.length;
            float[] pc = new float[numberOfColorComponents];
            if (point0.x == point1.x)
            {
                float l = point1.y - point0.y;
                for (int i = 0; i < numberOfColorComponents; i++)
                {
                    pc[i] = (color0[i] * (point1.y - p.y) / l
                            + color1[i] * (p.y - point0.y) / l);
                }
            }
            else
            {
                float l = point1.x - point0.x;
                for (int i = 0; i < numberOfColorComponents; i++)
                {
                    pc[i] = (color0[i] * (point1.x - p.x) / l
                            + color1[i] * (p.x - point0.x) / l);
                }
            }
            return pc;
        }
    }