Examples of GVTGlyphVector


Examples of org.apache.batik.gvt.font.GVTGlyphVector

            Iterator iter = layouts.iterator();
            while (iter.hasNext()) {
                GlyphLayout gl = (GlyphLayout)iter.next();
                gvl.add(gl.getGlyphVector());
            }
            GVTGlyphVector gv = new MultiGlyphVector(gvl);
            gvs[chunk] = gv;
            int numGlyphs = gv.getNumGlyphs();

            // System.out.println("Glyphs: " + numGlyphs);

            aci.first();
            MarginInfo mi = (MarginInfo)aci.getAttribute(FLOW_PARAGRAPH);
            if (mi == null) {
              continue;
            }
            justification = mi.getJustification();

            if (cRect == null) {
                for(int idx=0; idx <numGlyphs; idx++)
                    gv.setGlyphVisible(idx, false);
                continue;
            }

            float inc = ((prevBotMargin > mi.getTopMargin())
                         ? prevBotMargin : mi.getTopMargin());
            if (dy + inc <= height) {
                dy += inc;
            } else {
                // Move to next flow region..
                if (!flowRectsIter.hasNext()) {
                    cRect = null;
                    break; // No flow rect stop layout here...
                }

                cRect = (Rectangle2D)flowRectsIter.next();
                height = (float)cRect.getHeight();

                            // New rect so no previous row to consider...
                dy        = mi.getTopMargin();
            }
            prevBotMargin = mi.getBottomMargin();

            float leftMargin = mi.getFirstLineLeftMargin();
            float rightMargin = mi.getFirstLineRightMargin();

            x0    = (float)cRect.getX() + leftMargin;
            y0    = (float)cRect.getY();
            width = (float)(cRect.getWidth() - (leftMargin+rightMargin));
            height = (float)cRect.getHeight();
           
            List lineInfos = new LinkedList();

            float prevDesc = 0.0f;
            GlyphIterator gi = new GlyphIterator(aci, gv);
            GlyphIterator breakGI  = null, newBreakGI = null;

            if (!gi.done() && !gi.isPrinting()) {
              // This will place any preceeding whitespace on an imaginary
              // line that preceeds the real first line of the paragraph.
              lineInfos.add(gi.newLine
                            (new Point2D.Float(x0, y0+dy),
                             width, true));
            }


            GlyphIterator lineGI   =  gi.copy();
            boolean firstLine = true;
            while (!gi.done()) {
                boolean doBreak = false;
                boolean partial = false;

                if (gi.isPrinting() && (gi.getAdv() > width)) {
                    if (breakGI == null) {
                        // first char on line didn't fit.
                        // move to next flow rect.
                        if (!flowRectsIter.hasNext()) {
                            cRect = null;
                            gi = lineGI.copy(gi);
                            break; // No flow rect stop layout here...
                        }

                        cRect = (Rectangle2D)flowRectsIter.next();
                        x0    = (float) cRect.getX() + leftMargin;
                        y0    = (float) cRect.getY();
                        width = (float)(cRect.getWidth() -
                                        (leftMargin+rightMargin));
                        height = (float)cRect.getHeight();

                        // New rect so no previous row to consider...
                        dy        = firstLine?mi.getTopMargin():0; ;
                        prevDesc  = 0;
                        gi = lineGI.copy(gi);
                        continue;
                    }

                    gi = breakGI.copy(gi)// Back up to break loc...

                    nextLineMult = 1;
                    doBreak = true;
                    partial = false;
                } else if (gi.isLastChar()) {
                    nextLineMult = 1;
                    doBreak = true;
                    partial = true;
                }
                int lnBreaks = gi.getLineBreaks();
                if (lnBreaks != 0) {
                    if (doBreak)
                        nextLineMult -= 1;
                    nextLineMult += lnBreaks;
                    doBreak = true;
                    partial = true;
                }

                if (!doBreak) {
                    // System.out.println("No Brk Adv: " + gi.getAdv());
                    // We don't need to break the line because of this glyph
                    // So we just check if we need to update our break loc.
                    if ((gi.isBreakChar()) ||
                        (breakGI == null||
                        (!breakGI.isBreakChar())) {
                        // Make this the new break if curr char is a
                        // break char or we don't have any break chars
                        // yet, or our current break char is also not
                        // a break char.
                        newBreakGI = gi.copy(newBreakGI);
                        gi.nextChar();
                        if (gi.getChar() != GlyphIterator.ZERO_WIDTH_JOINER) {
                            GlyphIterator tmpGI = breakGI;
                            breakGI = newBreakGI;
                            newBreakGI = tmpGI;
                        }
                    } else {
                        gi.nextChar();
                    }
                    continue;
                }

                // System.out.println("   Brk Adv: " + gi.getAdv());

                // We will now attempt to break the line just
                // after 'gi'.

                // Note we are trying to figure out where the current
                // line is going to be placed (not the next line).  We
                // must wait until we have a potential line break so
                // we know how tall the line is.

                // Get the nomial line advance based on the
                // largest font we encountered on line...
                float lineSize = gi.getMaxAscent()+gi.getMaxDescent();
                float lineBoxHeight;
                if (lineHeightRelative)
                    lineBoxHeight = gi.getMaxFontSize()*lineHeight;
                else
                    lineBoxHeight = lineHeight;
                float halfLeading = (lineBoxHeight-lineSize)/2;

                float ladv = prevDesc + halfLeading + gi.getMaxAscent();
                float newDesc = halfLeading + gi.getMaxDescent();

                dy += ladv;
                float bottomEdge = newDesc;
                if (newDesc < gi.getMaxDescent())
                    bottomEdge = gi.getMaxDescent();

                if ((dy + bottomEdge) > height)  {
                    // The current Line doesn't fit in the
                    // current flow rectangle so we need to
                    // move line to the next flow rect.

                    // System.out.println("Doesn't Fit: " + dy);

                    if (!flowRectsIter.hasNext()) {
                        cRect = null;
                        gi = lineGI.copy(gi);
                        break; // No flow rect stop layout here...
                    }

                        // Remember how wide this rectangle is...
                    float oldWidth = width;

                    // Get info for new flow rect.
                    cRect = (Rectangle2D)flowRectsIter.next();
                    x0    = (float) cRect.getX() + leftMargin;
                    y0    = (float) cRect.getY();
                    width = (float)(cRect.getWidth() -
                                    (leftMargin+rightMargin));
                    height = (float)cRect.getHeight();

                    // New rect so no previous row to consider...
                    dy        = firstLine?mi.getTopMargin():0; ;
                    prevDesc  = 0;
                    // previous flows?

                    if (gi.getAdv() > oldWidth) {
                        // need to back up to start of line...
                        gi = lineGI.copy(gi);
                    }
                    continue;
                }

                prevDesc = newDesc + (nextLineMult-1)*lineBoxHeight;
                nextLineMult = 0f;
                lineInfos.add(gi.newLine
                              (new Point2D.Float(x0, y0+dy), width, partial));

                // System.out.println("Fit: " + dy);
                x0    -= leftMargin;
                width += leftMargin+rightMargin;

                leftMargin  = mi.getLeftMargin();
                rightMargin = mi.getRightMargin();
                x0    += leftMargin;
                width -= leftMargin+rightMargin;

                firstLine = false;
                // The line fits in the current flow rectangle.
                lineGI  = gi.copy(lineGI);
                breakGI = null;
            }
            dy += prevDesc;

            int idx = gi.getGlyphIndex();
            while(idx <numGlyphs)
                gv.setGlyphVisible(idx++, false);

            layoutChunk(aci, gv, gi.getOrigin(), justification, lineInfos);

            if (mi.isFlowRegionBreak()) {
                // Move to next flow region..
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

            Iterator iter = layouts.iterator();
            while (iter.hasNext()) {
                GlyphLayout gl = (GlyphLayout)iter.next();
                gvl.add(gl.getGlyphVector());
            }
            GVTGlyphVector gv = new MultiGlyphVector(gvl);
            gvs[chunk] = gv;
            int numGlyphs = gv.getNumGlyphs();

            // System.out.println("Glyphs: " + numGlyphs);

            aci.first();
            MarginInfo mi = (MarginInfo)aci.getAttribute(FLOW_PARAGRAPH);
            if (mi == null) {
              continue;
            }
            int justification = mi.getJustification();

            if (currentRegion == null) {
                for(int idx=0; idx <numGlyphs; idx++)
                    gv.setGlyphVisible(idx, false);
                continue;
            }

            float inc = ((prevBotMargin > mi.getTopMargin())
                         ? prevBotMargin : mi.getTopMargin());
            if (dy + inc <= height) {
                dy += inc;
            } else {
                // Move to next flow region..
                // NEXT FLOW REGION
                if (!flowRectsIter.hasNext()) {
                    currentRegion = null;
                    break; // No flow rect stop layout here...
                }

                // NEXT FLOW REGION
                currentRegion = (RegionInfo) flowRectsIter.next();
                height = (float) currentRegion.getHeight();
                // start a new alignment offset for this flow rect..
                verticalAlignOffset = new Point2D.Float(0,0);

                            // New rect so no previous row to consider...
                dy        = mi.getTopMargin();
            }
            prevBotMargin = mi.getBottomMargin();

            float leftMargin = mi.getLeftMargin();
            float rightMargin = mi.getRightMargin();
            if (((GlyphLayout)layouts.get(0)).isLeftToRight()) {
                leftMargin += mi.getIndent();
            } else {
                rightMargin += mi.getIndent();
            }

            x0 = (float) currentRegion.getX() + leftMargin;
            y0 = (float) currentRegion.getY();
            width = (float) (currentRegion.getWidth() -
                             (leftMargin + rightMargin));
            height = (float) currentRegion.getHeight();
           
            List lineInfos = new LinkedList();
            chunkLineInfos[chunk] = lineInfos;

            float prevDesc = 0.0f;
            GlyphIterator gi = new GlyphIterator(aci, gv);
            gis[chunk] = gi;

            GlyphIterator breakGI  = null, newBreakGI = null;

            if (!gi.done() && !gi.isPrinting()) {
                // This will place any preceeding whitespace on an
                // imaginary line that preceeds the real first line of
                // the paragraph, also calculate the vertical
                // alignment offset, this will be repeated until the
                // last line in the flow rect.
               updateVerticalAlignOffset(verticalAlignOffset,
                                         currentRegion, dy);
               lineInfos.add(gi.newLine
                             (new Point2D.Float(x0, y0+dy),
                              width, true, verticalAlignOffset));
            }


            GlyphIterator lineGI   =  gi.copy();
            boolean firstLine = true;
            while (!gi.done()) {
                boolean doBreak = false;
                boolean partial = false;

                if (gi.isPrinting() && (gi.getAdv() > width)) {
                    if (breakGI == null) {
                        // first char on line didn't fit.
                        // move to next flow rect.
                        if (!flowRectsIter.hasNext()) {
                            currentRegion = null;
                            gi = lineGI.copy(gi);
                            break; // No flow rect stop layout here...
                        }

                        // NEXT FLOW REGION
                        currentRegion = (RegionInfo) flowRectsIter.next();
                        x0 = (float) currentRegion.getX() + leftMargin;
                        y0 = (float) currentRegion.getY();
                        width = (float) (currentRegion.getWidth() -
                                        (leftMargin+rightMargin));
                        height = (float) currentRegion.getHeight();
                        // start a new alignment offset for this flow rect..
                        verticalAlignOffset = new Point2D.Float(0,0);

                        // New rect so no previous row to consider...
                        dy = firstLine ? mi.getTopMargin() : 0;
                        ;
                        prevDesc  = 0;
                        gi = lineGI.copy(gi);
                        continue;
                    }

                    gi = breakGI.copy(gi)// Back up to break loc...

                    nextLineMult = 1;
                    doBreak = true;
                    partial = false;
                } else if (gi.isLastChar()) {
                    nextLineMult = 1;
                    doBreak = true;
                    partial = true;
                }
                int lnBreaks = gi.getLineBreaks();
                if (lnBreaks != 0) {
                    if (doBreak)
                        nextLineMult -= 1;
                    nextLineMult += lnBreaks;
                    doBreak = true;
                    partial = true;
                }

                if (!doBreak) {
                    // System.out.println("No Brk Adv: " + gi.getAdv());
                    // We don't need to break the line because of this glyph
                    // So we just check if we need to update our break loc.
                    if ((gi.isBreakChar()) ||
                        (breakGI == null||
                        (!breakGI.isBreakChar())) {
                        // Make this the new break if curr char is a
                        // break char or we don't have any break chars
                        // yet, or our current break char is also not
                        // a break char.
                        newBreakGI = gi.copy(newBreakGI);
                        gi.nextChar();
                        if (gi.getChar() != GlyphIterator.ZERO_WIDTH_JOINER) {
                            GlyphIterator tmpGI = breakGI;
                            breakGI = newBreakGI;
                            newBreakGI = tmpGI;
                        }
                    } else {
                        gi.nextChar();
                    }
                    continue;
                }

                // System.out.println("   Brk Adv: " + gi.getAdv());

                // We will now attempt to break the line just
                // after 'gi'.

                // Note we are trying to figure out where the current
                // line is going to be placed (not the next line).  We
                // must wait until we have a potential line break so
                // we know how tall the line is.

                // Get the nomial line advance based on the
                // largest font we encountered on line...
                float lineSize = gi.getMaxAscent()+gi.getMaxDescent();
                float lineBoxHeight;
                if (lineHeightRelative)
                    lineBoxHeight = gi.getMaxFontSize()*lineHeight;
                else
                    lineBoxHeight = lineHeight;
                float halfLeading = (lineBoxHeight-lineSize)/2;

                float ladv = prevDesc + halfLeading + gi.getMaxAscent();
                float newDesc = halfLeading + gi.getMaxDescent();

                dy += ladv;
                float bottomEdge = newDesc;
                if (newDesc < gi.getMaxDescent())
                    bottomEdge = gi.getMaxDescent();

                if ((dy + bottomEdge) > height)  {
                    // The current Line doesn't fit in the
                    // current flow rectangle so we need to
                    // move line to the next flow rect.

                    // System.out.println("Doesn't Fit: " + dy);

                    if (!flowRectsIter.hasNext()) {
                        currentRegion = null;
                        gi = lineGI.copy(gi);
                        break; // No flow rect stop layout here...
                    }

                        // Remember how wide this rectangle is...
                    float oldWidth = width;

                    // Get info for new flow rect.
                    currentRegion = (RegionInfo) flowRectsIter.next();
                    x0     = (float) currentRegion.getX() + leftMargin;
                    y0     = (float) currentRegion.getY();
                    width  = (float)(currentRegion.getWidth() -
                                     (leftMargin+rightMargin));
                    height = (float) currentRegion.getHeight();
                    // start a new alignment offset for this flow rect..
                    verticalAlignOffset = new Point2D.Float(0,0);

                    // New rect so no previous row to consider...
                    dy = firstLine ? mi.getTopMargin() : 0;
                    ;
                    prevDesc  = 0;
                    // previous flows?

                    if (gi.getAdv() > oldWidth) {
                        // need to back up to start of line...
                        gi = lineGI.copy(gi);
                    }
                    continue;
                }

                prevDesc = newDesc + (nextLineMult-1)*lineBoxHeight;
                nextLineMult = 0f;
                updateVerticalAlignOffset(verticalAlignOffset,
                                          currentRegion, dy + bottomEdge);
                lineInfos.add(gi.newLine
                              (new Point2D.Float(x0, y0 + dy), width, partial,
                               verticalAlignOffset));

                // System.out.println("Fit: " + dy);
                x0    -= leftMargin;
                width += leftMargin+rightMargin;

                leftMargin  = mi.getLeftMargin();
                rightMargin = mi.getRightMargin();
                x0    += leftMargin;
                width -= leftMargin+rightMargin;

                firstLine = false;
                // The line fits in the current flow rectangle.
                lineGI  = gi.copy(lineGI);
                breakGI = null;
            }
            dy += prevDesc;

            int idx = gi.getGlyphIndex();
            while(idx <numGlyphs)
                gv.setGlyphVisible(idx++, false);

            if (mi.isFlowRegionBreak()) {
                // Move to next flow region..
                currentRegion = null;
                if (flowRectsIter.hasNext()) {
                    currentRegion = (RegionInfo) flowRectsIter.next();
                    height = (float) currentRegion.getHeight();
                    dy     = mi.getTopMargin();
                    verticalAlignOffset = new Point2D.Float(0,0);
                }
            }
        }

        for (int chunk=0; chunk < acis.length; chunk++) {
            List lineInfos = chunkLineInfos[chunk];
            if (lineInfos == null) continue;

            AttributedCharacterIterator aci = acis[chunk];
            aci.first();
            MarginInfo mi = (MarginInfo)aci.getAttribute(FLOW_PARAGRAPH);
            if (mi == null) {
              continue;
            }
            int justification = mi.getJustification();
           
            GVTGlyphVector gv = gvs[chunk];
            if (gv == null) break;

            GlyphIterator gi = gis[chunk];
           
            layoutChunk(gv, gi.getOrigin(), justification, lineInfos);
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

                TextSpanLayout layout =  run.getLayout();

                if ( layout.hasCharacterIndex(k) ){
                    if ( layout.isOnATextPath() ){
                       
                        GVTGlyphVector vector = layout.getGlyphVector();

                        //alt glyph ?
                        if ( layout.isAltGlyph() ){
                                //get the number of glyph visible here
                            int glyphs = vector.getNumGlyphs();
                            int visibleGlyphs = 0;
                            for( int h=0 ; h < glyphs ; h++ ){
                                if ( vector.isGlyphVisible(h)){
                                    visibleGlyphs++;
                                }
                            }
                                //get the number of character associated
                                //to this run
                            int charactersInRun = 1;
                            while ( layout.hasCharacterIndex( k+1 )){
                                charactersInRun++;
                                k++;
                            }
                            visible += (int)(charactersInRun*visibleGlyphs/glyphs);
                        }
                        else{
                            int lastGlyphIndexFound = -1;
                            do{
                                int glyphIndex = layout.getGlyphIndex(k);
                                ifglyphIndex == -1 ){
                                    //probable missing glyph
                                    if ( layout.isLeftToRight() ){
                                        glyphIndex = 1 + lastGlyphIndexFound;
                                    }
                                    else{
                                        glyphIndex = ( lastGlyphIndexFound == -1)
                                            ? vector.getNumGlyphs()-1
                                            : lastGlyphIndexFound -1;
                                    }
                                }
                                lastGlyphIndexFound = glyphIndex;
                                if ( vector.isGlyphVisible( glyphIndex ) ){
                                    visible++;
                                }
                           
                                k++;
                            }while (k <= lastChar && layout.hasCharacterIndex(k) );
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

           
        if ( info != null ){

            //retrieve the glyphvector containing the glyph
            //for 'charnum'
            GVTGlyphVector it = info.layout.getGlyphVector();

            Shape b;

            if ( info.glyphIndexStart == info.glyphIndexEnd ){
                b = it.getGlyphOutline(info.glyphIndexStart);
            }
            else{
                GeneralPath path = new GeneralPath();
                for( int k = info.glyphIndexStart ;
                     k <= info.glyphIndexEnd;
                     k++){

                    path.append(it.getGlyphOutline(k),false);
                }
                b = path;
            }

            //get the transform for the node
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

        }
    }

    protected Point2D getStartPoint(CharacterInformation info){

        GVTGlyphVector it = info.layout.getGlyphVector();

        Point2D b = it.getGlyphPosition(info.glyphIndexStart);

        Point2D result = new Point2D.Float();
           
        AffineTransform glyphTransform = it.getGlyphTransform(info.glyphIndexStart);

        double x = 0,y = 0;

        //glyph are defined starting at position (0,0)
        if ( glyphTransform != null ){
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

        }
    }

    protected Point2D getEndPoint(CharacterInformation info){

        GVTGlyphVector it = info.layout.getGlyphVector();
       
        Point2D b = it.getGlyphPosition(info.glyphIndexEnd);
       
        Point2D result = new Point2D.Float();
       
        AffineTransform glyphTransform = it.getGlyphTransform(info.glyphIndexEnd);
       
        GVTGlyphMetrics metrics = it.getGlyphMetrics(info.glyphIndexEnd);
       
        double x = 0,y = 0;
           
        x = metrics.getHorizontalAdvance();
           
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

        double angle = 0.0;
        int nbGlyphs = 0;

        if ( info != null ){

            GVTGlyphVector it = info.layout.getGlyphVector();

            for( int k = info.glyphIndexStart ;
                 k <= info.glyphIndexEnd ;
                 k++ ){

                nbGlyphs++;
               
                double glyphAngle = 0.0;

                //the glyph transform contains only a scale and a rotate.
                AffineTransform glyphTransform = it.getGlyphTransform(k);

                if ( glyphTransform != null ){
                    double cosTheta = glyphTransform.getScaleX();
                    double sinTheta = glyphTransform.getShearX();
               
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

                TextSpanLayout layout = run.getLayout();

                if ( layout.hasCharacterIndex(k) ){
                    if ( layout.isOnATextPath() ){
                       
                        GVTGlyphVector vector = layout.getGlyphVector();

                        //alt glyph ?
                        if ( layout.isAltGlyph() ){
                                //get the number of glyph visible here
                            int glyphs = vector.getNumGlyphs();
                            int visibleGlyphs = 0;
                            for( int h=0 ; h < glyphs ; h++ ){
                                if ( vector.isGlyphVisible(h)){
                                    visibleGlyphs++;
                                }
                            }
                                //get the number of character associated
                                //to this run
                            int charactersInRun = 1;
                            while ( layout.hasCharacterIndex( k+1 )){
                                charactersInRun++;
                                k++;
                            }
                            visible += (int)(charactersInRun*visibleGlyphs/glyphs);
                           
                            if ( visible > charnum +1 ){
                                visible = charnum +1;
                            }

                        }
                        else{
                            int lastGlyphIndexFound = -1;
                            do{
                                int glyphIndex = layout.getGlyphIndex(k);
                                ifglyphIndex == -1 ){
                                    //probable missing glyph
                                    if ( layout.isLeftToRight() ){
                                        glyphIndex = 1 + lastGlyphIndexFound;
                                    }
                                    else{
                                        glyphIndex = ( lastGlyphIndexFound == -1)
                                            ? vector.getNumGlyphs()-1
                                            : lastGlyphIndexFound -1;
                                    }
                                }
                                lastGlyphIndexFound = glyphIndex;
                                if ( vector.isGlyphVisible( glyphIndex ) ){
                                    visible++;
                                }
                                k++;
                            }while ((visible < (charnum+1)) && layout.hasCharacterIndex(k) );
                            //got one too far
                            k--;
                        }
                    }
                    else{
                        visible++;
                        while ( (visible < (charnum+1)) && layout.hasCharacterIndex(k+1) ){
                            k++;
                            visible++;
                        }
                    }
                }
            }
        }

        if ( visible != charnum+1 ){
            return null;
        }

        CharacterInformation info = new CharacterInformation();
        info.characterIndex = k-1;
        info.layout = run.getLayout();

        //check is it is a altGlyph
        if ( info.layout.isAltGlyph() ){
           
            //first visible glyph, last visible glyph
            info.glyphIndexStart = 0;
            info.glyphIndexEnd = info.layout.getGlyphCount()-1;
            boolean visibleGlyph = false;
            GVTGlyphVector vector = info.layout.getGlyphVector()
            for( int j = 0 ; j < vector.getNumGlyphs() ; j++ ){
                if ( !visibleGlyph && vector.isGlyphVisible(j) ){
                    info.glyphIndexStart = j;
                    visibleGlyph = true;
                }
                if ( visibleGlyph && (!vector.isGlyphVisible(j)) ){
                    info.glyphIndexEnd = j-1;
                    break;
                }
            }

View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

        while (iter.hasNext()) {
            GlyphLayout gl = (GlyphLayout)iter.next();
            gvs.add(gl.getGlyphVector());
        }

        GVTGlyphVector gv = new MultiGlyphVector(gvs);

        int numGlyphs = gv.getNumGlyphs();
        float[] gp = gv.getGlyphPositions(0, numGlyphs+1, null);

        if (numGlyphs == 0) return;

        // Now pull the line break locations out into an array so
        // I can jump around a bit easier.
        int brIdx = 0;
        int [] brLoc = new int[brLocs.size()+1];
        iter = brLocs.iterator();
        while (iter.hasNext())
            brLoc[brIdx++] = ((Integer)iter.next()).intValue();
        brLoc[brIdx] = aciEnd+1;
        brIdx = 0;
           
        // Now pull the paragraph break locations out into an array so
        // I can jump around a bit easier.
        int pIdx = 0;
        int [] pLoc = new int[pLocs.size()+1];
        iter = pLocs.iterator();
        while (iter.hasNext())
            pLoc[pIdx++] = ((Integer)iter.next()).intValue();
        pLoc[pIdx] = aciEnd+1;
        pIdx = 0;
       

        // Get an iterator for the flow rects.
        Iterator flowRectsIter = flowRects.iterator();
        if (!flowRectsIter.hasNext()) {
            // No place to flow into, hide all glyphs.
            for (int i=0; i>numGlyphs; i++)
                gv.setGlyphVisible(i, false);
            return;
        }

        // Ok get the info for the first rectangle...
        Rectangle2D cRect = (Rectangle2D)flowRectsIter.next();
        float x0     = (float)cRect.getX();
        float y0     = (float)cRect.getY();
        float width  = (float)cRect.getWidth();
        float height = (float)cRect.getHeight();

        // Get the font size at the start of the string...
        float fontSize = 12;
        Float fsFloat = (Float)aci.getAttributes().get(TextAttribute.SIZE);
        if (fsFloat != null) {
            fontSize = fsFloat.floatValue();
        }
        // Figure out where the font size might change again...
        int runLimit  = aci.getRunLimit(TEXT_COMPOUND_DELIMITER);

        // This is our current max font size
        float maxFontSize = fontSize;
        // This is the font size of the last printing char.
        float chFontSize  = fontSize;

        // Information for backing up to word Break (used when
        // wrapping normal lines. 

        // Glyph index of last break char seen (-1 if no break char on line)
        int   wBreakIdx         = -1;
        // The ACI index of last break char seen.
        int   wBreakACI         = -1;
        // Glyph index of last 'printing' char before last space seen
        // (needed to do visual justification on glyph bounds).
        int   wBreakChIdx       = -1;
        // The total advance for line including last non-space char.
        float wBreakAdv         =  0;
        // The total advance for line including spaces at end of line.
        float wBreakAdj         =  0;
        // The font size at last space seen.
        float wBreakFontSize    = fontSize;
        // The runLimit (for fonts) at last space seen.
        int   wBreakRunLimit    = runLimit;
        // The max font size since last space seen (printable chars only). 
        float wBreakMaxFontSize = maxFontSize;

        // Information for backing up to line start.
        // This is needed when we reach the end of a
        // line and realize it doesn't fit in the
        // current rect.
        // Glyph Index of first char on current line.
        int   lBreakIdx       = -1;
        // ACI Index of first char on current line.
        int   lBreakACI       = -1;
        // font size at start of line
        float lBreakFontSize  = fontSize;
        // runLimit (for font size) at start of line.
        int   lBreakRunLimit  = runLimit;
        // The index into the brLoc array at start of line
        int   lBreakBrIdx     = 0;
        // The index into the pLoc array at start of line
        int   lBreakPIdx      = 0;

        // Offset from top of current rect for baseline.
        float dy       = 0;
        // Printing char advance on line so far.
        float adv      = 0;
        // Advance of current char plus any leading non-printing chars.
        float chAdv    = 0;
        // GlyphIndex of last printing char seen
        // (used for full justification on glyph bounds).
        int   lastChar = 0;
        // The descent from previous line we need to incorporate
        float prevDesc = 0;


        // Used to know if we are doing the first glyph after line start.
        int  lineStart     = 0;

        // Per-line information lists.  Used after line breaks have
        // been decided upon.
        List lineStarts    = new LinkedList(); // glyph index of line starts
        List lineLocs      = new LinkedList(); // Point2D of line start.
        List lineAdvs      = new LinkedList(); // Visual width of line.
        List lineAdjs      = new LinkedList(); // x Offset for line
        List lineLastCharW = new LinkedList(); // used in full justification.
        List linePartial   = new LinkedList(); // should line be justified?

        lineStarts.add(new Integer(0));
        int i;
        boolean chIsSpace    = isSpace(ch);
        boolean partial      = false;
        float   nextLineMult = 1.0f;
        float   lineMult     = 1.0f;

        // Let's start looking at glyphs....
        for (i=0; i<numGlyphs; i++) {

            // Update font size for this char if needed.
            if (aciIndex >= runLimit) {
                runLimit = aci.getRunLimit(TEXT_COMPOUND_DELIMITER);
                fsFloat = (Float)aci.getAttributes().get(TextAttribute.SIZE);
                if (fsFloat != null) {
                    fontSize = fsFloat.floatValue();
                } else {
                    fontSize = 12;
                }
                // System.out.println("ACI: " + aciIndex +
                //                    " runLimit: " + runLimit +
                //                    " FS: " + fontSize);
            }

            // Get advance for this glyph...
            float gmAdv = gp[2*i+2] - gp[2*i];

            // Add to the 'Char adv' which includes any non printing
            // chars before this char.
            chAdv += gmAdv;

            // System.out.println("Ch : '" + ch + "' Idx: " + aciIndex);
   
            // If it's a space remeber it as a breaking location but
            // don't check for line break yet (wait till non-space char).
            if (chIsSpace) {
                wBreakIdx      = i;
                wBreakChIdx    = lastChar;
                wBreakACI      = aciIndex;
                wBreakAdv      = adv;
                wBreakAdj      = adv+chAdv;
                wBreakFontSize = fontSize;
                wBreakRunLimit = runLimit;

                // New break loc so incorporate wBreakMaxFontSize
                if (wBreakMaxFontSize > maxFontSize)
                    maxFontSize = wBreakMaxFontSize;

                wBreakMaxFontSize = chFontSize;
            }

            if (!chIsSpace) {
                // Ok we are a printing char so include all the
                // advaces we have collected.
                adv += chAdv;

                // Remember the size of this char...
                chFontSize = fontSize;
            }

            boolean doBreak = false;

            // Don't break at first char in line
            // (otherwise nothing will ever get drawn).
            if (!chIsSpace &&
                (lineStart != i) &&
                (adv > width)
                ) {

                // Better logic for wrap (allow it to squeeze upto 1/2 as
                // much as it would streatch if word wrapped).
                // (((wBreakIdx == -1) && (adv > width)) ||  // no break avail
                //  (adv-width > (width-wBreakAdv)*.5))



                if (wBreakIdx == -1) {
                    // Break in the middle of word.  Back out gmAdv
                    // since it will be used on the next line.
                    wBreakAdv   = adv-gmAdv;
                    wBreakAdj   = adv-gmAdv;
                    wBreakChIdx = lastChar;

                    i--; // reconsider letter (will get inc'd later).

                    // Include max font since last break char in max calc.
                    if (wBreakMaxFontSize > maxFontSize)
                        maxFontSize = wBreakMaxFontSize;
                } else {
                    // We have a break char to back up to.
                    // Reset state to just after breaking chars.
                    i          = wBreakIdx;
                    aciIndex   = wBreakACI;
                    fontSize   = wBreakFontSize;
                    chFontSize = wBreakFontSize;
                    runLimit   = wBreakRunLimit;

                    aciIndex += gv.getCharacterCount(i,i);
                    ch        = aci.setIndex(aciIndex);
                    chIsSpace = isSpace(ch);
                }

                nextLineMult = 1.0f;
                doBreak = true;
                partial = false;
            }

            // Track how many p's and br's we hit here.
            int pCount  = 0;
            int brCount = 0;
            // did we just pass a p or br?
            if ((aciIndex >= pLoc [pIdx]) ||
                (aciIndex >= brLoc[brIdx])) {

                // Count the P's here...
                while (aciIndex >= pLoc[pIdx]) {
                    pIdx++;
                    pCount++;
                    nextLineMult += 1.5;
                }

                // Count the br's here...
                while (aciIndex >= brLoc[brIdx]) {
                    brIdx++;
                    brCount++;
                    nextLineMult += 1.0;
                }

                if (doBreak) {
                    // If we were going to word wrap here anyway
                    // Don't double space...
                    nextLineMult -= 1.0f;
                } else {
                    // We need to specify the break
                    if (chIsSpace) {
                        wBreakAdv   = adv;
                        wBreakAdj   = adv+(chAdv-gmAdv);
                    } else {
                        // If a char with prior spaces then keep
                        // spaces on prev line and char on this line...
                        wBreakAdv   = adv-gmAdv;
                        wBreakAdj   = adv-gmAdv;
                    }

                    wBreakChIdx = lastChar;

                    i--; // reconsider letter.

                    // Include max font since break as max.
                    if (wBreakMaxFontSize > maxFontSize)
                        maxFontSize = wBreakMaxFontSize;
                }
               
                doBreak = true;
                partial = true;
            }


            if (doBreak) {
                // We will now attempt to break the line just
                // before the current char.

                // Note we are trying to figure out where the current
                // line is going to be placed (not the next line).  We
                // must wait until we have a potential line break so
                // we know how tall the line is.

                // Get the nomial line advance based on the
                // largest font we encountered on line...
                float ladv = (maxFontSize*.8f+prevDesc)*1.1f;

                // This is modified by any p's or br's we hit at
                // the end of the last line.
                dy += ladv*lineMult;

                // Remember the effect of p's br's at the end of this line.
                lineMult = nextLineMult;

                // Set ourself up for next line...
                nextLineMult = 0.0f;

                // System.out.println("Break L [" + lineStart + "," + i +
                //                    "] Loc: " + (y0+dy) +
                //                    " adv: " + wBreakAdv +
                //                    " adj: " + wBreakAdj);

                if ((dy + maxFontSize*.2f) <= height) {
                    // The line fits in the current flow rectangle.

                    // System.out.println("Fits: " + (dy + maxFontSize*.2f));


                    // Now remember info about start of next line.
                    // (needed so we can back up if that line doesn't
                    // fit in current rectangle).
                    lBreakIdx      = i+1;
                    lBreakACI      = aciIndex;
                    lBreakFontSize = fontSize;
                    lBreakRunLimit = runLimit;
                    lBreakPIdx     = pIdx;
                    lBreakBrIdx    = brIdx;

                    // Now we tweak line advance to account for
                    // visual bounds of last glyph.
                    Rectangle2D lastCharB = gv.getGlyphVisualBounds
                        (wBreakChIdx).getBounds2D();
                    Point2D     lastCharL = gv.getGlyphPosition
                        (wBreakChIdx);
                    float charW   = (float)
                        (lastCharB.getX()+lastCharB.getWidth()-
                         lastCharL.getX());
                    float charAdv = gp[2*wBreakChIdx+2]-gp[2*wBreakChIdx];
                    wBreakAdv -= charAdv-charW;

                    // Add all the info about the current line to lists.
                    lineLocs.add   (new Point2D.Float(x0, y0+dy));
                    lineAdvs.add   (new Float(wBreakAdv));
                    lineAdjs.add   (new Float(wBreakAdj));
                    lineLastCharW.add (new Float(charW));
                    linePartial.add(new Boolean(partial));

                    // Remember where next line starts.
                    lineStart = i+1;
                    lineStarts.add (new Integer(lineStart));

                    // Remember how far down this line goes into
                    // next line.
                    prevDesc        = maxFontSize*.2f;
                } else {
                    // The current line doesn't fit in the current
                    // flow rectangle so we need to go move line to
                    // the next flow rectangle.

                    // System.out.println("Doesn't Fit: " +
                    //                    (dy + maxFontSize*.2f));


                    if (!flowRectsIter.hasNext())
                        break; // No flow rect stop layout here...

                    // Remember how wide this rectangle is...
                    float oldWidth = width;

                    // Get info for new flow rect.
                    cRect = (Rectangle2D)flowRectsIter.next();
                    x0     = (float)cRect.getX();
                    y0     = (float)cRect.getY();
                    width  = (float)cRect.getWidth();
                    height = (float)cRect.getHeight();

                    // New rect so no previous row to consider...
                    dy        = 0;
                    prevDesc  = 0;
                    lineMult  = 1.0f; // don't pile up lineMults from
                                      // previous flows?

                    if (cRect.getWidth() >= oldWidth) {
                        // new rect is same width or wider so
                        // we can reuse our work on this line.

                        // Just undo anything we added in
                        if (!chIsSpace)
                            adv -= chAdv;

                        chAdv -= gmAdv;
                        // Unadvance p's and br's for this char...
                        pIdx  -= pCount;
                        brIdx -= brCount;
                        continue;
                    }

                    // new rect is smaller so back up to line start
                    // and try with new flow rect.
                    i          = lBreakIdx-1; // loop will inc...
                    aciIndex   = lBreakACI;
                    fontSize   = lBreakFontSize;
                    chFontSize = lBreakFontSize;
                    runLimit   = lBreakRunLimit;
                    pIdx       = lBreakPIdx;
                    brIdx      = lBreakBrIdx;

                    ch       = aci.setIndex(aciIndex);
                    chIsSpace = isSpace(ch);
                }

                // Set fontSize max's to last printing char size.
                maxFontSize       = chFontSize;
                wBreakMaxFontSize = chFontSize;

                // New line so reset line advance info.
                adv=0;
                chAdv=0;
                wBreakIdx = -1;
                continue;
            }

            if (!chIsSpace) {
                // Don't include spaces in max font size calc.
                if (chFontSize > wBreakMaxFontSize) {
                    wBreakMaxFontSize = chFontSize;
                }

                // Remember this as last non-space char...
                lastChar = i;

                // Reset char advance (incorporated into adv above).
                chAdv = 0;
            }

            // Increment everything for ext char...
            aciIndex += gv.getCharacterCount(i,i);
            ch = aci.setIndex(aciIndex);
            chIsSpace = isSpace(ch);
        }

        // Include max font since break char in max.
        if (wBreakMaxFontSize > maxFontSize)
            maxFontSize = wBreakMaxFontSize;
        dy += (maxFontSize*.8f+prevDesc)*1.1f;
        if ((dy + .2f*maxFontSize) >= height) {
            // Last line of text didn't fit...
            i = lineStart;
        } else {
            Rectangle2D lastCharB = gv.getGlyphVisualBounds
                (lastChar).getBounds2D();
            Point2D     lastCharL = gv.getGlyphPosition(lastChar);
            float charW   = (float)
                (lastCharB.getX()+lastCharB.getWidth()-
                 lastCharL.getX());
            float charAdv = gp[2*lastChar+2]-gp[2*lastChar];

            lineStarts.add (new Integer(i));
            lineLocs.add   (new Point2D.Float(x0, y0+dy));
            lineAdvs.add   (new Float(adv-(charAdv-charW)));
            lineAdjs.add   (new Float(adv+chAdv));
            lineLastCharW.add (new Float(charW));
            linePartial.add(new Boolean(true));
        }

        // ignore any glyphs i+  (didn't fit in rects.) 
        for (int j=i; j<numGlyphs; j++)
            gv.setGlyphVisible(j, false);

        // Limit ourselves to i glyphs...
        numGlyphs = i;


        Iterator lStartIter    =lineStarts.iterator();
        Iterator lLocIter      =lineLocs.iterator();
        Iterator lAdvIter      =lineAdvs.iterator();
        Iterator lAdjIter      =lineAdjs.iterator();
        Iterator lLastCharWIter=lineLastCharW.iterator();
        Iterator lPartIter      =linePartial.iterator();

        lineStart             = ((Integer)lStartIter.next()).intValue();
        Point2D.Float lineLoc = null;
        float         lineAdv = 0;
        float         lineAdj = 0;

        float xOrig=gp[0];
        float yOrig=gp[1];

        float xScale=1;
        float xAdj=0;
        float charW;

        // This loop goes through and puts glyphs where they belong
        // based on info collected in first trip through glyphVector...
        i =0;
        for (; i<numGlyphs; i++) {
            if (i == lineStart) {
                // Always comes through here on first char...

                // Update offset for new line based on last line length
                xOrig += lineAdj;

                // Get new values for everything...
                lineStart = ((Integer)lStartIter.next()).intValue();
                lineLoc   = (Point2D.Float)lLocIter.next();
                lineAdv   = (  (Float)lAdvIter.next())  .floatValue();
                lineAdj   = (  (Float)lAdjIter.next())  .floatValue();
                charW     = (  (Float)lLastCharWIter.next())  .floatValue();
                partial   = ((Boolean)lPartIter.next()) .booleanValue();

                xAdj = 0;
                xScale = 1;
                // Recalc justification info.
                switch (justification) {
                case 0: default: break;                  // Left
                case 1: xAdj = (width-lineAdv)/2; break; // Center
                case 2: xAdj =  width-lineAdv;    break; // Right
                case 3:                                  // Full
                    if ((!partial) && (lineStart != i+1)) {
                        // More than one char on line...
                        // Scale char spacing to fill line.
                        xScale = (width-charW)/(lineAdv-charW);
                    }
                    break;
                }
            }
            float x = lineLoc.x + (gp[2*i-xOrig)*xScale+xAdj;
            float y = lineLoc.y + (gp[2*i+1]-yOrig);
            gv.setGlyphPosition(i, new Point2D.Float(x, y));
        }

        float x = lineLoc.x + (gp[2*i-xOrig)*xScale+xAdj;
        float y = lineLoc.y + (gp[2*i+1]-yOrig);
        gv.setGlyphPosition(i, new Point2D.Float(x, y));
    }
View Full Code Here

Examples of org.apache.batik.gvt.font.GVTGlyphVector

            Iterator iter = layouts.iterator();
            while (iter.hasNext()) {
                GlyphLayout gl = (GlyphLayout)iter.next();
                gvl.add(gl.getGlyphVector());
            }
            GVTGlyphVector gv = new MultiGlyphVector(gvl);
            gvs[chunk] = gv;
            int numGlyphs = gv.getNumGlyphs();

            // System.out.println("Glyphs: " + numGlyphs);

            aci.first();
            MarginInfo mi = (MarginInfo)aci.getAttribute(FLOW_PARAGRAPH);
            if (mi == null) {
              continue;
            }
            justification = mi.getJustification();

            if (cRect == null) {
                for(int idx=0; idx <numGlyphs; idx++)
                    gv.setGlyphVisible(idx, false);
                continue;
            }

            float inc = ((prevBotMargin > mi.getTopMargin())
                         ? prevBotMargin : mi.getTopMargin());
            if (dy + inc <= height) {
                dy += inc;
            } else {
                // Move to next flow region..
                if (!flowRectsIter.hasNext()) {
                    cRect = null;
                    break; // No flow rect stop layout here...
                }

                cRect = (Rectangle2D)flowRectsIter.next();
                height = (float)cRect.getHeight();

                            // New rect so no previous row to consider...
                dy        = mi.getTopMargin();
            }
            prevBotMargin = mi.getBottomMargin();

            float leftMargin = mi.getFirstLineLeftMargin();
            float rightMargin = mi.getFirstLineRightMargin();

            x0    = (float)cRect.getX() + leftMargin;
            y0    = (float)cRect.getY();
            width = (float)(cRect.getWidth() - (leftMargin+rightMargin));
            height = (float)cRect.getHeight();
           
            List lineInfos = new LinkedList();

            float prevDesc = 0.0f;
            GlyphIterator gi = new GlyphIterator(aci, gv);
            GlyphIterator breakGI  = null, newBreakGI = null;

            if (!gi.done() && !gi.isPrinting()) {
              // This will place any preceeding whitespace on an imaginary
              // line that preceeds the real first line of the paragraph.
              lineInfos.add(gi.newLine
                            (new Point2D.Float(x0, y0+dy),
                             width, true));
            }


            GlyphIterator lineGI   =  gi.copy();
            boolean firstLine = true;
            while (!gi.done()) {
                boolean doBreak = false;
                boolean partial = false;

                if (gi.isPrinting() && (gi.getAdv() > width)) {
                    if (breakGI == null) {
                        // first char on line didn't fit.
                        // move to next flow rect.
                        if (!flowRectsIter.hasNext()) {
                            cRect = null;
                            gi = lineGI.copy(gi);
                            break; // No flow rect stop layout here...
                        }

                        cRect = (Rectangle2D)flowRectsIter.next();
                        x0    = (float) cRect.getX() + leftMargin;
                        y0    = (float) cRect.getY();
                        width = (float)(cRect.getWidth() -
                                        (leftMargin+rightMargin));
                        height = (float)cRect.getHeight();

                        // New rect so no previous row to consider...
                        dy        = firstLine?mi.getTopMargin():0; ;
                        prevDesc  = 0;
                        gi = lineGI.copy(gi);
                        continue;
                    }

                    gi = breakGI.copy(gi)// Back up to break loc...

                    nextLineMult = 1;
                    doBreak = true;
                    partial = false;
                } else if (gi.isLastChar()) {
                    nextLineMult = 1;
                    doBreak = true;
                    partial = true;
                }
                int lnBreaks = gi.getLineBreaks();
                if (lnBreaks != 0) {
                    if (doBreak)
                        nextLineMult -= 1;
                    nextLineMult += lnBreaks;
                    doBreak = true;
                    partial = true;
                }

                if (!doBreak) {
                    // System.out.println("No Brk Adv: " + gi.getAdv());
                    // We don't need to break the line because of this glyph
                    // So we just check if we need to update our break loc.
                    if ((gi.isBreakChar()) ||
                        (breakGI == null||
                        (!breakGI.isBreakChar())) {
                        // Make this the new break if curr char is a
                        // break char or we don't have any break chars
                        // yet, or our current break char is also not
                        // a break char.
                        newBreakGI = gi.copy(newBreakGI);
                        gi.nextChar();
                        if (gi.getChar() != GlyphIterator.ZERO_WIDTH_JOINER) {
                            GlyphIterator tmpGI = breakGI;
                            breakGI = newBreakGI;
                            newBreakGI = tmpGI;
                        }
                    } else {
                        gi.nextChar();
                    }
                    continue;
                }

                // System.out.println("   Brk Adv: " + gi.getAdv());

                // We will now attempt to break the line just
                // after 'gi'.

                // Note we are trying to figure out where the current
                // line is going to be placed (not the next line).  We
                // must wait until we have a potential line break so
                // we know how tall the line is.

                // Get the nomial line advance based on the
                // largest font we encountered on line...
                float lineSize = gi.getMaxAscent()+gi.getMaxDescent();
                float lineBoxHeight;
                if (lineHeightRelative)
                    lineBoxHeight = gi.getMaxFontSize()*lineHeight;
                else
                    lineBoxHeight = lineHeight;
                float halfLeading = (lineBoxHeight-lineSize)/2;

                float ladv = prevDesc + halfLeading + gi.getMaxAscent();
                float newDesc = halfLeading + gi.getMaxDescent();

                dy += ladv;
                float bottomEdge = newDesc;
                if (newDesc < gi.getMaxDescent())
                    bottomEdge = gi.getMaxDescent();

                if ((dy + bottomEdge) > height)  {
                    // The current Line doesn't fit in the
                    // current flow rectangle so we need to
                    // move line to the next flow rect.

                    // System.out.println("Doesn't Fit: " + dy);

                    if (!flowRectsIter.hasNext()) {
                        cRect = null;
                        gi = lineGI.copy(gi);
                        break; // No flow rect stop layout here...
                    }

                        // Remember how wide this rectangle is...
                    float oldWidth = width;

                    // Get info for new flow rect.
                    cRect = (Rectangle2D)flowRectsIter.next();
                    x0    = (float) cRect.getX() + leftMargin;
                    y0    = (float) cRect.getY();
                    width = (float)(cRect.getWidth() -
                                    (leftMargin+rightMargin));
                    height = (float)cRect.getHeight();

                    // New rect so no previous row to consider...
                    dy        = firstLine?mi.getTopMargin():0; ;
                    prevDesc  = 0;
                    // previous flows?

                    if (gi.getAdv() > oldWidth) {
                        // need to back up to start of line...
                        gi = lineGI.copy(gi);
                    }
                    continue;
                }

                prevDesc = newDesc + (nextLineMult-1)*lineBoxHeight;
                nextLineMult = 0f;
                lineInfos.add(gi.newLine
                              (new Point2D.Float(x0, y0+dy), width, partial));

                // System.out.println("Fit: " + dy);
                x0    -= leftMargin;
                width += leftMargin+rightMargin;

                leftMargin  = mi.getLeftMargin();
                rightMargin = mi.getRightMargin();
                x0    += leftMargin;
                width -= leftMargin+rightMargin;

                firstLine = false;
                // The line fits in the current flow rectangle.
                lineGI  = gi.copy(lineGI);
                breakGI = null;
            }
            dy += prevDesc;

            int idx = gi.getGlyphIndex();
            while(idx <numGlyphs)
                gv.setGlyphVisible(idx++, false);

            layoutChunk(aci, gv, gi.getOrigin(), justification, lineInfos);

            if (mi.isFlowRegionBreak()) {
                // Move to next flow region..
View Full Code Here
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.