Search in sources :

Example 16 with LineBreakMeasurer

use of java.awt.font.LineBreakMeasurer in project adempiere by adempiere.

the class TableElement method calculateSize.

/**************************************************************************
	 * 	Layout and Calculate Size.
	 * 	Set p_width & p_height
	 * 	@return true if calculated
	 */
protected boolean calculateSize() {
    if (p_sizeCalculated)
        return true;
    p_width = 0;
    //	reset
    m_printRows = new ArrayList<ArrayList<ArrayList<Object>>>(m_data.length);
    //	Max Column Width = 50% of available width (used if maxWidth not set)
    float dynMxColumnWidth = m_firstPage.width / 2;
    //	Width caolculation
    int rows = m_data.length;
    int cols = m_columnHeader.length;
    //	Data Sizes and Header Sizes
    Dimension2DImpl[][] dataSizes = new Dimension2DImpl[rows][cols];
    Dimension2DImpl[] headerSizes = new Dimension2DImpl[cols];
    FontRenderContext frc = new FontRenderContext(null, true, true);
    //	data columns - rows
    for (int dataCol = 0; dataCol < cols; dataCol++) {
        int col = dataCol;
        //	Print below existing column
        if (m_additionalLines.containsKey(new Integer(dataCol))) {
            col = ((Integer) m_additionalLines.get(new Integer(dataCol))).intValue();
            log.finest("DataColumn=" + dataCol + ", BelowColumn=" + col);
        }
        float colWidth = 0;
        for (int row = 0; row < rows; row++) {
            Object dataItem = m_data[row][dataCol];
            if (dataItem == null) {
                dataSizes[row][dataCol] = new Dimension2DImpl();
                continue;
            }
            String string = dataItem.toString();
            if (string.length() == 0) {
                dataSizes[row][dataCol] = new Dimension2DImpl();
                continue;
            }
            Font font = getFont(row, dataCol);
            //	Print below existing column = (col != dataCol)
            addPrintLines(row, col, dataItem);
            //	don't print
            dataSizes[row][dataCol] = new Dimension2DImpl();
            if (dataItem instanceof Boolean) {
                dataSizes[row][col].addBelow(LayoutEngine.IMAGE_SIZE);
                continue;
            } else if (dataItem instanceof ImageElement) {
                dataSizes[row][col].addBelow(new Dimension((int) ((ImageElement) dataItem).getWidth(), (int) ((ImageElement) dataItem).getHeight()));
                // Adjust the column width - teo_sarca, [ 1673620 ]
                float width = (float) Math.ceil(dataSizes[row][col].getWidth());
                if (colWidth < width)
                    colWidth = width;
                continue;
            } else if (dataItem instanceof BarcodeElement) {
                dataSizes[row][col].addBelow(new Dimension((int) ((BarcodeElement) dataItem).getWidth(), (int) ((BarcodeElement) dataItem).getHeight()));
                // Check if the overflow is allowed - teo_sarca, [ 1673590 ]
                if (!((BarcodeElement) dataItem).isAllowOverflow()) {
                    float width = (float) Math.ceil(dataSizes[row][col].getWidth());
                    if (colWidth < width)
                        colWidth = width;
                }
                continue;
            }
            //	No Width Limitations
            if (m_columnMaxWidth[col] == 0 || m_columnMaxWidth[col] == -1) {
                //	if (HTMLElement.isHTML(string))
                //		log.finest( "HTML (no) r=" + row + ",c=" + dataCol); 
                TextLayout layout = new TextLayout(string, font, frc);
                //	buffer
                float width = layout.getAdvance() + 2;
                float height = layout.getAscent() + layout.getDescent() + layout.getLeading();
                if (width > dynMxColumnWidth)
                    m_columnMaxWidth[col] = (int) Math.ceil(dynMxColumnWidth);
                else if (colWidth < width)
                    colWidth = width;
                if (dataSizes[row][col] == null) {
                    dataSizes[row][col] = new Dimension2DImpl();
                    log.log(Level.WARNING, "No Size for r=" + row + ",c=" + col);
                }
                dataSizes[row][col].addBelow(width, height);
            }
            //	Width limitations
            if (m_columnMaxWidth[col] != 0 && m_columnMaxWidth[col] != -1) {
                float height = 0;
                //
                if (HTMLElement.isHTML(string)) {
                    //	log.finest( "HTML (limit) r=" + row + ",c=" + dataCol);
                    HTMLRenderer renderer = HTMLRenderer.get(string);
                    colWidth = renderer.getWidth();
                    if (//	one line only
                    m_columnMaxHeight[col] == -1)
                        height = renderer.getHeightOneLine();
                    else
                        height = renderer.getHeight();
                    renderer.setAllocation((int) colWidth, (int) height);
                    //	log.finest( "calculateSize HTML - " + renderer.getAllocation());
                    //	replace for printing
                    m_data[row][dataCol] = renderer;
                } else {
                    String[] lines = Pattern.compile("$", Pattern.MULTILINE).split(string);
                    for (int lineNo = 0; lineNo < lines.length; lineNo++) {
                        AttributedString aString = new AttributedString(lines[lineNo]);
                        aString.addAttribute(TextAttribute.FONT, font);
                        AttributedCharacterIterator iter = aString.getIterator();
                        LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc);
                        while (measurer.getPosition() < iter.getEndIndex()) {
                            TextLayout layout = measurer.nextLayout(Math.abs(m_columnMaxWidth[col]));
                            float width = layout.getAdvance();
                            if (colWidth < width)
                                colWidth = width;
                            float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
                            if (//	one line only
                            m_columnMaxHeight[col] == -1) {
                                height = lineHeight;
                                break;
                            } else if (m_columnMaxHeight[col] == 0 || (height + lineHeight) <= m_columnMaxHeight[col])
                                height += lineHeight;
                        }
                    }
                //	for all lines
                }
                if (m_fixedWidth[col])
                    colWidth = Math.abs(m_columnMaxWidth[col]);
                dataSizes[row][col].addBelow(colWidth, height);
            }
            dataSizes[row][col].roundUp();
            if (dataItem instanceof NamePair)
                m_rowColDrillDown.put(new Point(row, col), (NamePair) dataItem);
            //	
            log.finest("Col=" + col + ", row=" + row + " => " + dataSizes[row][col] + " - ColWidth=" + colWidth);
        }
        //	for all data rows
        //	Column Width  for Header
        String string = "";
        if (m_columnHeader[dataCol] != null)
            string = m_columnHeader[dataCol].toString();
        //	Print below existing column
        if (col != dataCol)
            headerSizes[dataCol] = new Dimension2DImpl();
        else if (//	suppress Null
        colWidth == 0 && m_columnMaxWidth[dataCol] < 0 || string.length() == 0)
            headerSizes[dataCol] = new Dimension2DImpl();
        else {
            Font font = getFont(HEADER_ROW, dataCol);
            if (!font.isBold())
                font = new Font(font.getName(), Font.BOLD, font.getSize());
            //	No Width Limitations
            if (m_columnMaxWidth[dataCol] == 0 || m_columnMaxWidth[dataCol] == -1 || !m_multiLineHeader) {
                TextLayout layout = new TextLayout(string, font, frc);
                //	buffer
                float width = layout.getAdvance() + 3;
                float height = layout.getAscent() + layout.getDescent() + layout.getLeading();
                if (width > dynMxColumnWidth)
                    m_columnMaxWidth[dataCol] = (int) Math.ceil(dynMxColumnWidth);
                else if (colWidth < width)
                    colWidth = width;
                headerSizes[dataCol] = new Dimension2DImpl(width, height);
            }
            //	Width limitations
            if (m_columnMaxWidth[dataCol] != 0 && m_columnMaxWidth[dataCol] != -1) {
                float height = 0;
                //
                String[] lines = Pattern.compile("$", Pattern.MULTILINE).split(string);
                for (int lineNo = 0; lineNo < lines.length; lineNo++) {
                    AttributedString aString = new AttributedString(lines[lineNo]);
                    aString.addAttribute(TextAttribute.FONT, font);
                    AttributedCharacterIterator iter = aString.getIterator();
                    LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc);
                    colWidth = Math.abs(m_columnMaxWidth[dataCol]);
                    while (measurer.getPosition() < iter.getEndIndex()) {
                        TextLayout layout = measurer.nextLayout(colWidth);
                        float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
                        if (//	one line only
                        !m_multiLineHeader) {
                            height = lineHeight;
                            break;
                        } else
                            /*if (m_columnMaxHeight[dataCol] == 0
								|| (height + lineHeight) <= m_columnMaxHeight[dataCol])*/
                            height += lineHeight;
                    }
                }
                //	for all header lines
                headerSizes[dataCol] = new Dimension2DImpl(colWidth, height);
            }
        }
        //	headerSize
        headerSizes[dataCol].roundUp();
        colWidth = (float) Math.ceil(colWidth);
        //	Round Column Width
        if (dataCol == 0)
            colWidth += m_tFormat.getVLineStroke().floatValue();
        if (colWidth != 0)
            colWidth += (2 * H_GAP) + m_tFormat.getVLineStroke().floatValue();
        //	Print below existing column
        if (col != dataCol) {
            //	for the data column
            m_columnWidths.add(new Float(0.0));
            Float origWidth = (Float) m_columnWidths.get(col);
            if (origWidth == null)
                log.log(Level.SEVERE, "Column " + dataCol + " below " + col + " - no value for orig width");
            else {
                if (origWidth.compareTo(new Float(colWidth)) >= 0) {
                    log.finest("Same Width - Col=" + col + " - OrigWidth=" + origWidth + " - Width=" + colWidth + " - Total=" + p_width);
                } else {
                    m_columnWidths.set(col, new Float(colWidth));
                    p_width += (colWidth - origWidth.floatValue());
                    log.finest("New Width - Col=" + col + " - OrigWidth=" + origWidth + " - Width=" + colWidth + " - Total=" + p_width);
                }
            }
        } else //	Add new Column
        {
            m_columnWidths.add(new Float(colWidth));
            p_width += colWidth;
            log.finest("Width - Col=" + dataCol + " - Width=" + colWidth + " - Total=" + p_width);
        }
    }
    //	for all columns
    //	Height	**********
    p_height = 0;
    for (int row = 0; row < rows; row++) {
        float rowHeight = 0f;
        for (int col = 0; col < cols; col++) {
            if (//	max
            dataSizes[row][col].height > rowHeight)
                rowHeight = (float) dataSizes[row][col].height;
        }
        //	for all columns
        rowHeight += m_tFormat.getLineStroke().floatValue() + (2 * V_GAP);
        m_rowHeights.add(new Float(rowHeight));
        p_height += rowHeight;
    }
    //	for all rows
    //	HeaderRow
    m_headerHeight = 0;
    for (int col = 0; col < cols; col++) {
        if (headerSizes[col].height > m_headerHeight)
            m_headerHeight = (int) headerSizes[col].height;
    }
    //	for all columns
    //	Thick lines
    m_headerHeight += (4 * m_tFormat.getLineStroke().floatValue()) + (2 * V_GAP);
    p_height += m_headerHeight;
    //	Last row Lines
    //	last fat line
    p_height += m_tFormat.getLineStroke().floatValue();
    //	Page Layout	*******************************************************
    log.fine("FirstPage=" + m_firstPage + ", NextPages=" + m_nextPages);
    //	One Page on Y | Axis
    if (m_firstPage.height >= p_height && m_pageBreak.size() == 0) {
        log.finest("Page Y=1 - PageHeight=" + m_firstPage.height + " - TableHeight=" + p_height);
        //	Y
        m_firstRowOnPage.add(new Integer(0));
        //	Y index only
        m_pageHeight.add(new Float(p_height));
    } else //	multiple pages on Y | Axis
    {
        float availableHeight = 0f;
        float usedHeight = 0f;
        boolean firstPage = true;
        int addlRows = 0;
        //	for all rows
        for (int dataRow = 0; dataRow < m_rowHeights.size(); dataRow++) {
            float rowHeight = ((Float) m_rowHeights.get(dataRow)).floatValue();
            //	Y page break before
            boolean pageBreak = isPageBreak(dataRow);
            //adjust for lastrow
            if (dataRow + 1 == m_rowHeights.size()) {
                availableHeight -= m_tFormat.getLineStroke().floatValue();
            }
            if (!pageBreak && availableHeight < rowHeight) {
                if (availableHeight > 40 && rowHeight > 40) {
                    log.finest("- Split (leave on current) Row=" + dataRow + " - Available=" + availableHeight + ", RowHeight=" + rowHeight);
                //	if (splitRow (dataRow))
                //		addlRows += 1;
                }
                //	else
                pageBreak = true;
            }
            if (pageBreak) {
                availableHeight = firstPage ? m_firstPage.height : m_nextPages.height;
                //	Y
                m_firstRowOnPage.add(new Integer(dataRow + addlRows));
                if (!firstPage) {
                    //	Y index only
                    m_pageHeight.add(new Float(usedHeight));
                    log.finest("Page Y=" + m_pageHeight.size() + " - PageHeight=" + usedHeight);
                }
                log.finest("Page Y=" + m_firstRowOnPage.size() + " - Row=" + dataRow + " - force=" + isPageBreak(dataRow));
                firstPage = false;
                //
                availableHeight -= m_headerHeight;
                usedHeight += m_headerHeight;
            }
            availableHeight -= rowHeight;
            usedHeight += rowHeight;
            if (availableHeight < 0) {
                log.finest("- Split (move to next) Row=" + dataRow + " - Available=" + availableHeight + ", RowHeight=" + rowHeight);
            }
            log.finest("Page Y=" + m_pageHeight.size() + ", Row=" + dataRow + ",AddlRows=" + addlRows + ", Height=" + rowHeight + " - Available=" + availableHeight + ", Used=" + usedHeight);
        }
        //	for all rows
        //	Y index only
        m_pageHeight.add(new Float(usedHeight));
        log.finest("Page Y=" + m_pageHeight.size() + " - PageHeight=" + usedHeight);
    }
    //	One page on - X Axis
    if (m_firstPage.width >= p_width) {
        log.finest("Page X=1 - PageWidth=" + m_firstPage.width + " - TableWidth=" + p_width);
        //	X
        m_firstColumnOnPage.add(new Integer(0));
        //
        distributeColumns(m_firstPage.width - (int) p_width, 0, m_columnWidths.size());
    } else //	multiple pages on - X Axis
    {
        int availableWidth = 0;
        int lastStart = 0;
        for (int col = 0; col < m_columnWidths.size(); col++) {
            int columnWidth = ((Float) m_columnWidths.get(col)).intValue();
            //	X page preak
            if (availableWidth < columnWidth) {
                if (col != 0)
                    distributeColumns(availableWidth, lastStart, col);
                //
                //	X
                m_firstColumnOnPage.add(new Integer(col));
                log.finest("Page X=" + m_firstColumnOnPage.size() + " - Col=" + col);
                lastStart = col;
                //	Width is the same on all pages
                availableWidth = m_firstPage.width;
                //
                for (int repCol = 0; repCol < m_repeatedColumns && col > repCol; repCol++) {
                    float repColumnWidth = ((Float) m_columnWidths.get(repCol)).floatValue();
                    //	leave 50% of space available for non repeated columns
                    if (availableWidth < m_firstPage.width * 0.5)
                        break;
                    availableWidth -= repColumnWidth;
                }
            }
            //	pageBreak
            availableWidth -= columnWidth;
        }
    //	for acc columns
    }
    //	multiple - X pages
    log.fine("Pages=" + getPageCount() + " X=" + m_firstColumnOnPage.size() + "/Y=" + m_firstRowOnPage.size() + " - Width=" + p_width + ", Height=" + p_height);
    return true;
}
Also used : ArrayList(java.util.ArrayList) LineBreakMeasurer(java.awt.font.LineBreakMeasurer) AttributedString(java.text.AttributedString) Font(java.awt.Font) AttributedString(java.text.AttributedString) NamePair(org.compiere.util.NamePair) ValueNamePair(org.compiere.util.ValueNamePair) KeyNamePair(org.compiere.util.KeyNamePair) Dimension(java.awt.Dimension) Point(java.awt.Point) Point(java.awt.Point) TextLayout(java.awt.font.TextLayout) AttributedCharacterIterator(java.text.AttributedCharacterIterator) FontRenderContext(java.awt.font.FontRenderContext)

Example 17 with LineBreakMeasurer

use of java.awt.font.LineBreakMeasurer in project poi by apache.

the class DrawTextParagraph method breakText.

/**
     * break text into lines, each representing a line of text that fits in the wrapping width
     *
     * @param graphics The drawing context for computing text-lengths.
     */
protected void breakText(Graphics2D graphics) {
    lines.clear();
    DrawFactory fact = DrawFactory.getInstance(graphics);
    StringBuilder text = new StringBuilder();
    AttributedString at = getAttributedString(graphics, text);
    boolean emptyParagraph = ("".equals(text.toString().trim()));
    AttributedCharacterIterator it = at.getIterator();
    LineBreakMeasurer measurer = new LineBreakMeasurer(it, graphics.getFontRenderContext());
    for (; ; ) {
        int startIndex = measurer.getPosition();
        // add a pixel to compensate rounding errors
        double wrappingWidth = getWrappingWidth(lines.size() == 0, graphics) + 1;
        // shape width can be smaller that the sum of insets (this was proved by a test file)
        if (wrappingWidth < 0) {
            wrappingWidth = 1;
        }
        int nextBreak = text.indexOf("\n", startIndex + 1);
        if (nextBreak == -1) {
            nextBreak = it.getEndIndex();
        }
        TextLayout layout = measurer.nextLayout((float) wrappingWidth, nextBreak, true);
        if (layout == null) {
            // layout can be null if the entire word at the current position
            // does not fit within the wrapping width. Try with requireNextWord=false.
            layout = measurer.nextLayout((float) wrappingWidth, nextBreak, false);
        }
        if (layout == null) {
            // exit if can't break any more
            break;
        }
        int endIndex = measurer.getPosition();
        // skip over new line breaks (we paint 'clear' text runs not starting or ending with \n)
        if (endIndex < it.getEndIndex() && text.charAt(endIndex) == '\n') {
            measurer.setPosition(endIndex + 1);
        }
        TextAlign hAlign = paragraph.getTextAlign();
        if (hAlign == TextAlign.JUSTIFY || hAlign == TextAlign.JUSTIFY_LOW) {
            layout = layout.getJustifiedLayout((float) wrappingWidth);
        }
        AttributedString str = (emptyParagraph) ? // we will not paint empty paragraphs
        null : new AttributedString(it, startIndex, endIndex);
        DrawTextFragment line = fact.getTextFragment(layout, str);
        lines.add(line);
        maxLineHeight = Math.max(maxLineHeight, line.getHeight());
        if (endIndex == it.getEndIndex()) {
            break;
        }
    }
    rawText = text.toString();
}
Also used : AttributedString(java.text.AttributedString) TextAlign(org.apache.poi.sl.usermodel.TextParagraph.TextAlign) LineBreakMeasurer(java.awt.font.LineBreakMeasurer) Paint(java.awt.Paint) AttributedCharacterIterator(java.text.AttributedCharacterIterator) TextLayout(java.awt.font.TextLayout)

Aggregations

LineBreakMeasurer (java.awt.font.LineBreakMeasurer)17 TextLayout (java.awt.font.TextLayout)16 AttributedString (java.text.AttributedString)16 AttributedCharacterIterator (java.text.AttributedCharacterIterator)15 FontRenderContext (java.awt.font.FontRenderContext)7 Font (java.awt.Font)6 Point (java.awt.Point)6 Graphics2D (java.awt.Graphics2D)5 Paint (java.awt.Paint)5 Color (java.awt.Color)3 Rectangle (java.awt.Rectangle)3 ArrayList (java.util.ArrayList)3 Dimension (java.awt.Dimension)2 Insets (java.awt.Insets)2 KeyNamePair (org.compiere.util.KeyNamePair)2 NamePair (org.compiere.util.NamePair)2 ValueNamePair (org.compiere.util.ValueNamePair)2 BooleanAttribute (doc.attributes.BooleanAttribute)1 MathObjectAttribute (doc.attributes.MathObjectAttribute)1 Image (java.awt.Image)1