Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.idrsolutions.pdf.color.shading.Shape67 Maven / Gradle / Ivy
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2017 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
@LICENSE@
*
* ---------------
* Shape67.java
* ---------------
*/
package com.idrsolutions.pdf.color.shading;
import java.awt.Color;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
/**
* Class used to store shading type 6 and shading type 7 shape points and
* perform memory efficient and speed execution
*
* @author suda
*/
@SuppressWarnings("ALL")
public class Shape67 {
private final GeneralPath shape;
private final Color colorsArr[];
private final Point2D pointsArr[];
private int nSteps = 10; // used to find c1,c2,d1,d2 length steps
private final List patches = new ArrayList();
private TinyPatch lastFound; //cache last found to
private final double minX;
private final double minY;
/**
* @param sp size 12 points array
* @param colors size 4 color array
*/
public Shape67(final Point2D[] sp, final Color[] colors) {
this.pointsArr = sp;
this.colorsArr = colors;
shape = new GeneralPath();
shape.moveTo(sp[0].getX(), sp[0].getY());
shape.curveTo(sp[1].getX(), sp[1].getY(), sp[2].getX(), sp[2].getY(), sp[3].getX(), sp[3].getY());
shape.curveTo(sp[4].getX(), sp[4].getY(), sp[5].getX(), sp[5].getY(), sp[6].getX(), sp[6].getY());
shape.curveTo(sp[7].getX(), sp[7].getY(), sp[8].getX(), sp[8].getY(), sp[9].getX(), sp[9].getY());
shape.curveTo(sp[10].getX(), sp[10].getY(), sp[11].getX(), sp[11].getY(), sp[0].getX(), sp[0].getY());
shape.closePath();
Rectangle2D bounds = shape.getBounds2D();
minY = bounds.getMinY();
minX = bounds.getMinX();
}
public GeneralPath getShape() {
return shape;
}
public double getMinX() {
return minX;
}
public double getMinY() {
return minY;
}
public void setSteps(int steps) {
nSteps = steps;
}
private static Point2D[] curvePoints(Point2D p1, Point2D p2, Point2D p3, Point2D p4, int nSteps) {
Point2D[] arr = new Point2D[nSteps + 1];
arr[0] = p1;
for (int i = 1; i <= nSteps; i++) {
float t = (1.0f / nSteps) * i;
Point2D p = ShadingUtils.findDistancedPoint(t, p1, p2, p3, p4);
arr[i] = p;
}
return arr;
}
private static float[][] linePoints(Point2D p1, Point2D p2) {
float[][] arr = new float[3][2];
arr[0][0] = (float) p1.getX();
arr[0][1] = (float) p1.getY();
arr[1][0] = (float) (p1.getX() + p2.getX()) / 2;
arr[1][1] = (float) (p1.getY() + p2.getY()) / 2;
arr[2][0] = (float) p2.getX();
arr[2][1] = (float) p2.getY();
return arr;
}
private Point2D[] getC1Points() {
return curvePoints(pointsArr[0], pointsArr[11], pointsArr[10], pointsArr[9], nSteps);
}
private Point2D[] getC2Points() {
return curvePoints(pointsArr[3], pointsArr[4], pointsArr[5], pointsArr[6], nSteps);
}
private Point2D[] getD1Points() {
return curvePoints(pointsArr[0], pointsArr[1], pointsArr[2], pointsArr[3], nSteps);
}
private Point2D[] getD2Points() {
return curvePoints(pointsArr[9], pointsArr[8], pointsArr[7], pointsArr[6], nSteps);
}
public void generateBilinearMapping() {
final Point2D[] C1 = getC1Points();
final Point2D[] C2 = getC2Points();
final Point2D[] D1 = getD1Points();
final Point2D[] D2 = getD2Points();
final int szu = C1.length;
final int szv = D1.length;
Point2D[][] xy = new Point2D[szv][szu];
Color[][] cc = new Color[szv][szu];
float stepV = 1f / (szv - 1);
float stepU = 1f / (szu - 1);
float v = -stepV;
int[][] pointColors = new int[4][4];
for (int i = 0; i < 4; i++) {
pointColors[i] = new int[]{colorsArr[i].getRed(), colorsArr[i].getGreen(), colorsArr[i].getBlue(), colorsArr[i].getAlpha()};
}
float vMinus, uMinus, scx, scy, sdx, sdy, sbx, sby, sx, sy;
for (int i = 0; i < szv; i++) {
v += stepV;
vMinus = 1 - v;
float u = -stepU;
for (int j = 0; j < szu; j++) {
u += stepU;
uMinus = 1 - u;
scx = (float) (vMinus * C1[j].getX() + v * C2[j].getX());
scy = (float) (vMinus * C1[j].getY() + v * C2[j].getY());
sdx = (float) (uMinus * D1[i].getX() + u * D2[i].getX());
sdy = (float) (uMinus * D1[i].getY() + u * D2[i].getY());
sbx = (float) (vMinus * (uMinus * C1[0].getX() + u * C1[C1.length - 1].getX())
+ v * (uMinus * C2[0].getX() + u * C2[C2.length - 1].getX()));
sby = (float) (vMinus * ((1 - u) * C1[0].getY() + u * C1[C1.length - 1].getY())
+ v * (uMinus * C2[0].getY() + u * C2[C2.length - 1].getY()));
sx = scx + sdx - sbx;
sy = scy + sdy - sby;
xy[i][j] = new Point2D.Float(sx, sy);
int[] temp = new int[4];
for (int ci = 0; ci < 4; ci++) {
temp[ci] = (int) (vMinus * (uMinus * pointColors[0][ci] + u * pointColors[3][ci])
+ v * (uMinus * pointColors[1][ci] + u * pointColors[2][ci]));
}
cc[i][j] = new Color(temp[0], temp[1], temp[2], temp[3]);
}
}
int d = xy.length - 1; //dimensional length we consider as equal
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
Point2D[] patchPoints = {xy[i][j], xy[i][j + 1], xy[i + 1][j + 1], xy[i + 1][j]};
Color[] patchColors = {cc[i][j], cc[i][j + 1], cc[i + 1][j + 1], cc[i + 1][j]};
patches.add(new TinyPatch(patchPoints, patchColors));
}
}
}
public Color findPointColor(Point2D p, boolean isRecursive) {
if (patches.isEmpty()) {
generateBilinearMapping();
}
Color pColor = null;
if (lastFound != null && isPointInPoly(lastFound.points, p)) {
Color[] colors = lastFound.colors;
Point2D[] points = lastFound.points;
return recurseTrapezoidal(p, points, colors, isRecursive, 0);
}
for (TinyPatch patch : patches) {
if (patch.minX <= p.getX() && patch.minY <= p.getY() && isPointInPoly(patch.points, p)) {
lastFound = patch;
Color[] colors = patch.colors;
Point2D[] points = patch.points;
return recurseTrapezoidal(p, points, colors, isRecursive, 0);
}
lastFound = null;
}
return pColor;
}
private static Color recurseTrapezoidal(Point2D p, Point2D[] points, Color[] colors, boolean isRecursive, int depth) {
if (depth > 2 || !isRecursive) {
return colors[0];
}
float[][] C1 = linePoints(points[0], points[3]);
float[][] C2 = linePoints(points[1], points[2]);
float[][] D1 = linePoints(points[0], points[1]);
float[][] D2 = linePoints(points[3], points[2]);
final int szu = C1.length;
final int szv = D1.length;
Point2D[][] xy = new Point2D[szv][szu];
Color[][] cc = new Color[szv][szu];
float stepV = 1f / (szv - 1);
float stepU = 1f / (szu - 1);
float v = -stepV;
int[][] pColors = new int[4][4];
for (int i = 0; i < 4; i++) {
pColors[i] = new int[]{colors[i].getRed(), colors[i].getGreen(), colors[i].getBlue(), colors[i].getAlpha()};
}
float vMinus, uMinus, scx, scy, sdx, sdy, sbx, sby, u, sx, sy;
for (int i = 0; i < szv; i++) {
v += stepV;
vMinus = 1 - v;
u = -stepU;
for (int j = 0; j < szu; j++) {
u += stepU;
uMinus = 1 - u;
scx = vMinus * C1[j][0] + v * C2[j][0];
scy = vMinus * C1[j][1] + v * C2[j][1];
sdx = uMinus * D1[i][0] + u * D2[i][0];
sdy = uMinus * D1[i][1] + u * D2[i][1];
sbx = vMinus * (uMinus * C1[0][0] + u * C1[2][0]) + v * (uMinus * C2[0][0] + u * C2[2][0]);
sby = vMinus * (uMinus * C1[0][1] + u * C1[2][1]) + v * (uMinus * C2[0][1] + u * C2[2][1]);
sx = scx + sdx - sbx;
sy = scy + sdy - sby;
xy[i][j] = new Point2D.Float(sx, sy);
int[] temp = new int[4];
for (int ci = 0; ci < 4; ci++) {
temp[ci] = (int) (vMinus * (uMinus * pColors[0][ci] + u * pColors[3][ci])
+ v * (uMinus * pColors[1][ci] + u * pColors[2][ci]));
}
cc[i][j] = new Color(temp[0], temp[1], temp[2], temp[3]);
}
}
int d = xy.length - 1; //dimensional length we consider as equal
for (int i = 0; i < d; i++) {
for (int j = 0; j < d; j++) {
Point2D[] patchPoints = {xy[i][j], xy[i][j + 1], xy[i + 1][j + 1], xy[i + 1][j]};
Color[] patchColors = {cc[i][j], cc[i][j + 1], cc[i + 1][j + 1], cc[i + 1][j]};
if (isPointInPoly(patchPoints, p)) {
depth++;
return recurseTrapezoidal(p, patchPoints, patchColors, isRecursive, depth);
}
}
}
return colors[0];
}
private static class TinyPatch {
final Color[] colors;
final Point2D[] points;
double minX, minY;
public TinyPatch(Point2D[] points, Color[] colors) {
this.colors = colors;
this.points = points;
for (Point2D p : points) {
minX = Math.min(minX, p.getX());
minY = Math.min(minY, p.getY());
}
}
}
private static boolean isPointInPoly(Point2D[] points, Point2D p) {
boolean c = false;
int nvert = points.length;
double px = p.getX();
double py = p.getY();
Point2D pi, pj;
for (int i = 0, j = nvert - 1; i < nvert; j = i++) {
pi = points[i];
pj = points[j];
double piY = pi.getY();
double pjY = pj.getY();
if ((piY > py) != (pjY > py)) {
double piX = pi.getX();
if ((px < (pj.getX() - piX) * (py - piY) / (pjY - piY) + piX)) {
c = !c;
}
}
}
return c;
}
}