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

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

The 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-2015 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 org.jpedal.objects.PdfData;
import org.jpedal.utils.repositories.Vector_Rectangle;

import java.awt.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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 areas has changed since last call to getHighlightedAreas(int)*/
    boolean hasHighlightAreasUpdated;

    /**
	 * Deprecated on 16/06/2014, please use setFoundParagraphAsArray(int x, int y, int page).
     * @deprecated
	 */
	public Rectangle setFoundParagraph(final int x, final int y, final int page){
        
        final int[][] rectParams = getLineAreasAs2DArray(page);
        
		if(rectParams!=null){
            final Rectangle[] lines = new Rectangle[rectParams.length];
            
            for(int i = 0; i < lines.length; i++){
                lines[i] = new Rectangle(rectParams[i][0],rectParams[i][1],rectParams[i][2],rectParams[i][3]);
            }
            
			final Rectangle point = new Rectangle(x,y,1,1);
			final Rectangle current = new Rectangle(0,0,0,0);
			boolean lineFound = false;
			int selectedLine = 0;

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

			if(lineFound){
				double left = lines[selectedLine].x;
				double cx = lines[selectedLine].getCenterX();
				double right = lines[selectedLine].x+lines[selectedLine].width;
				double cy = lines[selectedLine].getCenterY();
				int h = lines[selectedLine].height;

				current.x=lines[selectedLine].x;
				current.y=lines[selectedLine].y;
				current.width=lines[selectedLine].width;
				current.height=lines[selectedLine].height;

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

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

							if(current.x>lines[i].x){
								current.width = (current.x+current.width)-lines[i].x;
								current.x = lines[i].x;
							}
							if((current.x+current.width)<(lines[i].x+lines[i].width)) {
                                current.width = (lines[i].x + lines[i].width) - current.x;
                            }
							if(current.y>lines[i].y){
								current.height = (current.y+current.height)-lines[i].y;
								current.y = lines[i].y;
							}
							if((current.y+current.height)<(lines[i].y+lines[i].height)){
								current.height = (lines[i].y+lines[i].height)-current.y;
							}

							break;
						}
					}
				}

				//Return to selected item else we have duplicate highlights
				left = lines[selectedLine].x;
				cx = lines[selectedLine].getCenterX();
				right = lines[selectedLine].x+lines[selectedLine].width;
				cy = lines[selectedLine].getCenterY();
				h = lines[selectedLine].height;

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

							if(current.x>lines[i].x){
								current.width = (current.x+current.width)-lines[i].x;
								current.x = lines[i].x;
							}
							if((current.x+current.width)<(lines[i].x+lines[i].width)) {
                                current.width = (lines[i].x + lines[i].width) - current.x;
                            }
							if(current.y>lines[i].y){
								current.height = (current.y+current.height)-lines[i].y;
								current.y = lines[i].y;
							}
							if((current.y+current.height)<(lines[i].y+lines[i].height)){
								current.height = (lines[i].y+lines[i].height)-current.y;
							}

							break;
						}
					}
				}
				selected.trim();
				addHighlights(selected.get(), true, page);
				return current;
			}
			return null;
		}
		return null;
	}
    
    /**
	 * Highlights a section of lines that form a paragraph and
	 * returns the area that encloses all highlight areas.
	 * @return int[] that contains x,y,w,h of all areas 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;
}



    /**
     * This method is deprecated on 12/06/2014, please use 
     * addToLineAreas(int[] area, int writingMode, int page).
     * @deprecated
     * @param area
     * @param writingMode
     * @param page 
     */
    public void addToLineAreas(final Rectangle area, final int writingMode, final int page) {
        boolean addNew = true;

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

            //Set area
            lineAreas = new HashMap();
            lineAreas.put(page, new Rectangle[]{area});

            //Set writing direction
            lineWritingMode = new HashMap();
            lineWritingMode.put(page, new int[]{writingMode});

        }else{
            final Rectangle[] lastAreas = ((Rectangle[])lineAreas.get(page));
            final int[] lastWritingMode = ((int[])lineWritingMode.get(page));

            //Check for objects close to or intersecting each other
            if(area!=null){ //Ensure actual area is selected
                if(lastAreas!=null){
                    for(int i=0; i!= lastAreas.length; i++){
                        final int lwm = lastWritingMode[i];
                        int cx = area.x;
                        int cy = area.y;
                        int cw = area.width;
                        int ch = area.height;
                        //int cm = cy+(ch/2);

                        int lx = lastAreas[i].x;
                        int ly = lastAreas[i].y;
                        int lw = lastAreas[i].width;
                        int lh = lastAreas[i].height;
                        //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
                                                        lastAreas[i].intersects(area)))//Check to see if it intersects at all
                                        ){
                                    addNew = false;

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

                                lx = lastAreas[i].x;
                                ly = lastAreas[i].y;
                                lw = lastAreas[i].width;
                                lh = lastAreas[i].height;
                                cx = area.x;
                                cy = area.y;
                                cw = area.width;
                                ch = area.height;

                                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
                                                lastAreas[i].intersects(area))//Check to see if it intersects at all
                                        ){
                                    addNew = false;

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

                                lx = lastAreas[i].y;
                                ly = lastAreas[i].x;
                                lw = lastAreas[i].height;
                                lh = lastAreas[i].width;
                                cx = area.y;
                                cy = area.x;
                                cw = area.height;
                                ch = area.width;

                                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
                                                lastAreas[i].intersects(area))//Check to see if it intersects at all
                                        ){
                                    addNew = false;

                                    //No need to reset the writing mode as already set
                                    lastAreas[i]=mergePartLines(lastAreas[i], 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+ch)) && (ly-(lw*0.6)<(cy+ch)))// Check for text to right of current area
                                                        )
                                                                || area.intersects(lastAreas[i])
                                                )
                                        ){
                                    addNew = false;

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

                                break;

                        }

                    }
                }else{
                    addNew = true;
                }

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

                    final Rectangle[] lineAreas;
                    final int[] lineWritingMode;

                    if(lastAreas!=null){
                        lineAreas = new Rectangle[lastAreas.length+1];
                        for(int i=0; i!= lastAreas.length; i++){
                            lineAreas[i] = lastAreas[i];
                        }
                        lineAreas[lineAreas.length-1] = area;

                        lineWritingMode = new int[lastWritingMode.length+1];
                        for(int i=0; i!= lastWritingMode.length; i++){
                            lineWritingMode[i] = lastWritingMode[i];
                        }
                        lineWritingMode[lineWritingMode.length-1] = writingMode;

                    }else{
                        lineAreas = new Rectangle[1];
                        lineAreas[0] = area;

                        lineWritingMode = new int[1];
                        lineWritingMode[0] = writingMode;
                    }

                    //Set area
                    this.lineAreas.put(page, lineAreas);

                    //Set writing direction
                    this.lineWritingMode.put(page, lineWritingMode);
                }

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

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

            //Set area
            lineAreas = new HashMap();
            lineAreas.put(page, new int[][]{area});

            //Set writing direction
            lineWritingMode = new HashMap();
            lineWritingMode.put(page, new int[]{writingMode});

        }else{
            final int[][] lastAreas = ((int[][])lineAreas.get(page));
            final int[] lastWritingMode = ((int[])lineWritingMode.get(page));

            //Check for objects close to or intersecting each other
            if(area!=null){ //Ensure actual area is selected
                if(lastAreas!=null){
                    for(int i=0; i!= lastAreas.length; i++){
                        final int lwm = lastWritingMode[i];
                        int cx = area[0];
                        int cy = area[1];
                        int cw = area[2];
                        int ch = area[3];
                        //int cm = cy+(ch/2);

                        int lx = lastAreas[i][0];
                        int ly = lastAreas[i][1];
                        int lw = lastAreas[i][2];
                        int lh = lastAreas[i][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(lastAreas[i], area)))//Check to see if it intersects at all
                                        ){
                                    addNew = false;

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

                                lx = lastAreas[i][0];
                                ly = lastAreas[i][1];
                                lw = lastAreas[i][2];
                                lh = lastAreas[i][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(lastAreas[i], area))//Check to see if it intersects at all
                                        ){
                                    addNew = false;

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

                                lx = lastAreas[i][1];
                                ly = lastAreas[i][0];
                                lw = lastAreas[i][3];
                                lh = lastAreas[i][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(lastAreas[i], area))//Check to see if it intersects at all
                                        ){
                                    addNew = false;

                                    //No need to reset the writing mode as already set
                                    lastAreas[i]=mergePartLines(lastAreas[i], 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+ch)) && (ly-(lw*0.6)<(cy+ch)))// Check for text to right of current area
                                                        )
                                                                || intersects(area, lastAreas[i])
                                                )
                                        ){
                                    addNew = false;

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

                                break;

                        }

                    }
                }else{
                    addNew = true;
                }

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

                    final int[][] lineAreas;
                    final int[] lineWritingMode;

                    if(lastAreas!=null){
                        lineAreas = new int[lastAreas.length+1][4];
                        for(int i=0; i!= lastAreas.length; i++){
                            lineAreas[i] = lastAreas[i];
                        }
                        lineAreas[lineAreas.length-1] = area;

                        lineWritingMode = new int[lastWritingMode.length+1];
                        for(int i=0; i!= lastWritingMode.length; i++){
                            lineWritingMode[i] = lastWritingMode[i];
                        }
                        lineWritingMode[lineWritingMode.length-1] = writingMode;

                    }else{
                        lineAreas = new int[1][];
                        lineAreas[0] = area;

                        lineWritingMode = new int[1];
                        lineWritingMode[0] = writingMode;
                    }

                    //Set area
                    this.lineAreas.put(page, lineAreas);

                    //Set writing direction
                    this.lineWritingMode.put(page, lineWritingMode);
                }

            }
        }
    }

    /**
     * remove zone on page for text areas if present
     */
    public void removeFoundTextArea(final int[] rectArea, final int page){

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

        final Integer p = page;
        final int[][] areas = ((int[][])this.areas.get(p));
        if(areas!=null){
            final int size=areas.length;
            for(int i=0;ifinish){
                                final int temp = start;
                                start = finish;
                                finish = temp;
                                backward = true;
                            }

                            if(start==finish){
                                if(startPoint.x>endPoint.x){
                                    final Point temp = startPoint;
                                    startPoint = endPoint;
                                    endPoint = temp;
                                }
                            }

                            if(start!=-1 && finish!=-1){
                                //Fill in all the lines between
                                final Integer p = page;
                                final Rectangle[] areas = new Rectangle[finish-start+1];

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

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

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

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

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

                                                }
                                                break;
                                            case PdfData.HORIZONTAL_RIGHT_TO_LEFT:
                                                //
                                                break;
                                            case PdfData.VERTICAL_TOP_TO_BOTTOM:
                                                if(backward){
                                                    if((endPoint.y-15)<=areas[top].y){
                                                        //Do nothing to areas as we want to pick up the start of a line
                                                    }else{
                                                        areas[top].height -= (endPoint.y-areas[top].y);
                                                        areas[top].y = endPoint.y;
                                                    }

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

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

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

                                                }
                                                break;
                                        }


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

                                                }else{
                                                    if((endPoint.x+15)>=areas[bottom].x+areas[bottom].width){
                                                        //Do nothing to areas as we want to pick up the end of a line
                                                    }else {
                                                        areas[bottom].width = endPoint.x - areas[bottom].x;
                                                    }
                                                }
                                                break;
                                            case PdfData.HORIZONTAL_RIGHT_TO_LEFT:
                                                //
                                                break;
                                            case PdfData.VERTICAL_TOP_TO_BOTTOM:
                                                // if going backwards
                                                if(backward){
                                                    if((startPoint.y+15)>=areas[bottom].y+areas[bottom].height){
                                                        //Do nothing to areas as we want to pick up the end of a line
                                                    }else{
                                                        areas[bottom].height = startPoint.y - areas[bottom].y;
                                                    }

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

                                                }else{
                                                    if((endPoint.y+15)>=areas[bottom].y+areas[bottom].height){
                                                        //Do nothing to areas as we want to pick up the end of a line
                                                    }else {
                                                        areas[bottom].height = endPoint.y - areas[bottom].y;
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                }
                                this.areas.put(p, areas);
                            }
//							else {
//								//This is the first highlight and nothing was selected
//								if(nothingToHighlight){
//									System.out.println("Area == null");
//									//Prevent text extraction on nothing
//									this.areas = null;
//								}
//							}
                        }
                    }
                }
            }else{
                //if inset add in difference transparently
                for(int v=0; v!=highlights.length; v++){
                    if(highlights[v]!=null){
                        if(highlights[v].width<0){
                            highlights[v].width = -highlights[v].width;
                            highlights[v].x -=highlights[v].width;
                        }

                        if(highlights[v].height<0){
                            highlights[v].height = -highlights[v].height;
                            highlights[v].y -=highlights[v].height;
                        }

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

                                //see if already added
                                final int size=areas.length;
                                for(int i=0;ifinish){
                                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 Integer p = page;
                                final int[][] areas = new int[finish-start+1][4];

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

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

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

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

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

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

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

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

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

                                                }
                                                break;
                                        }


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

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

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

                                                }else{
                                                    if((endPoint[1]+15)>=areas[bottom][1]+areas[bottom][3]){
                                                        //Do nothing to areas as we want to pick up the end of a line
                                                    }else {
                                                        areas[bottom][3] = endPoint[1] - areas[bottom][1];
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                }
                                this.areas.put(p, areas);
                            }
//							else {
//								//This is the first highlight and nothing was selected
//								if(nothingToHighlight){
//									System.out.println("Area == null");
//									//Prevent text extraction on nothing
//									this.areas = null;
//								}
//							}
                        }
                    }
                }
            }else{
                //if inset add in difference transparently
                for(int v=0; v!=highlights.length; v++){
                    if(highlights[v]!=null){
                        if(highlights[v][2]<0){
                            highlights[v][2] = -highlights[v][2];
                            highlights[v][0] -=highlights[v][2];
                        }

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

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

                                //see if already added
                                final int size=areas.length;
                                for(int i=0;ily2) {
            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;
    }
    
    /**
     * This method is deprecated on 12/06/2014, please use
     * mergePartLines(int[] lastArea, int[] area)
     * @deprecated
     * @param lastArea
     * @param area
     * @return 
     */
    private static Rectangle mergePartLines(final Rectangle lastArea, final Rectangle area){
        /**
         * Check coords from both areas and merge them to make
         * a single larger area containing contents of both
         */
        final int x1 =area.x;
        final int x2 =area.x + area.width;
        final int y1 =area.y;
        final int y2 =area.y + area.height;
        final int lx1 =lastArea.x;
        final int lx2 =lastArea.x + lastArea.width;
        final int ly1 =lastArea.y;
        final int ly2 =lastArea.y + lastArea.height;

        //Ensure the highest and lowest values are selected
        if(x1ly2) {
            area.height = y2 - area.y;
        } else {
            area.height = ly2 - area.y;
        }

        if(x2>lx2) {
            area.width = x2 - area.x;
        } else {
            area.width = lx2 - area.x;
        }

        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.
     * @param Xp
     * @param Yp
     * @param rectParams[] x,y,w,h
     * @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