Package org.jpedal

Source Code of org.jpedal.SwingPainter

/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info:  http://www.jpedal.org
*
* (C) Copyright 2012, IDRsolutions and Contributors.
*
*   This file is part of JPedal
*
     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


  *
  * ---------------

  * SwingPainter.java
  * ---------------
  * (C) Copyright 2012, by IDRsolutions and Contributors.
  *
  *
  * --------------------------
*/
package org.jpedal;

//<start-adobe><start-ulc><start-thin>
import org.jpedal.examples.simpleviewer.gui.SwingGUI;
import org.jpedal.examples.simpleviewer.gui.swing.SwingMouseSelector;
//<end-thin><end-ulc><end-adobe>

import org.jpedal.exception.PdfException;
import org.jpedal.external.ExternalHandlers;
import org.jpedal.external.Options;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.objects.PdfPageData;
import org.jpedal.objects.acroforms.rendering.AcroRenderer;
import org.jpedal.parser.DecoderOptions;
import org.jpedal.render.DynamicVectorRenderer;
import org.jpedal.render.SwingDisplay;
import org.jpedal.text.TextLines;
import org.jpedal.utils.ScalingFactory;

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

/**
* handle drawing of content in Swing panel for screen display
*/
class SwingPainter {

    protected int lastFormPage=-1,lastStart=-1,lastEnd=-1;

    /**allows user to create viewport on page and scale to this*/
    public Rectangle viewableArea=null;

    private int pageUsedForTransform;

    /**tracks indent so changing to continuous does not disturb display*/
    private int lastIndent=-1;

    /**rectangle drawn on screen by user*/
    private Rectangle cursorBoxOnScreen = null;
    private Rectangle lastCursorBoxOnScreen=null;

    /**colour of highlighted rectangle*/
    private Color outlineColor;

    private AffineTransform cursorAf;

    private double indent=0;

    /**
     * used to apply the imageable area to the displayscaling, used instead of
     * displayScaling, as to preserve displayScaling
     */
    private AffineTransform viewScaling=null;
    private PdfDecoder pdfDecoder;

    DisplayOffsets displayOffsets;

    DecoderOptions options=new DecoderOptions();

    public SwingPainter(PdfDecoder pdfDecoder,DecoderOptions options) {
        this.pdfDecoder = pdfDecoder;
        this.options=options;

        displayOffsets=options.getDisplayOffsets();
    }

    public void paintPage(Graphics2D g2, PdfDecoder pdfDecoder, Display pages, PdfPageData pageData, int pageNumber,
                          DynamicVectorRenderer currentDisplay, int displayView, int displayRotation, int insetW, int insetH,
                          TextLines textLines, Border myBorder, PageOffsets currentOffset, ExternalHandlers externalHandlers){

        AcroRenderer formRenderer=pdfDecoder.getFormRenderer();
        Rectangle visibleRect=pdfDecoder.getVisibleRect();
        int pageCount=pdfDecoder.getPageCount();
        float scaling=pdfDecoder.getScaling();

        pages.init(scaling, pageCount, displayRotation, pageNumber, currentDisplay, false, pageData, insetW, insetH);

        //remember so we can put it back
        final AffineTransform rawAf=g2.getTransform();

        //include any user trnaslation
        g2.translate(displayOffsets.getUserOffsetX(), displayOffsets.getUserOffsetY());

        //track all changes
        int start=pageNumber,end=pageNumber;

        //control if we display forms on multiple pages
        if(displayView!=Display.SINGLE_PAGE && displayView!=Display.PAGEFLOW){
            start= pages.getStartPage();
            end= pages.getEndPage();
            if(start==0 || end==0 || lastEnd!=end || lastStart!=start)
                lastFormPage=-1;

            lastEnd=end;
            lastStart=start;

        }

        if(lastFormPage!=pageNumber){

            if (formRenderer != null){
                formRenderer.displayComponentsOnscreen(start,end);

                //switch off if forms for this page found
                if(formRenderer.getCompData().getStartComponentCountForPage(pageNumber)!=-1)
                    lastFormPage=pageNumber; //ensure not called too early
            }
        }

        //center if required
        if(pdfDecoder.alignment==Display.DISPLAY_CENTERED){
            double width=pdfDecoder.getBounds().getWidth();

            if(displayView==Display.PAGEFLOW)
                width=visibleRect.getWidth();

            int pdfWidth=pdfDecoder.getPDFWidth();
            if(displayView!=Display.SINGLE_PAGE)
                pdfWidth=(int) pages.getPageSize(displayView).getWidth();

            //we indent it here so selected page is  in middle of panel and now make rest of co-ords relative which is all much easier....
            if(displayView==Display.PAGEFLOW){

                indent=((visibleRect.width- pages.getWidthForPage(pageNumber))/2)-insetW-pdfDecoder.getBounds().x;

            } else if (displayView==Display.FACING) {

                int page = pageNumber;
                if (pages.getSeparateCover() && (page & 1)==1)
                    page--;
                else if (!pages.getSeparateCover() && (page & 1)==0)
                    page--;

                //Get widths of pages
                int firstW,secondW;
                if ((displayRotation + pageData.getRotation(page))%180==90)
                    firstW = pageData.getCropBoxHeight(page);
                else
                    firstW = pageData.getCropBoxWidth(page);

                if (page+1 > pageCount) {
                    secondW = firstW;
                } else {
                    if ((displayRotation + pageData.getRotation(page + 1))%180==90)
                        secondW = pageData.getCropBoxHeight(page + 1);
                    else
                        secondW = pageData.getCropBoxWidth(page + 1);
                }

                //set pageGap
                int pageGap = 0;
                if (!pages.getTurnoverOn() || pageData.hasMultipleSizes() || pageCount==2)
                    pageGap = currentOffset.pageGap/2;

                //set indent
                indent = (((width - ((firstW + secondW) * scaling)) / 2) - pageGap - insetW);
            } else
                indent=((width-pdfWidth)/2);

            if(displayView==Display.SINGLE_PAGE)
                lastIndent=(int)indent;
            else if((displayView==Display.CONTINUOUS || displayView==Display.PAGEFLOW) && lastIndent!=-1){
                indent=lastIndent;
                lastIndent = -1;
            }else
                lastIndent=-1;

            g2.translate(indent,0);

            if(formRenderer!=null && currentOffset !=null){ //if all forms flattened, we can get a null value for currentOffset so avoid this case

                if(displayView==Display.PAGEFLOW)
                    indent= indent-((pageNumber-1)*(PageOffsets.getPageFlowPageWidth((int)(pageData.getCropBoxWidth(pageNumber)*scaling),scaling)));

                formRenderer.getCompData().setPageValues(scaling,displayRotation,(int)indent,displayOffsets.getUserOffsetX(), displayOffsets.getUserOffsetY(),displayView,currentOffset.widestPageNR, currentOffset.widestPageR);
                formRenderer.getCompData().resetScaledLocation(scaling,displayRotation,(int)indent);//indent here does nothing.
            }
        }else if(formRenderer!=null && currentOffset !=null){
            lastIndent=-1;
            formRenderer.getCompData().setPageValues(scaling,displayRotation,(int)indent,displayOffsets.getUserOffsetX(), displayOffsets.getUserOffsetY(),displayView, currentOffset.widestPageNR, currentOffset.widestPageR);
            formRenderer.getCompData().resetScaledLocation(scaling,displayRotation,(int)indent);
        }

        pages.initRenderer(textLines.areas, g2, myBorder, (int) indent);

        pages.drawPage(viewScaling, pdfDecoder.displayScaling, pageUsedForTransform);

        /**/
        //disabled if not in Single PAGE
             if(displayView==Display.SINGLE_PAGE){
             /**/
            /**
             * draw highlighted text boxes
             */


            // add any viewport
            if(viewScaling!=null)
                g2.transform(viewScaling);

            /**add any highlighted rectangle on screen*/
            if (cursorBoxOnScreen != null)
                cursorAf=g2.getTransform();

            pages.resetToDefaultClip();

        }

        if(displayView==Display.SINGLE_PAGE){
            drawHighlightsForImage(g2, pages.getHighlightedImage(),scaling,displayRotation, insetW, insetH, pdfDecoder.max_x, pdfDecoder.max_y);
        }else{
            pages.setHighlightedImage(null);
        }

        /**
         * draw other pages if not in SINGLE mode
         **/
        pages.drawBorder();

        //restore affine settings
        g2.setTransform(rawAf);

        //draw facing mode turnover

        //draw preview on page if set
        if(displayView == Display.SINGLE_PAGE)
            pages.drawPreviewImage(g2, visibleRect);

    }

    public void setCursorBoxOnScreen(Rectangle cursorBoxOnScreen, boolean isSamePage, AcroRenderer formRenderer) {
        this.cursorBoxOnScreen=cursorBoxOnScreen;

        if (!isSamePage && formRenderer != null){
            formRenderer.removeDisplayComponentsFromScreen();
            lastFormPage=-1; //reset so will appear on reparse
        }
    }

    public Rectangle getCursorBoxOnScreen() {
        return cursorBoxOnScreen;
    }

    public void drawCursor(Graphics g, int alignment) {

        /**add any highlighted rectangle on screen*/
        if (cursorBoxOnScreen != null){
            Graphics2D g2=(Graphics2D) g;
            AffineTransform defaultAf=g2.getTransform();

            if(cursorAf!=null){
                g2.setTransform(cursorAf);

                Shape clip=g2.getClip();

                //remove clip for drawing outline
                if(alignment==Display.DISPLAY_CENTERED && clip!=null)
                    g2.setClip(null);

                //<start-adobe>
                if(cursorBoxOnScreen!=null && PdfDecoder.showMouseBox)
                    paintRectangle(g2, cursorBoxOnScreen, pdfDecoder.scaling, outlineColor);
                lastCursorBoxOnScreen=cursorBoxOnScreen;
                //<end-adobe>

                g2.setClip(clip);

                g2.setTransform(defaultAf);

            }
        }
    }

    final public void updateCursorBoxOnScreen(Rectangle newOutlineRectangle, Color outlineColor, PdfDecoder pdfDecoder, int pageNumber) {

        PdfPageData pageData=pdfDecoder.getPdfPageData();

        //area to reapint
        int x_size=pdfDecoder.x_size;
        int y_size=pdfDecoder.y_size;

        if(newOutlineRectangle!=null){

            int x=newOutlineRectangle.x;
            int y=newOutlineRectangle.y;
            int w=newOutlineRectangle.width;
            int h=newOutlineRectangle.height;

            int cropX=pageData.getCropBoxX(pageNumber);
            int cropY=pageData.getCropBoxY(pageNumber);
            int cropW=pageData.getCropBoxWidth(pageNumber);
            int cropH=pageData.getCropBoxHeight(pageNumber);

            //allow for odd crops and correct
            if(y>0 && y<(cropY))
                y=y+cropY;

            if(x<cropX){
                int diff=cropX-x;
                w=w-diff;
                x=cropX;
            }

            if(y<cropY){
                int diff=cropY-y;
                h=h-diff;
                y=y+diff;
            }
            if((x+w)>cropW+cropX)
                w=cropX+cropW-x;
            if((y+h)>(cropY+cropH))
                h=cropY+cropH-y;

            cursorBoxOnScreen = new Rectangle(x,y,w,h);

        }else
            cursorBoxOnScreen=null;

        this.outlineColor = outlineColor;

        int strip=30;

        /**allow offset from page being centered*/
        int dx=0;
        //center if required
        if(pdfDecoder.alignment==Display.DISPLAY_CENTERED){
            int width=pdfDecoder.getBounds().width;
            int pdfWidth=pdfDecoder.getPDFWidth();

            if(pdfDecoder.displayView!=Display.SINGLE_PAGE)
                pdfWidth=(int) pdfDecoder.pages.getPageSize(pdfDecoder.displayView).getWidth();

            dx=((width-pdfWidth)/2);
        }

        /**repaint manager*/
        RepaintManager currentManager=RepaintManager.currentManager(pdfDecoder);

        if(lastCursorBoxOnScreen!=null){
            if(pdfDecoder.displayRotation==0 || pdfDecoder.displayRotation==180)
                currentManager.addDirtyRegion(pdfDecoder, pdfDecoder.insetW+dx, pdfDecoder.insetH,x_size+5,y_size);
            else
                currentManager.addDirtyRegion(pdfDecoder, pdfDecoder.insetH+dx, pdfDecoder.insetW,y_size+5,x_size);

            lastCursorBoxOnScreen=null;
        }

        if(cursorBoxOnScreen!=null){
            currentManager.addDirtyRegion(pdfDecoder,(int)(cursorBoxOnScreen.x* pdfDecoder.scaling)-strip,
                    (int)(((pdfDecoder.max_y)-cursorBoxOnScreen.y-cursorBoxOnScreen.height)* pdfDecoder.scaling)-strip,
                    (int)(cursorBoxOnScreen.width* pdfDecoder.scaling)+strip+strip,
                    (int)(cursorBoxOnScreen.height* pdfDecoder.scaling)+strip+strip);
        }

        if(viewScaling!=null)
            currentManager.markCompletelyDirty(pdfDecoder);

        //force repaint
        pdfDecoder.repaint();
    }
    //<end-adobe>

    public double getIndent() {
        return indent;
    }

    /**
     * initialise panel and set size to display during updates and update the AffineTransform to new values<br>
     */
    public void setPageRotation(int newRotation, PdfPageData pageData) {

        pdfDecoder.displayRotation = newRotation;

        //assume unrotated for multiple views and rotate on a page basis
        if(pdfDecoder.displayView!=Display.SINGLE_PAGE)
            newRotation=0;

        pageUsedForTransform= pdfDecoder.pageNumber;
        if(pdfDecoder.displayView!=Display.SINGLE_PAGE && pdfDecoder.displayView!=Display.FACING)
            pdfDecoder.displayScaling = ScalingFactory.getScalingForImage(1, 0, pdfDecoder.scaling,pageData);//(int)(pageData.getCropBoxWidth(pageNumber)*scaling),(int)(pageData.getCropBoxHeight(pageNumber)*scaling),
        else
            pdfDecoder.displayScaling = ScalingFactory.getScalingForImage(pdfDecoder.pageNumber,newRotation, pdfDecoder.scaling, pageData);//(int)(pageData.getCropBoxWidth(pageNumber)*scaling),(int)(pageData.getCropBoxHeight(pageNumber)*scaling),

        if(newRotation == 90){
            pdfDecoder.displayScaling.translate(pdfDecoder.insetH/ pdfDecoder.scaling, pdfDecoder.insetW/ pdfDecoder.scaling);
        }else if(newRotation == 270){
            pdfDecoder.displayScaling.translate(-pdfDecoder.insetH/ pdfDecoder.scaling,-pdfDecoder.insetW/ pdfDecoder.scaling);
        }else if(newRotation == 180){
            pdfDecoder.displayScaling.translate(-pdfDecoder.insetW/ pdfDecoder.scaling, pdfDecoder.insetH/(pdfDecoder.scaling));
        }else{
            pdfDecoder.displayScaling.translate(pdfDecoder.insetW/ pdfDecoder.scaling,-pdfDecoder.insetH/ pdfDecoder.scaling);
        }

        //force redraw if screen being cached
        pdfDecoder.pages.refreshDisplay();

        /**
         * now apply any viewport scaling
         */
        if(viewableArea!=null){

            viewScaling=new AffineTransform();

            /**workout scaling and choose larger*/
            double dx=(double)viewableArea.width/(double) pageData.getCropBoxWidth(pdfDecoder.pageNumber);
            double dy=(double)viewableArea.height/(double) pageData.getCropBoxHeight(pdfDecoder.pageNumber);
            double viewScale=dx;
            if(dy<dx)
                viewScale=dy;

            /**workout any translation*/
            double x=viewableArea.x;//left align
            double y=viewableArea.y+(viewableArea.height-(pageData.getCropBoxHeight(pdfDecoder.pageNumber)*viewScale));//top align

            viewScaling.translate(x,y);
            viewScaling.scale(viewScale,viewScale);

        }else
            viewScaling=null;
    }

    //<start-adobe>
    public AffineTransform setViewableArea(Rectangle viewport, PdfDecoder pdfDecoder, PdfPageData pageData) throws PdfException {
        if (viewport != null) {

            double x = viewport.getX();
            double y = viewport.getY();
            double w = viewport.getWidth();
            double h = viewport.getHeight();

            // double crx = pageData.getCropBoxX(pageNumber);
            // double cry = pageData.getCropBoxY(pageNumber);
            double crw = pageData.getCropBoxWidth(pdfDecoder.pageNumber);
            double crh = pageData.getCropBoxHeight(pdfDecoder.pageNumber);

            // throw exception if viewport cannot fit in cropbox
            if (x < 0 || y < 0 || (x + w) > crw || (y + h) > crh) {
                throw new PdfException("Viewport is not totally enclosed within displayed panel.");
            }

            // if viewport exactlly matches the cropbox
            if (crw == w && crh == h) {
            } else {// else work out scaling ang apply

                viewableArea = viewport;
                setPageRotation(pdfDecoder.displayRotation,pageData);
                pdfDecoder.repaint();
            }
        } else {
            resetViewableArea(pdfDecoder, pageData);
        }

        return viewScaling;
    }
    //<end-adobe>

    public DisplayOffsets getDisplayOffsets() {
        return displayOffsets;
    }

    public void resetViewableArea(PdfDecoder pdfDecoder, PdfPageData pageData) {

        if (viewableArea != null) {
            viewableArea = null;

            setPageRotation(pdfDecoder.displayRotation, pageData);
            pdfDecoder.repaint();
        }
    }

    public void resetMultiPageForms(int page, PdfDecoder pdfDecoder, AcroRenderer formRenderer, Display pages) {

        formRenderer.removeDisplayComponentsFromScreen();
        pdfDecoder.add(pages.getScroll(), BorderLayout.SOUTH);

        lastFormPage=-1; //reset so will appear on reparse

        formRenderer.displayComponentsOnscreen(page,page);

        //switch off if forms for this page found
        if(formRenderer.getCompData().getStartComponentCountForPage(page)!=-1)
            lastFormPage=page; //ensure not called too early
    }

    public void forceRedraw() {

        lastFormPage = -1;
        lastEnd = -1;
        lastStart = -1;
    }


    private static void drawHighlightsForImage(Graphics2D g2, int[] highlightedImage, float scaling, int displayRotation, int insetW,int insetH, int max_x,int max_y) {

        if(highlightedImage!=null){

            //All image highlight coords scaled here to allow for any scaling value

            //Varibles added to make the code more readable
            int x = (int) (highlightedImage[0] * scaling);
            int y = (int) (highlightedImage[1] * scaling);
            int w = (int) (highlightedImage[2] * scaling);
            int h = (int) (highlightedImage[3] * scaling);

            //      //Check for negative values
            if (w < 0) {
                w = -w;
                x = x - w;
            }
            if (h < 0) {
                h = -h;
                y = y - h;
            }

            //Final values to use
            int finalX;
            int finalY;
            int finalW = w;
            int finalH = h;

            //Handle Any Rotation
            if (displayRotation == 90) {

                finalH = w;
                finalW = h;

                finalX = insetW + y;
                finalY = insetH + x;

            } else if (displayRotation == 180) {

                finalX = (int) ((max_x * scaling) - (x) - w) + insetW;
                finalY = (insetH + y);

            } else if (displayRotation == 270) {

                finalH = w;
                finalW = h;

                finalY = (int) ((max_x * scaling) - (x) - w) + insetW;
                finalX = (int) ((max_y * scaling) - (y) - h) + insetH;

            } else {
                finalX = insetW + x;
                finalY = (int) ((max_y * scaling) - (y) - h) + insetH;

            }

            Color oldColor = g2.getColor();
            Composite oldComposite = g2.getComposite();
            Stroke oldStroke = g2.getStroke();

            g2.setStroke(new BasicStroke(2));
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, PdfDecoder.highlightComposite));

            //draw border
            if (SwingDisplay.invertHighlight) {
                g2.setColor(Color.WHITE);
                g2.setXORMode(Color.BLACK);
            } else {
                g2.setColor(DecoderOptions.highlightColor);
                g2.drawRect(finalX, finalY, finalW, finalH);
            }

            //fill border
            g2.fillRect(finalX, finalY, finalW, finalH);
            //set back to original setup
            g2.setColor(oldColor);
            g2.setComposite(oldComposite);
            g2.setStroke(oldStroke);
        }
    }


    //<start-adobe>

    /**
     * draw cursorBox on screen with specified color,
     */
    private static void paintRectangle(Graphics2D g2,Rectangle cursorBoxOnScreen, float scaling,Color outlineColor){

        Stroke oldStroke = g2.getStroke();//copy before to stop page border from being dotted
        Stroke lineStroke;

        //allow for negative
        if(scaling<0)
            lineStroke = new BasicStroke(1/-scaling);
        else
            lineStroke = new BasicStroke(1/scaling);

        g2.setStroke(lineStroke);

        g2.setColor(outlineColor);

        //Draw opaque square around highlight area
        g2.draw(cursorBoxOnScreen);

        g2.setStroke(oldStroke);

    }

    //<end-adobe>

    public static BufferedImage getSelectedRectangleOnscreen(float t_x1, float t_y1, float t_x2, float t_y2, float scaling, int pageNumber, PdfPageData pageData, AcroRenderer formRenderer, DynamicVectorRenderer currentDisplay, PdfObjectReader currentPdfFile) {

        /** get page sizes */
        int mediaBoxH = pageData.getMediaBoxHeight(pageNumber);
        int crw = pageData.getCropBoxWidth(pageNumber);
        int crh = pageData.getCropBoxHeight(pageNumber);
        int crx = pageData.getCropBoxX(pageNumber);
        int cry = pageData.getCropBoxY(pageNumber);

        // check values for rotated pages
        if (t_y2 < cry)
            t_y2 = cry;
        if (t_x1 < crx)
            t_x1 = crx;
        if (t_y1 > (crh + cry))
            t_y1 = crh + cry;
        if (t_x2 > (crx + crw))
            t_x2 = crx + crw;

        if ((t_x2 - t_x1) < 1 || (t_y1 - t_y2) < 1)
            return null;

        float scalingFactor = scaling / 100;
        float imgWidth = t_x2 - t_x1;
        float imgHeight = t_y1 - t_y2;

        /**
         * create the image
         */
        BufferedImage img = new BufferedImage((int) (imgWidth * scalingFactor),
                (int) (imgHeight * scalingFactor), BufferedImage.TYPE_INT_RGB);

        Graphics2D g2 = img.createGraphics();

        /**
         * workout the scaling
         */
        if (cry > 0)// fix for negative pages
            cry = mediaBoxH - crh - cry;

        // use 0 for rotated extraction
        AffineTransform scaleAf = ScalingFactory.getScalingForImage(pageNumber, 0, scalingFactor,pageData);
        int cx = -crx, cy = -cry;

        scaleAf.translate(cx, -cy);
        scaleAf.translate(-(t_x1 - crx), mediaBoxH - t_y1 - cry);

        AffineTransform af = g2.getTransform();

        g2.transform(scaleAf);

        currentDisplay.setG2(g2);
        currentDisplay.paintBackground(new Rectangle(crx, cry, crw, crh));

        currentDisplay.setOptimsePainting(true); //ensure drawn
        currentDisplay.paint(null, null, null);


        /**
         * draw acroform data onto Panel
         */
        if (formRenderer != null && formRenderer.hasFormsOnPage(pageNumber)) {

            //note rotation is hard-coded to zero as rotation on image is zero!
            formRenderer.getCompData().renderFormsOntoG2(g2, pageNumber, scaling, 0,
                    0, null,null, currentPdfFile, pageData.getMediaBoxHeight(pageNumber));


        }

        g2.setTransform(af);

        g2.dispose();

        return img;
    }
}
TOP

Related Classes of org.jpedal.SwingPainter

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