/*
 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.swing.text;

import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Component;
import java.awt.Container;
import java.awt.font.FontRenderContext;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicReference;

import javax.swing.BorderFactory;
import javax.swing.CellRendererPane;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JEditorPane;
import javax.swing.JViewport;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.Document;
import javax.swing.text.EditorKit;
import javax.swing.text.AbstractDocument;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTML;

import sun.font.FontDesignMetrics;

import sun.swing.text.html.FrameEditorPaneTag;

/**
 * An implementation of {@code Printable} to print {@code JTextComponent} with
 * the header and footer.
 *
 * <h1>
 * WARNING: this class is to be used in
 * javax.swing.text.JTextComponent only.
 * </h1>
 *
 * <p>
 * The implementation creates a new {@code JTextComponent} ({@code printShell})
 * to print the content using the {@code Document}, {@code EditorKit} and
 * rendering-affecting properties from the original {@code JTextComponent}.
 *
 * <p>
 * {@code printShell} is laid out on the first {@code print} invocation.
 *
 * <p>
 * This class can be used on any thread. Part of the implementation is executed
 * on the EDT though.
 *
 * @author Igor Kushnirskiy
 *
 * @since 1.6
 */
public class TextComponentPrintable implements CountingPrintable {


    private static final int LIST_SIZE = 1000;

    private boolean isLayouted = false;

    /*
     * The text component to print.
     */
    private final JTextComponent textComponentToPrint;

    /*
     * The FontRenderContext to layout and print with
     */
    private final AtomicReference<FontRenderContext> frc =
        new AtomicReference<FontRenderContext>(null);

    /**
     * Special text component used to print to the printer.
     */
    private final JTextComponent printShell;

    private final MessageFormat headerFormat;
    private final MessageFormat footerFormat;

    private static final float HEADER_FONT_SIZE = 18.0f;
    private static final float FOOTER_FONT_SIZE = 12.0f;

    private final Font headerFont;
    private final Font footerFont;

    /**
     * stores metrics for the unhandled rows. The only metrics we need are
     * yStart and yEnd when row is handled by updatePagesMetrics it is removed
     * from the list. Thus the head of the list is the fist row to handle.
     *
     * sorted
     */
    private final List<IntegerSegment> rowsMetrics;

    /**
     * thread-safe list for storing pages metrics. The only metrics we need are
     * yStart and yEnd.
     * It has to be thread-safe since metrics are calculated on
     * the printing thread and accessed on the EDT thread.
     *
     * sorted
     */
    private final List<IntegerSegment> pagesMetrics;

    /**
     * Returns {@code TextComponentPrintable} to print {@code textComponent}.
     *
     * @param textComponent {@code JTextComponent} to print
     * @param headerFormat the page header, or {@code null} for none
     * @param footerFormat the page footer, or {@code null} for none
     * @return {@code TextComponentPrintable} to print {@code textComponent}
     */
    public static Printable getPrintable(final JTextComponent textComponent,
            final MessageFormat headerFormat,
            final MessageFormat footerFormat) {

        if (textComponent instanceof JEditorPane
                && isFrameSetDocument(textComponent.getDocument())) {
            //for document with frames we create one printable per
            //frame and merge them with the CompoundPrintable.
            List<JEditorPane> frames = getFrames((JEditorPane) textComponent);
            List<CountingPrintable> printables =
                new ArrayList<CountingPrintable>();
            for (JEditorPane frame : frames) {
                printables.add((CountingPrintable)
                               getPrintable(frame, headerFormat, footerFormat));
            }
            return new CompoundPrintable(printables);
        } else {
            return new TextComponentPrintable(textComponent,
               headerFormat, footerFormat);
        }
    }

    /**
     * Checks whether the document has frames. Only HTMLDocument might
     * have frames.
     *
     * @param document the {@code Document} to check
     * @return {@code true} if the {@code document} has frames
     */
    private static boolean isFrameSetDocument(final Document document) {
        boolean ret = false;
        if (document instanceof HTMLDocument) {
            HTMLDocument htmlDocument = (HTMLDocument)document;
            if (htmlDocument.getIterator(HTML.Tag.FRAME).isValid()) {
                ret = true;
            }
        }
        return ret;
    }


    /**
     * Returns frames under the {@code editor}.
     * The frames are created if necessary.
     *
     * @param editor the {@JEditorPane} to find the frames for
     * @return list of all frames
     */
    private static List<JEditorPane> getFrames(final JEditorPane editor) {
        List<JEditorPane> list = new ArrayList<JEditorPane>();
        getFrames(editor, list);
        if (list.size() == 0) {
            //the frames have not been created yet.
            //let's trigger the frames creation.
            createFrames(editor);
            getFrames(editor, list);
        }
        return list;
    }

    /**
     * Adds all {@code JEditorPanes} under {@code container} tagged by {@code
     * FrameEditorPaneTag} to the {@code list}. It adds only top
     * level {@code JEditorPanes}.  For instance if there is a frame
     * inside the frame it will return the top frame only.
     *
     * @param c the container to find all frames under
     * @param list {@code List} to append the results too
     */
    private static void getFrames(final Container container, List<JEditorPane> list) {
        for (Component c : container.getComponents()) {
            if (c instanceof FrameEditorPaneTag
                && c instanceof JEditorPane ) { //it should be always JEditorPane
                list.add((JEditorPane) c);
            } else {
                if (c instanceof Container) {
                    getFrames((Container) c, list);
                }
            }
        }
    }

    /**
     * Triggers the frames creation for {@code JEditorPane}
     *
     * @param editor the {@code JEditorPane} to create frames for
     */
    private static void createFrames(final JEditorPane editor) {
        Runnable doCreateFrames =
            new Runnable() {
                public void run() {
                    final int WIDTH = 500;
                    final int HEIGHT = 500;
                    CellRendererPane rendererPane = new CellRendererPane();
                    rendererPane.add(editor);
                    //the values do not matter
                    //we only need to get frames created
                    rendererPane.setSize(WIDTH, HEIGHT);
                };
            };
        if (SwingUtilities.isEventDispatchThread()) {
            doCreateFrames.run();
        } else {
            try {
                SwingUtilities.invokeAndWait(doCreateFrames);
            } catch (Exception e) {
                if (e instanceof RuntimeException) {
                    throw (RuntimeException) e;
                } else {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * Constructs  {@code TextComponentPrintable} to print {@code JTextComponent}
     * {@code textComponent} with {@code headerFormat} and {@code footerFormat}.
     *
     * @param textComponent {@code JTextComponent} to print
     * @param headerFormat the page header or {@code null} for none
     * @param footerFormat the page footer or {@code null} for none
     */
    private TextComponentPrintable(JTextComponent textComponent,
            MessageFormat headerFormat,
            MessageFormat footerFormat) {
        this.textComponentToPrint = textComponent;
        this.headerFormat = headerFormat;
        this.footerFormat = footerFormat;
        headerFont = textComponent.getFont().deriveFont(Font.BOLD,
            HEADER_FONT_SIZE);
        footerFont = textComponent.getFont().deriveFont(Font.PLAIN,
            FOOTER_FONT_SIZE);
        this.pagesMetrics =
            Collections.synchronizedList(new ArrayList<IntegerSegment>());
        this.rowsMetrics = new ArrayList<IntegerSegment>(LIST_SIZE);
        this.printShell = createPrintShell(textComponent);
    }


    /**
     * creates a printShell.
     * It creates closest text component to {@code textComponent}
     * which uses {@code frc} from the {@code TextComponentPrintable}
     * for the {@code getFontMetrics} method.
     *
     * @param textComponent {@code JTextComponent} to create a
     *        printShell for
     * @return the print shell
     */
    private JTextComponent createPrintShell(final JTextComponent textComponent) {
        if (SwingUtilities.isEventDispatchThread()) {
            return createPrintShellOnEDT(textComponent);
        } else {
            FutureTask<JTextComponent> futureCreateShell =
                new FutureTask<JTextComponent>(
                    new Callable<JTextComponent>() {
                        public JTextComponent call() throws Exception {
                            return createPrintShellOnEDT(textComponent);
                        }
                    });
            SwingUtilities.invokeLater(futureCreateShell);
            try {
                return futureCreateShell.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                Throwable cause = e.getCause();
                if (cause instanceof Error) {
                    throw (Error) cause;
                }
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                }
                throw new AssertionError(cause);
            }
        }
    }
    private JTextComponent createPrintShellOnEDT(final JTextComponent textComponent) {
        assert SwingUtilities.isEventDispatchThread();

        JTextComponent ret = null;
        if (textComponent instanceof JTextField) {
            ret =
                new JTextField() {
                    {
                        setHorizontalAlignment(
                            ((JTextField) textComponent).getHorizontalAlignment());
                    }
                    @Override
                    public FontMetrics getFontMetrics(Font font) {
                        return (frc.get() == null)
                            ? super.getFontMetrics(font)
                            : FontDesignMetrics.getMetrics(font, frc.get());
                    }
                };
        } else if (textComponent instanceof JTextArea) {
            ret =
                new JTextArea() {
                    {
                        JTextArea textArea = (JTextArea) textComponent;
                        setLineWrap(textArea.getLineWrap());
                        setWrapStyleWord(textArea.getWrapStyleWord());
                        setTabSize(textArea.getTabSize());
                    }
                    @Override
                    public FontMetrics getFontMetrics(Font font) {
                        return (frc.get() == null)
                            ? super.getFontMetrics(font)
                            : FontDesignMetrics.getMetrics(font, frc.get());
                    }
                };
        } else if (textComponent instanceof JTextPane) {
            ret =
                new JTextPane() {
                    @Override
                    public FontMetrics getFontMetrics(Font font) {
                        return (frc.get() == null)
                            ? super.getFontMetrics(font)
                            : FontDesignMetrics.getMetrics(font, frc.get());
                    }
                    @Override
                    public EditorKit getEditorKit() {
                        if (getDocument() == textComponent.getDocument()) {
                            return ((JTextPane) textComponent).getEditorKit();
                        } else {
                            return super.getEditorKit();
                        }
                    }
                };
        } else if (textComponent instanceof JEditorPane) {
            ret =
                new JEditorPane() {
                    @Override
                    public FontMetrics getFontMetrics(Font font) {
                        return (frc.get() == null)
                            ? super.getFontMetrics(font)
                            : FontDesignMetrics.getMetrics(font, frc.get());
                    }
                    @Override
                    public EditorKit getEditorKit() {
                        if (getDocument() == textComponent.getDocument()) {
                            return ((JEditorPane) textComponent).getEditorKit();
                        } else {
                            return super.getEditorKit();
                        }
                    }
                };
        }
        //want to occupy the whole width and height by text
        ret.setBorder(null);

        //set properties from the component to print
        ret.setOpaque(textComponent.isOpaque());
        ret.setEditable(textComponent.isEditable());
        ret.setEnabled(textComponent.isEnabled());
        ret.setFont(textComponent.getFont());
        ret.setBackground(textComponent.getBackground());
        ret.setForeground(textComponent.getForeground());
        ret.setComponentOrientation(
            textComponent.getComponentOrientation());

        if (ret instanceof JEditorPane) {
            ret.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES,
                textComponent.getClientProperty(
                JEditorPane.HONOR_DISPLAY_PROPERTIES));
            ret.putClientProperty(JEditorPane.W3C_LENGTH_UNITS,
                textComponent.getClientProperty(JEditorPane.W3C_LENGTH_UNITS));
            ret.putClientProperty("charset",
                textComponent.getClientProperty("charset"));
        }
        ret.setDocument(textComponent.getDocument());
        return ret;
    }




    /**
     * Returns the number of pages in this printable.
     * <p>
     * This number is defined only after {@code print} returns NO_SUCH_PAGE.
     *
     * @return the number of pages.
     */
    public int getNumberOfPages() {
        return pagesMetrics.size();
    }

    /**
     * See Printable.print for the API description.
     *
     * There are two parts in the implementation.
     * First part (print) is to be called on the printing thread.
     * Second part (printOnEDT) is to be called on the EDT only.
     *
     * print triggers printOnEDT
     */
    public int print(final Graphics graphics,
            final PageFormat pf,
            final int pageIndex) throws PrinterException {
        if (!isLayouted) {
            if (graphics instanceof Graphics2D) {
                frc.set(((Graphics2D)graphics).getFontRenderContext());
            }
            layout((int)Math.floor(pf.getImageableWidth()));
            calculateRowsMetrics();
        }
        int ret;
        if (!SwingUtilities.isEventDispatchThread()) {
            Callable<Integer> doPrintOnEDT = new Callable<Integer>() {
                public Integer call() throws Exception {
                    return printOnEDT(graphics, pf, pageIndex);
                }
            };
            FutureTask<Integer> futurePrintOnEDT =
                new FutureTask<Integer>(doPrintOnEDT);
            SwingUtilities.invokeLater(futurePrintOnEDT);
            try {
                ret = futurePrintOnEDT.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                Throwable cause = e.getCause();
                if (cause instanceof PrinterException) {
                    throw (PrinterException)cause;
                } else if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    throw new RuntimeException(cause);
                }
            }
        } else {
            ret = printOnEDT(graphics, pf, pageIndex);
        }
        return ret;
    }


    /**
     * The EDT part of the print method.
     *
     * This method is to be called on the EDT only. Layout should be done before
     * calling this method.
     */
    private int printOnEDT(final Graphics graphics,
            final PageFormat pf,
            final int pageIndex) throws PrinterException {
        assert SwingUtilities.isEventDispatchThread();
        Border border = BorderFactory.createEmptyBorder();
        //handle header and footer
        if (headerFormat != null || footerFormat != null) {
            //Printable page enumeration is 0 base. We need 1 based.
            Object[] formatArg = new Object[]{Integer.valueOf(pageIndex + 1)};
            if (headerFormat != null) {
                border = new TitledBorder(border,
                    headerFormat.format(formatArg),
                    TitledBorder.CENTER, TitledBorder.ABOVE_TOP,
                    headerFont, printShell.getForeground());
            }
            if (footerFormat != null) {
                border = new TitledBorder(border,
                    footerFormat.format(formatArg),
                    TitledBorder.CENTER, TitledBorder.BELOW_BOTTOM,
                    footerFont, printShell.getForeground());
            }
        }
        Insets borderInsets = border.getBorderInsets(printShell);
        updatePagesMetrics(pageIndex,
            (int)Math.floor(pf.getImageableHeight()) - borderInsets.top
                           - borderInsets.bottom);

        if (pagesMetrics.size() <= pageIndex) {
            return NO_SUCH_PAGE;
        }

        Graphics2D g2d = (Graphics2D)graphics.create();

        g2d.translate(pf.getImageableX(), pf.getImageableY());
        border.paintBorder(printShell, g2d, 0, 0,
            (int)Math.floor(pf.getImageableWidth()),
            (int)Math.floor(pf.getImageableHeight()));

        g2d.translate(0, borderInsets.top);
        //want to clip only vertically
        Rectangle clip = new Rectangle(0, 0,
            (int) pf.getWidth(),
            pagesMetrics.get(pageIndex).end
                - pagesMetrics.get(pageIndex).start + 1);

        g2d.clip(clip);
        int xStart = 0;
        if (ComponentOrientation.RIGHT_TO_LEFT ==
                printShell.getComponentOrientation()) {
            xStart = (int) pf.getImageableWidth() - printShell.getWidth();
        }
        g2d.translate(xStart, - pagesMetrics.get(pageIndex).start);
        printShell.print(g2d);

        g2d.dispose();

        return Printable.PAGE_EXISTS;
    }


    private boolean needReadLock = false;

    /**
     * Tries to release document's readlock
     *
     * Note: Not to be called on the EDT.
     */
    private void releaseReadLock() {
        assert ! SwingUtilities.isEventDispatchThread();
        Document document = textComponentToPrint.getDocument();
        if (document instanceof AbstractDocument) {
            try {
                ((AbstractDocument) document).readUnlock();
                needReadLock = true;
            } catch (Error ignore) {
                // readUnlock() might throw StateInvariantError
            }
        }
    }


    /**
     * Tries to acquire document's readLock if it was released
     * in releaseReadLock() method.
     *
     * Note: Not to be called on the EDT.
     */
    private void acquireReadLock() {
        assert ! SwingUtilities.isEventDispatchThread();
        if (needReadLock) {
            try {
                /*
                 * wait until all the EDT events are processed
                 * some of the document changes are asynchronous
                 * we need to make sure we get the lock after those changes
                 */
                SwingUtilities.invokeAndWait(
                    new Runnable() {
                        public void run() {
                        }
                    });
            } catch (InterruptedException ignore) {
            } catch (java.lang.reflect.InvocationTargetException ignore) {
            }
            Document document = textComponentToPrint.getDocument();
            ((AbstractDocument) document).readLock();
            needReadLock = false;
        }
    }

    /**
     * Prepares {@code printShell} for printing.
     *
     * Sets properties from the component to print.
     * Sets width and FontRenderContext.
     *
     * Triggers Views creation for the printShell.
     *
     * There are two parts in the implementation.
     * First part (layout) is to be called on the printing thread.
     * Second part (layoutOnEDT) is to be called on the EDT only.
     *
     * {@code layout} triggers {@code layoutOnEDT}.
     *
     * @param width width to layout the text for
     */
    private void layout(final int width) {
        if (!SwingUtilities.isEventDispatchThread()) {
            Callable<Object> doLayoutOnEDT = new Callable<Object>() {
                public Object call() throws Exception {
                    layoutOnEDT(width);
                    return null;
                }
            };
            FutureTask<Object> futureLayoutOnEDT = new FutureTask<Object>(
                doLayoutOnEDT);

            /*
             * We need to release document's readlock while printShell is
             * initializing
             */
            releaseReadLock();
            SwingUtilities.invokeLater(futureLayoutOnEDT);
            try {
                futureLayoutOnEDT.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                Throwable cause = e.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                } else {
                    throw new RuntimeException(cause);
                }
            } finally {
                acquireReadLock();
            }
        } else {
            layoutOnEDT(width);
        }

        isLayouted = true;
    }

    /**
     * The EDT part of layout method.
     *
     * This method is to be called on the EDT only.
     */
    private void layoutOnEDT(final int width) {
        assert SwingUtilities.isEventDispatchThread();
        //need to have big value but smaller than MAX_VALUE otherwise
        //printing goes south due to overflow somewhere
        final int HUGE_INTEGER = Integer.MAX_VALUE - 1000;

        CellRendererPane rendererPane = new CellRendererPane();

        //need to use JViewport since text is layouted to the viewPort width
        //otherwise it will be layouted to the maximum text width
        JViewport viewport = new JViewport();
        viewport.setBorder(null);
        Dimension size = new Dimension(width, HUGE_INTEGER);

        //JTextField is a special case
        //it layouts text in the middle by Y
        if (printShell instanceof JTextField) {
            size =
                new Dimension(size.width, printShell.getPreferredSize().height);
        }
        printShell.setSize(size);
        viewport.setComponentOrientation(printShell.getComponentOrientation());
        viewport.setSize(size);
        viewport.add(printShell);
        rendererPane.add(viewport);
    }

    /**
     * Calculates pageMetrics for the pages up to the {@code pageIndex} using
     * {@code rowsMetrics}.
     * Metrics are stored in the {@code pagesMetrics}.
     *
     * @param pageIndex the page to update the metrics for
     * @param pageHeight the page height
     */
    private void updatePagesMetrics(final int pageIndex, final int pageHeight) {
        while (pageIndex >= pagesMetrics.size() && !rowsMetrics.isEmpty()) {
            // add one page to the pageMetrics
            int lastPage = pagesMetrics.size() - 1;
            int pageStart = (lastPage >= 0)
               ? pagesMetrics.get(lastPage).end + 1
               : 0;
            int rowIndex;
            for (rowIndex = 0;
                   rowIndex < rowsMetrics.size()
                   && (rowsMetrics.get(rowIndex).end - pageStart + 1)
                     <= pageHeight;
                   rowIndex++) {
            }
            if (rowIndex == 0) {
                // can not fit a single row
                // need to split
                pagesMetrics.add(
                    new IntegerSegment(pageStart, pageStart + pageHeight - 1));
            } else {
                rowIndex--;
                pagesMetrics.add(new IntegerSegment(pageStart,
                    rowsMetrics.get(rowIndex).end));
                for (int i = 0; i <= rowIndex; i++) {
                    rowsMetrics.remove(0);
                }
            }
        }
    }

    /**
     * Calculates rowsMetrics for the document. The result is stored
     * in the {@code rowsMetrics}.
     *
     * Two steps process.
     * First step is to find yStart and yEnd for the every document position.
     * Second step is to merge all intersected segments ( [yStart, yEnd] ).
     */
    private void calculateRowsMetrics() {
        final int documentLength = printShell.getDocument().getLength();
        List<IntegerSegment> documentMetrics = new ArrayList<IntegerSegment>(LIST_SIZE);
        Rectangle rect;
        for (int i = 0, previousY = -1, previousHeight = -1; i < documentLength;
                 i++) {
            try {
                rect = printShell.modelToView(i);
                if (rect != null) {
                    int y = (int) rect.getY();
                    int height = (int) rect.getHeight();
                    if (height != 0
                            && (y != previousY || height != previousHeight)) {
                        /*
                         * we do not store the same value as previous. in our
                         * documents it is often for consequent positons to have
                         * the same modelToView y and height.
                         */
                        previousY = y;
                        previousHeight = height;
                        documentMetrics.add(new IntegerSegment(y, y + height - 1));
                    }
                }
            } catch (BadLocationException e) {
                assert false;
            }
        }
        /*
         * Merge all intersected segments.
         */
        Collections.sort(documentMetrics);
        int yStart = Integer.MIN_VALUE;
        int yEnd = Integer.MIN_VALUE;
        for (IntegerSegment segment : documentMetrics) {
            if (yEnd < segment.start) {
                if (yEnd != Integer.MIN_VALUE) {
                    rowsMetrics.add(new IntegerSegment(yStart, yEnd));
                }
                yStart = segment.start;
                yEnd = segment.end;
            } else {
                yEnd = segment.end;
            }
        }
        if (yEnd != Integer.MIN_VALUE) {
            rowsMetrics.add(new IntegerSegment(yStart, yEnd));
        }
    }

    /**
     *  Class to represent segment of integers.
     *  we do not call it Segment to avoid confusion with
     *  javax.swing.text.Segment
     */
    private static class IntegerSegment implements Comparable<IntegerSegment> {
        final int start;
        final int end;

        IntegerSegment(int start, int end) {
            this.start = start;
            this.end = end;
        }

        public int compareTo(IntegerSegment object) {
            int startsDelta = start - object.start;
            return (startsDelta != 0) ? startsDelta : end - object.end;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof IntegerSegment) {
                return compareTo((IntegerSegment) obj) == 0;
            } else {
                return false;
            }
        }

        @Override
        public int hashCode() {
            // from the "Effective Java: Programming Language Guide"
            int result = 17;
            result = 37 * result + start;
            result = 37 * result + end;
            return result;
        }

        @Override
        public String toString() {
            return "IntegerSegment [" + start + ", " + end + "]";
        }
    }
}
