/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008 jOpenDocument, by ILM Informatique. All rights reserved. * * The contents of this file are subject to the terms of the GNU * General Public License Version 3 only ("GPL"). * You may not use this file except in compliance with the License. * You can obtain a copy of the License at http://www.gnu.org/licenses/gpl-3.0.html * See the License for the specific language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each file. * */ package org.jopendocument.renderer; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.util.List; import javax.swing.JPanel; import org.jopendocument.model.OpenDocument; import org.jopendocument.model.PrintedPage; import org.jopendocument.model.draw.DrawFrame; import org.jopendocument.model.draw.DrawImage; import org.jopendocument.model.office.OfficeBody; import org.jopendocument.model.office.OfficeSpreadsheet; import org.jopendocument.model.style.StyleStyle; import org.jopendocument.model.style.StyleTableCellProperties; import org.jopendocument.model.table.TableShapes; import org.jopendocument.model.table.TableTable; import org.jopendocument.model.table.TableTableCell; import org.jopendocument.model.table.TableTableColumn; import org.jopendocument.model.table.TableTableRow; import org.jopendocument.util.ValueHelper; public class ODTRenderer extends JPanel { private static final long serialVersionUID = -4903349568929293597L; private double resizeFactor; private OfficeBody body; private TableTable table; private int printHeightPixel; private int printWidthPixel; private int printWidth; private int printHeight; private static final ODTCellBackgroundRenderer backgroundRenderer = new ODTCellBackgroundRenderer(); private static final ODTCellBorderRenderer borderRenderer = new ODTCellBorderRenderer(); private static final ODTCellTextRenderer textRenderer = new ODTCellTextRenderer(); private static final ODTCellImageRenderer imageRenderer = new ODTCellImageRenderer(); private static boolean debug = false; private PrintedPage currentPage; private boolean paintMaxResolution; private boolean ignoreMargins; private OpenDocument od; private int currentPageIndex; public ODTRenderer(OpenDocument doc) { this.body = doc.getBody(); this.setBackground(Color.WHITE); this.currentPageIndex = 0; this.currentPage = doc.getPrintedPage(this.currentPageIndex); setResizeFactor(360); this.od = doc; } public void setCurrentPage(int i) { this.currentPageIndex = i; this.currentPage = od.getPrintedPage(i); updateSize(); repaint(); } private void updateSize() { this.setSize(getPageWidthInPixel(), getPageHeightInPixel()); } public double getPageHeight() { return this.getPageHeightInPixel() * resizeFactor; } public int getPageHeightInPixel() { int h = 0; final TableTableRow[] rows = this.currentPage.getRows(); final int rowCount = rows.length; for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { final TableTableRow row = rows[rowIndex]; h += (int) (row.getHeight() / this.resizeFactor); } return h; } public double getPageWidth() { return this.getPageWidthInPixel() * resizeFactor; } public int getPageWidthInPixel() { final int printStartCol = table.getPrintStartCol(); final int printStopCol = table.getPrintStopCol(); final TableTableRow[] rows = this.currentPage.getRows(); final double currentResizeFactor = this.resizeFactor; int marginLeft = table.getPageLayoutProperties().getMarginLeft(); if (ignoreMargins) { marginLeft = 0; } int h = (int) (marginLeft / currentResizeFactor); final TableTableColumn[] columns = table.getColumns().toArray(new TableTableColumn[0]); for (int rowIndex = 0; rowIndex < 1; rowIndex++) { final TableTableRow row = rows[rowIndex]; final TableTableCell[] cells = row.getCellsInRange(printStartCol, printStopCol); final int cellsSize = cells.length; // les cells repeated sont deja clonées for (int i = 0; i < cellsSize; i++) { final TableTableCell cell = cells[i]; if (cell == null) { continue; } final TableTableColumn col = columns[printStartCol + i]; final StyleStyle style = cell.getStyle(); h += (int) (col.getWidth() / this.resizeFactor); } } return h; } public int getPrintedPagesNumber() { return this.od.getPrintedPageCount(); } public synchronized void setResizeFactor(double resizeFactor) { this.resizeFactor = resizeFactor; final List<OfficeSpreadsheet> l = this.body.getOfficeSpreadsheets(); final int spreadSheatCount = l.size(); for (int i = 0; i < spreadSheatCount; i++) { final List<TableTable> tables = l.get(i).getTables(); for (int j = 0; j < tables.size(); j++) { final TableTable t = tables.get(j); this.table = t; printWidth = t.getPrintWidth() + t.getPageLayoutProperties().getMarginLeft() + t.getPageLayoutProperties().getMarginRight(); printHeight = t.getPageLayoutProperties().getPageHeight(); if (ignoreMargins) { printWidth = t.getPrintWidth(); printHeight = t.getPrintHeight(); } printWidthPixel = (int) Math.ceil(printWidth / resizeFactor); printHeightPixel = (int) Math.ceil(printHeight / resizeFactor); setPreferredSize(new Dimension(printWidthPixel, printHeightPixel)); break; } } updateSize(); repaint(); } public int getPrintWidthInPixel() { return printWidthPixel; } public int getPrintHeightInPixel() { return printHeightPixel; } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; if (debug) { printRendererInformation(); System.out.println("********************** RENDERING BACKGROUND *************"); } drawODTBackground(g2); if (debug) { System.out.println("********************** RENDERING BORDERS *************"); } drawODTBorders(g2); if (debug) { System.out.println("********************** RENDERING TEXTS *************"); } drawODTText(g2); if (debug) { System.out.println("********************** RENDERING IMAGES *************"); } drawODTImages(g2); } /** * @param g2 */ private final void drawODTImages(Graphics2D g2) { if (!paintMaxResolution) { g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED); } else { g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); } // Images in Cells drawCells(g2, imageRenderer); // Image in Page final TableTable currentTable = this.table; TableShapes shapes = currentTable.getTableShapes(); if (shapes == null) { return; } List<DrawFrame> frames = shapes.getDrawFrames(); final double currentResizeFactor = this.resizeFactor; int borderLeft = (int) (currentTable.getPageLayoutProperties().getMarginLeft() / currentResizeFactor); int borderRight = (int) (currentTable.getPageLayoutProperties().getMarginRight() / currentResizeFactor); int borderTop = (int) (currentTable.getPageLayoutProperties().getMarginTop() / currentResizeFactor); int borderBottom = (int) (currentTable.getPageLayoutProperties().getMarginBottom() / currentResizeFactor); if (this.ignoreMargins) { borderLeft = 0; borderRight = 0; borderTop = 0; borderBottom = 0; } for (DrawFrame frame : frames) { DrawImage dIm = frame.getDrawImage(); if (dIm != null) { double dx = borderLeft + ValueHelper.getLength(frame.getSvgX()) / resizeFactor; double dy = borderTop + ValueHelper.getLength(frame.getSvgY()) / resizeFactor; double w = ValueHelper.getLength(frame.getSvgWidth()) / resizeFactor; double h = ValueHelper.getLength(frame.getSvgHeight()) / resizeFactor; Image im = null; if (!paintMaxResolution) { im = body.getDocument().getImage(dIm.getXlinkHref(), (int) w, (int) h); g2.drawImage(im, (int) Math.round(dx), (int) Math.round(dy), null); } else { im = body.getDocument().getImage(dIm.getXlinkHref()); g2.drawImage(im, (int) Math.round(dx), (int) Math.round(dy), (int) Math.round(w), (int) Math.round(h), null); } } } } /** * @param g2 */ private final void drawODTText(Graphics2D g2) { // Texts g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); drawCells(g2, textRenderer); } /** * @param g2 */ private final void drawODTBorders(Graphics2D g2) { // Borders g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); drawCells(g2, borderRenderer); } /** * @param g2 */ private final void drawODTBackground(Graphics2D g2) { // Background g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); drawCells(g2, backgroundRenderer); } private final void drawCells(final Graphics2D g, final ODTCellRenderer renderer) { // Constants final TableTable currentTable = this.table; final int printStartCol = currentTable.getPrintStartCol(); final int printStopCol = currentTable.getPrintStopCol(); final TableTableRow[] rows = this.currentPage.getRows(); final int rowCount = rows.length; final double currentResizeFactor = this.resizeFactor; int marginLeft = currentTable.getPageLayoutProperties().getMarginLeft(); int marginTop = currentTable.getPageLayoutProperties().getMarginTop(); if (ignoreMargins) { marginLeft = 0; marginTop = 0; } final int borderLeft = (int) (marginLeft / currentResizeFactor); final TableTableColumn[] columns = table.getColumns().toArray(new TableTableColumn[0]); int y = (int) (marginTop / currentResizeFactor); for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) { final TableTableRow row = rows[rowIndex]; final int rowHeight = (int) (row.getHeight() / currentResizeFactor); final TableTableCell[] cells = row.getCellsInRange(printStartCol, printStopCol); final int cellsSize = cells.length; int x = borderLeft; // les cells repeated sont deja clonées for (int i = 0; i < cellsSize; i++) { final TableTableCell cell = cells[i]; if (cell == null) { continue; } final TableTableColumn col = columns[printStartCol + i]; final StyleStyle style = cell.getStyle(); int cellWidth = (int) (col.getWidth() / currentResizeFactor); final StyleTableCellProperties cellProps = style.getStyleTableCellProperties(); int cellHeight = rowHeight; if (cell.getTableNumberRowsSpanned() > 1) { for (int repeat = 1; repeat < cell.getTableNumberRowsSpanned(); repeat++) { cellHeight += rows[rowIndex + repeat].getHeight() / currentResizeFactor; } } if (cell.getTableNumberColumnsSpanned() > 1) { for (int repeat = 1; repeat < cell.getTableNumberColumnsSpanned(); repeat++) { final int colIndex = printStartCol + i + repeat; final double w = (columns[colIndex].getWidth() / currentResizeFactor); cellWidth += w; } } try { renderer.draw(g, x, y, cellWidth, cellHeight, currentResizeFactor, cell, cellProps); } catch (Exception e) { // TODO: handle exception System.err.println("Failed on x:" + x + " y:" + y + " Cell:" + cell); e.printStackTrace(); } x += cellWidth; } y += rowHeight; } } public double getPrintWidth() { return this.printWidth; } public double getPrintHeight() { return this.printHeight; } /** * Set the image rendering policy * * @param b : true if you need an extra definition (ex for printing) */ public void setPaintMaxResolution(boolean b) { this.paintMaxResolution = b; imageRenderer.setPaintMaxResolution(b); } public void setIgnoreMargins(boolean b) { this.ignoreMargins = b; } public void printRendererInformation() { System.out.println("==== Spreadsheet Renderer ==="); System.out.println("Rendering file: " + this.od.getZipFile().getName()); System.out.println("Document margins ignored: " + this.ignoreMargins); System.out.println("Max image quality: " + this.paintMaxResolution); System.out.println("Current page: " + (this.currentPageIndex + 1) + " / " + this.getPrintedPagesNumber()); System.out.println("Width: " + (long) getPrintWidth() + " micrometers (" + getPrintWidth() / 10000 + " cms)"); System.out.println("Height: " + (long) getPrintHeight() + " micrometers (" + getPrintHeight() / 10000 + " cms)"); System.out.println("Size in pixels: " + this.getPrintWidthInPixel() + "x" + this.getPrintHeightInPixel()); System.out.println("Resize factor " + this.resizeFactor); System.out.println("Page:" + this.currentPage.getRows().length + " rows "); System.out.println(); } public void setDebug(boolean b) { debug = true; } }