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

org.jpedal.text.TextLines Maven / Gradle / Ivy

There is a newer version: 20151002
Show newest version
/*
 * ===========================================
 * 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
 *
     This library 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 library 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 library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 *
 * ---------------
 * TextLines.java
 * ---------------
 */
package org.jpedal.text;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.jpedal.objects.PdfData;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.repositories.generic.Vector_Rectangle_Int;

public class TextLines {

    /**stores area of arrays in which text should be highlighted*/
    private Map> lineAreas = new HashMap>();
    private Map> lineWritingMode = new HashMap>();

    /**Highlight Areas stored here*/
    public Map areas = new HashMap();
    
    /**Track if highlgiht localAreas has changed since last call to getHighlightedAreas(int)*/
    boolean hasHighlightAreasUpdated;
 
    /**
	 * Highlights a section of lines that form a paragraph and
 returns the area that encloses all highlight localAreas.
     * @param x Coord x value to begin looking for a paragraph
     * @param y Coord y value to begin looking for a paragraph
     * @param page Page number of page to look for a paragraph on
	 * @return int[] that contains x,y,w,h of all localAreas highlighted
	 */
    public int[] setFoundParagraphAsArray(final int x, final int y, final int page){

    final int[][] lines = getLineAreasAs2DArray(page);

    if(lines!=null){

        final int[] point = {x,y,1,1};
        final int[] current = {0,0,0,0};
        boolean lineFound = false;
        int selectedLine = 0;

        for(int i=0; i!=lines.length; i++){
            if(intersects(lines[i],point)){
                selectedLine = i;
                lineFound = true;
                break;
            }
        }

        if(lineFound){
            int left = lines[selectedLine][0];
            int cx = lines[selectedLine][0]+(lines[selectedLine][2]/2);
            int right = lines[selectedLine][0]+lines[selectedLine][2];
            int cy = lines[selectedLine][1]+(lines[selectedLine][3]/2);
            int h = lines[selectedLine][3];

            current[0]=lines[selectedLine][0];
            current[1]=lines[selectedLine][1];
            current[2]=lines[selectedLine][2];
            current[3]=lines[selectedLine][3];

            boolean foundTop = true;
            boolean foundBottom = true;
            final Vector_Rectangle_Int selected = new Vector_Rectangle_Int(0);
            selected.addElement(lines[selectedLine]);

            while(foundTop){
                foundTop = false;
                for(int i=0; i!=lines.length; i++){
                    if(contains(left, cy+h, lines[i]) || contains(cx, cy+h, lines[i]) || contains(right, cy+h, lines[i])){
                        selected.addElement(lines[i]);
                        foundTop = true;
                        cy = lines[i][1] + (lines[i][3]/2);
                        h = lines[i][3];

                        if(current[0]>lines[i][0]){
                            current[2] = (current[0]+current[2])-lines[i][0];
                            current[0] = lines[i][0];
                        }
                        if((current[0]+current[2])<(lines[i][0]+lines[i][2])) {
                            current[2] = (lines[i][0] + lines[i][2]) - current[0];
                        }
                        if(current[1]>lines[i][1]){
                            current[3] = (current[1]+current[3])-lines[i][1];
                            current[1] = lines[i][1];
                        }
                        if((current[1]+current[3])<(lines[i][1]+lines[i][3])){
                            current[3] = (lines[i][1]+lines[i][3])-current[1];
                        }

                        break;
                    }
                }
            }

            //Return to selected item else we have duplicate highlights
            left = lines[selectedLine][0];
            cx = lines[selectedLine][0]+(lines[selectedLine][2]/2);
            right = lines[selectedLine][0]+lines[selectedLine][2];
            cy = lines[selectedLine][1] + (lines[selectedLine][3]/2);
            h = lines[selectedLine][3];

            while(foundBottom){
                foundBottom = false;
                for(int i=0; i!=lines.length; i++){
                    if(contains(left, cy-h, lines[i]) || contains(cx,cy-h, lines[i]) || contains(right,cy-h, lines[i])){
                        selected.addElement(lines[i]);
                        foundBottom = true;
                        cy = lines[i][1] + (lines[i][3]/2);
                        h = lines[i][3];

                        if(current[0]>lines[i][0]){
                            current[2] = (current[0]+current[2])-lines[i][0];
                            current[0] = lines[i][0];
                        }
                        if((current[0]+current[2])<(lines[i][0]+lines[i][2])) {
                            current[2] = (lines[i][0] + lines[i][2]) - current[0];
                        }
                        if(current[1]>lines[i][1]){
                            current[3] = (current[1]+current[3])-lines[i][1];
                            current[1] = lines[i][1];
                        }
                        if((current[1]+current[3])<(lines[i][1]+lines[i][3])){
                            current[3] = (lines[i][1]+lines[i][3])-current[1];
                        }

                        break;
                    }
                }
            }
            selected.trim();
            addHighlights(selected.get(), true, page);
            return current;
        }
        return null;
    }
    return null;
}

    public void addToLineAreas(final int[] area, final int writingMode, final int page) {
        boolean addNew = true;

        if(lineAreas==null){ //If null, create array

            lineAreas = new HashMap>();
            lineWritingMode = new HashMap>();
        }
        
        ArrayList lastAreas = lineAreas.get(page);
        ArrayList lastWritingMode = (lineWritingMode.get(page));

        //Check for objects close to or intersecting each other
        if (area != null) { //Ensure actual area is selected
            if (lastAreas != null) {
                int cx;
                int cy;
                int cw;
                int ch;
                //int cm = cy+(ch/2);

                int lx;
                int ly;
                int lw;
                int lh;

                for (int i = 0; i != lastAreas.size(); i++) {
                    final int[] lastArea = lastAreas.get(i);
                    final int lwm = lastWritingMode.get(i);
                    cx = area[0];
                    cy = area[1];
                    cw = area[2];
                    ch = area[3];
                    //int cm = cy+(ch/2);

                    lx = lastArea[0];
                    ly = lastArea[1];
                    lw = lastArea[2];
                    lh = lastArea[3];
                    //int lm = ly+(lh/2);

                    final int currentBaseLine;
                    final int lastBaseLine;
                    final float heightMod = 5f;
                    final float widthMod = 1.1f;

                    switch (writingMode) {
                        case PdfData.HORIZONTAL_LEFT_TO_RIGHT:

                                if(lwm== writingMode && ((ly>(cy-(ch/heightMod))) && (ly<(cy+(ch/heightMod)))) && //Ensure this is actually the same line and are about the same size
                                        (((lhch-(ch/heightMod))) && //Check text is the same height
                                                (((lx>(cx + cw-(ch*widthMod))) && (lx<(cx + cw+(ch*widthMod)))) || //Check for object at end of this object
                                                        ((lx + lw>(cx-(ch*widthMod))) && (lx + lw<(cx+(ch*widthMod)))) ||//Check for object at start of this object
                                    intersects(lastArea, area)))//Check to see if it intersects at all
                                    ) {
                                addNew = false;

                                //No need to reset the writing mode as already set
                                lastAreas.set(i, mergePartLines(lastArea, area));
                            }
                            break;
                        case PdfData.HORIZONTAL_RIGHT_TO_LEFT:

                            lx = lastArea[0];
                            ly = lastArea[1];
                            lw = lastArea[2];
                            lh = lastArea[3];
                            cx = area[0];
                            cy = area[1];
                            cw = area[2];
                            ch = area[3];

                            if(lwm== writingMode && ((ly>(cy-5)) && (ly<(cy+5)) && lh<=(ch+(ch/5)) && lh>=(ch-(ch/5))) && //Ensure this is actually the same line and are about the same size
                                    (((lx>(cx + cw-(ch*0.6))) && (lx<(cx + cw+(ch*0.6)))) || //Check for object at end of this object
                                            ((lx + lw>(cx-(ch*0.6))) && (lx + lw<(cx+(ch*0.6)))) ||//Check for object at start of this object
                                intersects(lastArea, area))//Check to see if it intersects at all
                                ) {
                                addNew = false;

                                //No need to reset the writing mode as already set
                                lastAreas.set(i, mergePartLines(lastArea, area));
                            }
                            break;
                        case PdfData.VERTICAL_TOP_TO_BOTTOM:

                            lx = lastArea[1];
                            ly = lastArea[0];
                            lw = lastArea[3];
                            lh = lastArea[2];
                            cx = area[1];
                            cy = area[0];
                            cw = area[3];
                            ch = area[2];

                        if(lwm== writingMode && ((ly>(cy-5)) && (ly<(cy+5)) && lh<=(ch+(ch/5)) && lh>=(ch-(ch/5))) && //Ensure this is actually the same line and are about the same size
                                    (((lx>(cx + cw-(ch*0.6))) && (lx<(cx + cw+(ch*0.6)))) || //Check for object at end of this object
                                            ((lx + lw>(cx-(ch*0.6))) && (lx + lw<(cx+(ch*0.6)))) ||//Check for object at start of this object
                                intersects(lastArea, area))//Check to see if it intersects at all
                                ) {
                                addNew = false;

                                //No need to reset the writing mode as already set
                                lastAreas.set(i, mergePartLines(lastArea, area));
                            }

                            break;

                        case PdfData.VERTICAL_BOTTOM_TO_TOP:

                            //Calculate the coord value at the bottom of the text
                            currentBaseLine = cx + cw;
                            lastBaseLine = lx + lw;

                            if(lwm== writingMode //Check the current writing mode
                                            && (currentBaseLine >= (lastBaseLine-(lw/3))) && (currentBaseLine <= (lastBaseLine+(lw/3))) //Check is same line
                                && //Only check left or right if the same line is shared
                                (( //Check for text on either side
                                ((ly + (lh + (lw * 0.6)) > cy) && (ly + (lh - (lw * 0.6)) < cy))// Check for text to left of current area
                                || ((ly + (lw * 0.6) > (cy + ch)) && (ly - (lw * 0.6) < (cy + ch)))// Check for text to right of current area
                                )
                                || intersects(area, lastArea))) {
                                addNew = false;

                                //No need to reset the writing mode as already set
                                lastAreas.set(i, mergePartLines(lastArea, area));
                            }

                            break;

                    }

                }
            } else {

                lastAreas = new ArrayList();
                lineAreas.put(page, lastAreas);

                lastWritingMode = new ArrayList();
                lineWritingMode.put(page, lastWritingMode);

                addNew = true;
            }

            //If no object near enough to merge, start a new area
            if (addNew) {

                lastAreas.add(area);
                lastWritingMode.add(writingMode);

            }

        }
    }

    /**
     * remove zone on page for text localAreas if present
     * @param rectArea Text area to remove
     * @param page Page to check for these localAreas
     */
    public void removeFoundTextArea(final int[] rectArea, final int page){

        //clearHighlights();
        if(rectArea==null|| areas==null) {
            return;
        }

        final Integer p = page;
        final int[][] localAreas = this.areas.get(p);
        if(localAreas!=null){
            final int size=localAreas.length;
            for(int i=0;i();
                }

                final int[][] lines = getLineAreasAs2DArray(page);
                final int[] writingMode = this.getLineWritingMode(page);

                int start = -1;
                int finish = -1;
                boolean backward = false;
                //Find the first selected line and the last selected line.
                if (lines != null) {
                    for (int i = 0; i != lines.length; i++) {
                        if (contains(startPoint[0], startPoint[1], lines[i])) {
                            start = i;
                        }

                        if (contains(endPoint[0], endPoint[1], lines[i])) {
                            finish = i;
                        }

                        if (start != -1 && finish != -1) {
                            break;
                        }
                    }

                    if (start > finish) {
                        final int temp = start;
                        start = finish;
                        finish = temp;
                        backward = true;
                    }

                    if (start == finish) {
                        if (startPoint[0] > endPoint[0]) {
                            final int[] temp = startPoint;
                            startPoint = endPoint;
                            endPoint = temp;
                        }
                    }

                    if (start != -1 && finish != -1) {
                        //Fill in all the lines between
                        final int[][] localAreas = new int[finish - start + 1][4];

                        System.arraycopy(lines, start + 0, localAreas, 0, finish - start + 1);

                        if (localAreas.length > 0) {
                            final int top = 0;
                            final int bottom = localAreas.length - 1;

                            if (localAreas[top] != null && localAreas[bottom] != null) {

                                switch (writingMode[start]) {
                                    case PdfData.HORIZONTAL_LEFT_TO_RIGHT:
                                        // if going backwards
                                        if (backward) {
                                            if ((endPoint[0] - 15) <= localAreas[top][0]) {
                                                //Do nothing to localAreas as we want to pick up the start of a line
                                            } else {
                                                localAreas[top][2] -= (endPoint[0] - localAreas[top][0]);
                                                localAreas[top][0] = endPoint[0];
                                            }

                                        } else {
                                            if ((startPoint[0] - 15) <= localAreas[top][0]) {
                                                //Do nothing to localAreas as we want to pick up the start of a line
                                            } else {
                                                localAreas[top][2] -= (startPoint[0] - localAreas[top][0]);
                                                localAreas[top][0] = startPoint[0];
                                            }

                                        }
                                        break;
                                    case PdfData.HORIZONTAL_RIGHT_TO_LEFT:
                                        LogWriter.writeLog("THIS TEXT DIRECTION HAS NOT BEEN IMPLEMENTED YET (Right to Left)");
                                        break;
                                    case PdfData.VERTICAL_TOP_TO_BOTTOM:
                                        if (backward) {
                                            if ((endPoint[1] - 15) <= localAreas[top][1]) {
                                                //Do nothing to localAreas as we want to pick up the start of a line
                                            } else {
                                                localAreas[top][3] -= (endPoint[1] - localAreas[top][1]);
                                                localAreas[top][1] = endPoint[1];
                                            }

                                        } else {
                                            if ((startPoint[1] - 15) <= localAreas[top][1]) {
                                                //Do nothing to localAreas as we want to pick up the start of a line
                                            } else {
                                                localAreas[top][3] -= (startPoint[1] - localAreas[top][1]);
                                                localAreas[top][1] = startPoint[1];
                                            }

                                        }
                                        break;
                                    case PdfData.VERTICAL_BOTTOM_TO_TOP:
                                        if (backward) {
                                            if ((endPoint[1] - 15) <= localAreas[top][1]) {
                                                //Do nothing to localAreas as we want to pick up the start of a line
                                            } else {
                                                localAreas[top][3] -= (endPoint[1] - localAreas[top][1]);
                                                localAreas[top][1] = endPoint[1];
                                            }

                                        } else {
                                            if ((startPoint[1] - 15) <= localAreas[top][1]) {
                                                //Do nothing to localAreas as we want to pick up the start of a line
                                            } else {
                                                localAreas[top][3] -= (startPoint[1] - localAreas[top][1]);
                                                localAreas[top][1] = startPoint[1];
                                            }

                                        }
                                        break;
                                }

                                switch (writingMode[finish]) {
                                    case PdfData.HORIZONTAL_LEFT_TO_RIGHT:
                                        // if going backwards
                                        if (backward) {
                                            if ((startPoint[0] + 15) >= localAreas[bottom][0] + localAreas[bottom][2]) {
                                                //Do nothing to localAreas as we want to pick up the end of a line
                                            } else {
                                                localAreas[bottom][2] = startPoint[0] - localAreas[bottom][0];
                                            }

                                        } else {
                                            if ((endPoint[0] + 15) >= localAreas[bottom][0] + localAreas[bottom][2]) {
                                                //Do nothing to localAreas as we want to pick up the end of a line
                                            } else {
                                                localAreas[bottom][2] = endPoint[0] - localAreas[bottom][0];
                                            }
                                        }
                                        break;
                                    case PdfData.HORIZONTAL_RIGHT_TO_LEFT:
                                        LogWriter.writeLog("THIS TEXT DIRECTION HAS NOT BEEN IMPLEMENTED YET (Right to Left)");
                                        break;
                                    case PdfData.VERTICAL_TOP_TO_BOTTOM:
                                        // if going backwards
                                        if (backward) {
                                            if ((startPoint[1] + 15) >= localAreas[bottom][1] + localAreas[bottom][3]) {
                                                //Do nothing to localAreas as we want to pick up the end of a line
                                            } else {
                                                localAreas[bottom][3] = startPoint[1] - localAreas[bottom][1];
                                            }

                                        } else {
                                            if ((endPoint[1] + 15) >= localAreas[bottom][1] + localAreas[bottom][3]) {
                                                //Do nothing to localAreas as we want to pick up the end of a line
                                            } else {
                                                localAreas[bottom][3] = endPoint[1] - localAreas[bottom][1];
                                            }
                                        }
                                        break;
                                    case PdfData.VERTICAL_BOTTOM_TO_TOP:
                                        // if going backwards
                                        if (backward) {
                                            if ((startPoint[1] + 15) >= localAreas[bottom][1] + localAreas[bottom][3]) {
                                                //Do nothing to localAreas as we want to pick up the end of a line
                                            } else {
                                                localAreas[bottom][3] = startPoint[1] - localAreas[bottom][1];
                                            }

                                        } else {
                                            if ((endPoint[1] + 15) >= localAreas[bottom][1] + localAreas[bottom][3]) {
                                                //Do nothing to localAreas as we want to pick up the end of a line
                                            } else {
                                                localAreas[bottom][3] = endPoint[1] - localAreas[bottom][1];
                                            }
                                        }
                                        break;
                                }
                            }
                        }
                        return localAreas;
                    }
                }
            }
        } else {
            //if inset add in difference transparently
            if (highlights != null) {
                if (highlights[2] < 0) {
                    highlights[2] = -highlights[2];
                    highlights[0] -= highlights[2];
                }

                if (highlights[3] < 0) {
                    highlights[3] = -highlights[3];
                    highlights[1] -= highlights[3];
                }

                if (areas != null) {
                    final Integer p = page;
                    int[][] localAreas = this.areas.get(p);
                    if (localAreas != null) {
                        boolean matchFound = false;

                        //see if already added
                        final int size = localAreas.length;
                        for (int i = 0; i < size; i++) {
                            if (localAreas[i] != null) {
                                //If area has been added before please ignore
                                if (localAreas[i] != null && (localAreas[i][0] == highlights[0] && localAreas[i][1] == highlights[1] && localAreas[i][2] == highlights[2]
                                        && localAreas[i][3] == highlights[3])) {
                                    matchFound = true;
                                    i = size;
                                }
                            }
                        }

                        if (!matchFound) {
                            final int newSize = localAreas.length + 1;
                            final int[][] newAreas = new int[newSize][4];
                            for (int i = 0; i < localAreas.length; i++) {
                                if (localAreas[i] != null) {
                                    newAreas[i] = new int[]{localAreas[i][0], localAreas[i][1], localAreas[i][2], localAreas[i][3]};
                                }
                            }
                            localAreas = newAreas;

                            localAreas[localAreas.length - 1] = highlights;
                        }
                        return localAreas;
                    } else {
                        return new int[][]{highlights};
                    }
                } else {
                    areas = new HashMap();
                    final int[][] localAreas = new int[1][4];
                    localAreas[0] = highlights;
                    return localAreas;
                }
            }
        }
        return null;
    }
    
    public boolean hasHighlightAreasUpdated() {
		return hasHighlightAreasUpdated;
	}

    /**
     * Get all the highlights currently stored. The returned Map 
     * using the page numbers as the keys for the values.
     * 
     * @return A Map containing all highlights currently stored.
     */
    public Map getAllHighlights(){
    	hasHighlightAreasUpdated = false;
        if(areas==null){
            return null;
        }else{
            return Collections.unmodifiableMap(areas);
        }
    }
    
    /**
     * Creates a two-dimensional int array containing x,y,width and height
 values for each rectangle that is stored in the localAreas map,
 which allows us to create a swing/fx rectangle on these values.
     * @param page of type int.
     * @return an int[][] Containing x,y,w,h of Highlights on Page.
     */
    public int[][] getHighlightedAreasAs2DArray(final int page) {

        if(areas==null) {
            return null;
        } else{
            final Integer p = page;
            final int[][] localAreas = this.areas.get(p);
            if(localAreas!=null){
                final int count=localAreas.length;

                final int[][] returnValue=new int[count][4];

                for(int ii=0;ii la) {
        if(la == null || la.keySet().isEmpty()){
            lineAreas = null;
        }else{
            final Set keys = la.keySet();
            
            for(final int i : keys){
                final int[][] values = la.get(i);
                final ArrayList list = new ArrayList(Arrays.asList(values));

                lineAreas.put(i, list);
            }
        }
    }

    @SuppressWarnings("UnusedDeclaration")
    public void setLineWritingMode(final Map lineOrientation) {
        if(lineOrientation == null || lineOrientation.keySet().isEmpty()){
            lineWritingMode = null;
        }else{
            final Set keys = lineOrientation.keySet();
            
            for(final int i : keys){
                final int[] values = lineOrientation.get(i);
                final ArrayList list = new ArrayList();
                
                for(final int ii : values){
                    list.add(ii);
                }
                lineWritingMode.put(i, list);
            }
        }
    }


    /**
     * Creates a two-dimensional int array containing x,y,width and height
 values for each rectangle that is stored in the localLineAreas map,
 which allows us to create a swing/fx rectangle on these values.
     * @param page of type int.
     * @return an int[][] Containing x,y,w,h of line localAreas on Page.
     */
    public int[][] getLineAreasAs2DArray(final int page){
        
        if(lineAreas==null || lineAreas.get(page) == null) {
            return null;
        } else{
            final ArrayList localLineAreas = this.lineAreas.get(page);

            if(localLineAreas==null) {
                return null;
            }

            final int count=localLineAreas.size();

            final int[][] returnValue=new int[count][4];

            for(int ii=0;ii localLineWritingMode = (this.lineWritingMode.get(page));

            if(localLineWritingMode==null) {
                return null;
            }

            final int count=localLineWritingMode.size();
            
            final int[] returnValue=new int[count];
            for(int i=0; i!=count; i++){
                returnValue[i] = localLineWritingMode.get(i);
            }
            
            return returnValue;
        }
    }

    private static int[] mergePartLines(final int[] lastArea, final int[] area){
        /*
         * Check coords from both areas and merge them to make
         * a single larger area containing contents of both
         */
        final int x1 =area[0];
        final int x2 =area[0] + area[2];
        final int y1 =area[1];
        final int y2 =area[1] + area[3];
        final int lx1 =lastArea[0];
        final int lx2 =lastArea[0] + lastArea[2];
        final int ly1 =lastArea[1];
        final int ly2 =lastArea[1] + lastArea[3];

        //Ensure the highest and lowest values are selected
        if(x1ly2) {
            area[3] = y2 - area[1];
        } else {
            area[3] = ly2 - area[1];
        }

        if(x2>lx2) {
            area[2] = x2 - area[0];
        } else {
            area[2] = lx2 - area[0];
        }

        return area;
    }
    
    /**
     * Checks whether two rectangles intersect
     * Takes the raw x,y,w,h data of the rectangles in array form.
     * @param paramsOne
     * @param paramsTwo
     * @return boolean
     */
    public static boolean intersects(final int[] paramsOne, final int[] paramsTwo){
        
        final int X1 = paramsOne[0];
        final int Y1 = paramsOne[1];
        final int W1 = paramsOne[2];
        final int H1 = paramsOne[3];
        final int X2 = paramsTwo[0];
        final int Y2 = paramsTwo[1];
        final int W2 = paramsTwo[2];
        final int H2 = paramsTwo[3];

        return !(X1 + W1 < X2 || X2 + W2 < X1 || Y1 + H1 < Y2 || Y2 + H2 < Y1);
    }

    /**
     * Checks whether a point at (x,y) lies within the
     * bounds of an unrotated rectangles raw x,y,w,h values.
     * @return
     */
    private static boolean contains(final int x, final int y, final int[] rectParams){
        
        final int minX = rectParams[0]; //x
        final int minY = rectParams[1]; //y
        final int maxX = rectParams[0] + rectParams[2]; //x + width
        final int maxY = rectParams[1] + rectParams[3]; //y + height

        return (x >= minX && x <= maxX) && (y >= minY && y <= maxY);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy