Java tutorial
/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2011 Jaspersoft Corporation. All rights reserved. * http://www.jaspersoft.com * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is part of JasperReports. * * JasperReports is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JasperReports is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JasperReports. If not, see <http://www.gnu.org/licenses/>. */ package de.kiwiwings.jasperreports.exporter; import java.awt.Dimension; import java.awt.font.TextAttribute; import java.awt.geom.Dimension2D; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.io.IOException; import java.io.OutputStream; import java.text.AttributedCharacterIterator.Attribute; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import net.sf.jasperreports.charts.util.DrawChartRenderer; import net.sf.jasperreports.engine.DefaultJasperReportsContext; import net.sf.jasperreports.engine.JRAbstractExporter; import net.sf.jasperreports.engine.JRBoxContainer; import net.sf.jasperreports.engine.JRCommonElement; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRGenericElementType; import net.sf.jasperreports.engine.JRGenericPrintElement; import net.sf.jasperreports.engine.JRPen; import net.sf.jasperreports.engine.JRPrintElement; import net.sf.jasperreports.engine.JRPrintEllipse; import net.sf.jasperreports.engine.JRPrintFrame; import net.sf.jasperreports.engine.JRPrintHyperlink; import net.sf.jasperreports.engine.JRPrintHyperlinkParameter; import net.sf.jasperreports.engine.JRPrintImage; import net.sf.jasperreports.engine.JRPrintLine; import net.sf.jasperreports.engine.JRPrintPage; import net.sf.jasperreports.engine.JRPrintRectangle; import net.sf.jasperreports.engine.JRPrintText; import net.sf.jasperreports.engine.JRPropertiesUtil; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JRWrappingSvgRenderer; import net.sf.jasperreports.engine.JasperReportsContext; import net.sf.jasperreports.engine.Renderable; import net.sf.jasperreports.engine.RenderableUtil; import net.sf.jasperreports.engine.export.GenericElementHandlerEnviroment; import net.sf.jasperreports.engine.export.JRExportProgressMonitor; import net.sf.jasperreports.engine.export.JRHyperlinkProducer; import net.sf.jasperreports.engine.export.JRXmlExporter; import net.sf.jasperreports.engine.export.ooxml.JRPptxExporter; import net.sf.jasperreports.engine.fill.JRTemplatePrintText; import net.sf.jasperreports.engine.fonts.FontFace; import net.sf.jasperreports.engine.fonts.FontFamily; import net.sf.jasperreports.engine.fonts.FontInfo; import net.sf.jasperreports.engine.fonts.FontUtil; import net.sf.jasperreports.engine.type.ImageTypeEnum; import net.sf.jasperreports.engine.type.LineDirectionEnum; import net.sf.jasperreports.engine.type.ModeEnum; import net.sf.jasperreports.engine.type.RenderableTypeEnum; import net.sf.jasperreports.engine.util.JRStyledText; import net.sf.jasperreports.engine.util.JRStyledTextUtil; import net.sf.jasperreports.export.ExporterInputItem; import net.sf.jasperreports.export.OutputStreamExporterOutput; import net.sf.jasperreports.repo.RepositoryUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.xslf.usermodel.LineDash; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFAutoShape; import org.apache.poi.xslf.usermodel.XSLFGroupShape; import org.apache.poi.xslf.usermodel.XSLFPictureData; import org.apache.poi.xslf.usermodel.XSLFRelation; import org.apache.poi.xslf.usermodel.XSLFShape; import org.apache.poi.xslf.usermodel.XSLFSheet; import org.apache.poi.xslf.usermodel.XSLFSimpleShape; import org.apache.poi.xslf.usermodel.XSLFSimpleShapeHelper; import org.apache.poi.xslf.usermodel.XSLFSlideMaster; import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect; import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont; import org.openxmlformats.schemas.presentationml.x2006.main.CTEmbeddedFontDataId; import org.openxmlformats.schemas.presentationml.x2006.main.CTEmbeddedFontList; import org.openxmlformats.schemas.presentationml.x2006.main.CTEmbeddedFontListEntry; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation; import com.google.typography.font.sfntly.Font; import com.google.typography.font.sfntly.FontFactory; import com.google.typography.font.sfntly.data.WritableFontData; import com.google.typography.font.tools.conversion.eot.EOTWriter; import de.kiwiwings.jasperreports.exporter.customizer.SheetCustomizer; /** * Exports a JasperReports document to PPTX format. * @author Teodor Danciu (teodord@users.sourceforge.net) * @version $Id: JRPptxExporter.java 5527 2012-08-01 12:04:08Z shertage $ */ public class PptxShapeExporter extends JRAbstractExporter<PptxShapeReportConfiguration, PptxShapeExporterConfiguration, OutputStreamExporterOutput, PptxShapeExporterContext> implements FontResolver { private static final Log log = LogFactory.getLog(PptxShapeExporter.class); /** * The exporter key, as used in * {@link GenericElementHandlerEnviroment#getElementHandler(JRGenericElementType, String)}. */ public static final String PPTX_EXPORTER_KEY = JRPropertiesUtil.PROPERTY_PREFIX + "pptx"; protected static final String PPTX_EXPORTER_PROPERTIES_PREFIX = JRPropertiesUtil.PROPERTY_PREFIX + "export.pptx."; protected XMLSlideShow ppt; protected XSLFSheet slide; protected Map<Integer, XSLFSheet> slideList = new HashMap<Integer, XSLFSheet>(); protected int reportIndex; protected int pageIndex; protected List<Integer> frameIndexStack; protected int elementIndex; protected boolean startPage; protected String invalidCharReplacement; protected class ExporterContext extends BaseExporterContext implements PptxShapeExporterContext { public ExporterContext() { } } /** * @see #JRPptxExporter(JasperReportsContext) */ public PptxShapeExporter() { this(DefaultJasperReportsContext.getInstance()); } public PptxShapeExporter(JasperReportsContext jasperReportsContext) { super(jasperReportsContext); exporterContext = new ExporterContext(); } protected Class<PptxShapeExporterConfiguration> getConfigurationInterface() { return PptxShapeExporterConfiguration.class; } protected Class<PptxShapeReportConfiguration> getItemConfigurationInterface() { return PptxShapeReportConfiguration.class; } @SuppressWarnings("deprecation") protected void ensureOutput() { if (exporterOutput != null) return; exporterOutput = new net.sf.jasperreports.export.parameters.ParametersOutputStreamExporterOutput( getJasperReportsContext(), getParameters(), getCurrentJasperPrint()); } public void exportReport() throws JRException { ensureJasperReportsContext(); ensureInput(); initExport(); ensureOutput(); OutputStream outputStream = getExporterOutput().getOutputStream(); try { exportReportToStream(outputStream); } catch (IOException e) { throw new JRRuntimeException(e); } finally { getExporterOutput().close(); resetExportContext(); } } /** * */ protected void exportReportToStream(OutputStream os) throws JRException, IOException { ppt = new XMLSlideShow(); ppt.setPageSize(new Dimension(jasperPrint.getPageWidth(), jasperPrint.getPageHeight())); int nbrBackElem = 0; if (itemConfiguration.hasBackground()) { nbrBackElem = exportBackground(); } List<ExporterInputItem> items = exporterInput.getItems(); for (reportIndex = 0; reportIndex < items.size(); reportIndex++) { ExporterInputItem item = items.get(reportIndex); setCurrentExporterInputItem(item); setExporterHints(); slideList.clear(); List<JRPrintPage> pages = jasperPrint.getPages(); if (pages == null || pages.size() == 0) continue; PageRange pageRange = getPageRange(); int startPageIndex = (pageRange == null || pageRange.getStartPageIndex() == null) ? 0 : pageRange.getStartPageIndex(); int endPageIndex = (pageRange == null || pageRange.getEndPageIndex() == null) ? (pages.size() - 1) : pageRange.getEndPageIndex(); // pre-create pages for hyperlinks between them for (int i = startPageIndex; i <= endPageIndex; i++) { createSlide(null);//FIXMEPPTX slideList.put(i, slide); } JRPrintPage page = null; for (pageIndex = startPageIndex; pageIndex <= endPageIndex; pageIndex++) { if (Thread.interrupted()) { throw new JRException("Current thread interrupted."); } page = pages.get(pageIndex); slide = slideList.get(pageIndex); List<JRPrintElement> list = page.getElements(); list = list.subList(nbrBackElem, list.size()); page.setElements(list); exportPage(page); SheetCustomizer sheetCustomizer[] = itemConfiguration.getSheetCustomizer(); if (sheetCustomizer != null) { for (SheetCustomizer sc : sheetCustomizer) { sc.customize(slide); } } } } embedFonts(); ppt.write(os); } /** * */ protected void exportPage(JRPrintPage page) throws JRException { frameIndexStack = new ArrayList<Integer>(); exportElements(page.getElements()); JRExportProgressMonitor progressMonitor = getCurrentItemConfiguration().getProgressMonitor(); if (progressMonitor != null) { progressMonitor.afterPageExport(); } } protected void createSlide(String name) { slide = ppt.createSlide(); } /** * */ protected void exportElements(List<JRPrintElement> elements) throws JRException { if (elements == null) return; elementIndex = -1; for (JRPrintElement element : elements) { elementIndex++; if (filter != null && !filter.isToExport(element)) continue; if (element instanceof JRPrintLine) { exportLine((JRPrintLine) element); } else if (element instanceof JRPrintRectangle) { exportRectangle((JRPrintRectangle) element); } else if (element instanceof JRPrintEllipse) { exportEllipse((JRPrintEllipse) element); } else if (element instanceof JRPrintImage) { exportImage((JRPrintImage) element); } else if (element instanceof JRPrintText) { exportText((JRPrintText) element); } else if (element instanceof JRPrintFrame) { exportFrame((JRPrintFrame) element); } else if (element instanceof JRGenericPrintElement) { exportGenericElement((JRGenericPrintElement) element); } } } protected void exportElementAttributes(XSLFSimpleShape xsShape // the target shape , JRCommonElement jrShape // the source shape , JRPen jrPen // the outline of the shape , JRBoxContainer jrBox // box around the shape, if applicable , XSLFShape hyperlinkTarget // a shape or group of shape as hyperlink object ) { assert (xsShape != null && jrShape != null); if (jrShape.getKey() != null) { XSLFSimpleShapeHelper.setShapeName(xsShape, jrShape.getKey()); } if ((jrShape.getModeValue() == null || jrShape.getModeValue() == ModeEnum.OPAQUE) && jrShape.getBackcolor() != null) { xsShape.setFillColor(jrShape.getBackcolor()); } if (jrPen != null && jrPen.getLineWidth() > 0) { xsShape.setLineWidth(jrPen.getLineWidth()); xsShape.setLineColor(jrPen.getLineColor()); switch (jrPen.getLineStyleValue()) { case DASHED: xsShape.setLineDash(LineDash.DASH); break; case DOTTED: xsShape.setLineDash(LineDash.DOT); break; default: xsShape.setLineDash(LineDash.SOLID); break; } } // TODO: set border to box around the shape setHyperlinkURL(jrShape, hyperlinkTarget); } protected void setHyperlinkURL(JRCommonElement jrShape, XSLFShape hyperlinkTarget) { if (hyperlinkTarget == null || !(jrShape instanceof JRPrintHyperlink)) return; // http://openxmldeveloper.org/discussions/formats/f/15/t/304.aspx JRPrintHyperlink link = (JRPrintHyperlink) jrShape; JRHyperlinkProducer customHandler = getHyperlinkProducer(link); PackageRelationship rel = null; String action = null; if (customHandler != null) { String href = customHandler.getHyperlink(link); if (href != null) { rel = slide.getPackagePart().addExternalRelationship(href, XSLFRelation.HYPERLINK.getRelation()); } } switch (link.getHyperlinkTypeValue()) { case REFERENCE: { String href = link.getHyperlinkReference(); if (href != null) { rel = slide.getPackagePart().addExternalRelationship(href, XSLFRelation.HYPERLINK.getRelation()); } break; } case LOCAL_PAGE: { XSLFSheet targetSlide = slideList.get(link.getHyperlinkPage()); rel = slide.getPackagePart().addRelationship(targetSlide.getPackagePart().getPartName(), TargetMode.INTERNAL, XSLFRelation.SLIDE.getRelation()); action = "ppaction://hlinksldjump"; break; } case REMOTE_PAGE: { String href = link.getHyperlinkReference(); if (href != null) { rel = slide.getPackagePart().addExternalRelationship(href, XSLFRelation.HYPERLINK.getRelation()); } Integer page = link.getHyperlinkPage(); if (page != null) { action = "ppaction://hlinkpres?slideindex=" + page; if (link.getHyperlinkParameters() != null) { List<JRPrintHyperlinkParameter> plist = link.getHyperlinkParameters().getParameters(); if (plist != null) { for (JRPrintHyperlinkParameter p : plist) { if ("slidetitle".equals(p.getName())) { action += "&slidetitle=" + p.getValue().toString(); break; } } } } } break; } case NONE: default: case LOCAL_ANCHOR: case REMOTE_ANCHOR: // not implemented ... only pages (not elements) can be referenced in powerpoint break; } if (rel != null) { CTHyperlink hlink = XSLFSimpleShapeHelper.addHyperlink(hyperlinkTarget); if (hlink == null) { slide.getPackagePart().removeRelationship(rel.getId()); } else { hlink.setId(rel.getId()); if (action != null) { hlink.setAction(action); } } } } /** * */ protected void exportLine(JRPrintLine line) { int x1 = line.getX() + getOffsetX(); int y1 = line.getY() + getOffsetY(); int x2 = x1 + Math.max(line.getWidth(), 1); int y2 = y1 + Math.max(line.getHeight(), 1); if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN) { // flip vertical int tmp = x2; x2 = x1; x1 = tmp; } Line2D myline = new Line2D.Double(x1, y1, x2, y2); XSLFAutoShape xfline = PptxGraphics2D.getShape(myline, slide); exportElementAttributes(xfline, line, line.getLinePen(), null, xfline); } /** * */ protected void exportRectangle(JRPrintRectangle rectangle) { int x = rectangle.getX() + getOffsetX(); int y = rectangle.getY() + getOffsetY(); int width = rectangle.getWidth(); int height = rectangle.getHeight(); int radius = rectangle.getRadius(); XSLFAutoShape xfrect; if (radius == 0) { Rectangle2D myrect = new Rectangle2D.Double(x, y, width, height); xfrect = PptxGraphics2D.getShape(myrect, slide); } else { RoundRectangle2D myrect = new RoundRectangle2D.Double(x, y, width, height, radius, radius); xfrect = PptxGraphics2D.getShape(myrect, slide); } exportElementAttributes(xfrect, rectangle, rectangle.getLinePen(), null, xfrect); } /** * */ protected void exportEllipse(JRPrintEllipse ellipse) { int x = ellipse.getX() + getOffsetX(); int y = ellipse.getY() + getOffsetY(); int width = ellipse.getWidth(); int height = ellipse.getHeight(); Ellipse2D myoval = new Ellipse2D.Double(x, y, width, height); XSLFAutoShape xfOval = PptxGraphics2D.getShape(myoval, slide); exportElementAttributes(xfOval, ellipse, ellipse.getLinePen(), null, xfOval); } /** * */ public void exportText(JRPrintText text) { JasperReportsContext jrctx = getJasperReportsContext(); JRStyledText styledText = getStyledText(text); Locale locale = getTextLocale(text); PptxShapeTextHelper textHelper; if (outlineFont(text.getFontName(), locale)) { textHelper = new PptxShapeGlyphHelper(jrctx, text, styledText, getOffsetX(), getOffsetY(), locale, invalidCharReplacement, slide, this, pageIndex); } else { textHelper = new PptxShapeRunHelper(jrctx, text, styledText, getOffsetX(), getOffsetY(), locale, invalidCharReplacement, slide, this, pageIndex); } textHelper.export(); exportElementAttributes(textHelper.getShapeBox(), text, null, text, textHelper.getShape()); } /** * */ public void exportImage(JRPrintImage image) throws JRException { int leftPadding = image.getLineBox().getLeftPadding().intValue(); int topPadding = image.getLineBox().getTopPadding().intValue();//FIXMEDOCX maybe consider border thickness int rightPadding = image.getLineBox().getRightPadding().intValue(); int bottomPadding = image.getLineBox().getBottomPadding().intValue(); double availableImageWidth = image.getWidth() - leftPadding - rightPadding; availableImageWidth = availableImageWidth < 0 ? 0 : availableImageWidth; double availableImageHeight = image.getHeight() - topPadding - bottomPadding; availableImageHeight = availableImageHeight < 0 ? 0 : availableImageHeight; Renderable renderer = image.getRenderable(); if (renderer == null || availableImageWidth == 0 || availableImageHeight == 0) return; if (renderer.getTypeValue() == RenderableTypeEnum.IMAGE) { // Non-lazy image renderers are all asked for their image data at some point. // Better to test and replace the renderer now, in case of lazy load error. renderer = RenderableUtil.getInstance(jasperReportsContext).getOnErrorRendererForImageData(renderer, image.getOnErrorTypeValue()); if (renderer == null) return; } double normalWidth = availableImageWidth; double normalHeight = availableImageHeight; // Image load might fail. Renderable tmpRenderer = RenderableUtil.getInstance(jasperReportsContext) .getOnErrorRendererForDimension(renderer, image.getOnErrorTypeValue()); Dimension2D dimension = tmpRenderer == null ? null : tmpRenderer.getDimension(jasperReportsContext); // If renderer was replaced, ignore image dimension. if (tmpRenderer == renderer && dimension != null) { normalWidth = dimension.getWidth(); normalHeight = dimension.getHeight(); } double cropTop = 0; double cropLeft = 0; double cropBottom = 0; double cropRight = 0; switch (image.getScaleImageValue()) { case FILL_FRAME: // width = availableImageWidth; // height = availableImageHeight; break; default: case RETAIN_SHAPE: if (availableImageWidth > 0 && availableImageHeight > 0) { if (normalWidth > availableImageWidth) { normalHeight /= normalWidth / availableImageWidth; normalWidth = availableImageWidth; } if (normalHeight > availableImageHeight) { normalWidth /= normalHeight / availableImageHeight; normalHeight = availableImageHeight; } } // nobreak case CLIP: if (availableImageWidth > 0 && availableImageHeight > 0) { double reducedWidth = getOffsetInPercent(normalWidth, availableImageWidth); switch (image.getHorizontalAlignmentValue()) { default: case LEFT: cropRight = reducedWidth; break; case RIGHT: cropLeft = reducedWidth; break; case CENTER: cropLeft = cropRight = reducedWidth / 2d; break; } double reducedHeight = getOffsetInPercent(normalHeight, availableImageHeight); switch (image.getVerticalAlignmentValue()) { default: case BOTTOM: cropTop = reducedHeight; break; case TOP: cropBottom = reducedHeight; break; case MIDDLE: cropTop = cropBottom = reducedHeight / 2; break; } } break; } XSLFSimpleShape backgroundShape; XSLFShape hyperlinkShape; if (renderer instanceof DrawChartRenderer) { Rectangle2D rect = new Rectangle2D.Double(image.getX(), image.getY(), image.getWidth(), image.getHeight()); PptxGraphics2D grx2 = new PptxGraphics2D(rect, this, slide); // Background color is applied to whole Image backgroundShape = grx2.getShape(rect); renderer.render(jasperReportsContext, grx2, rect); // hyperlinks are only available for visible elements of the chart XSLFGroupShape grp = grx2.getShapeGroup(); CTNonVisualDrawingProps cp = grp.getXmlObject().getNvGrpSpPr().getCNvPr(); cp.setName(cp.getName().replaceFirst("[^ ]+", "JFreeChart")); hyperlinkShape = grp; } else { // if (image.isLazy())//FIXMEDOCX learn how to link images Renderable imgRenderer = image.getRenderable(); if (imgRenderer.getTypeValue() == RenderableTypeEnum.SVG) { imgRenderer = new JRWrappingSvgRenderer(imgRenderer, new Dimension(image.getWidth(), image.getHeight()), ModeEnum.OPAQUE == image.getModeValue() ? image.getBackcolor() : null); } ImageTypeEnum mimeType = imgRenderer.getImageTypeValue(); if (mimeType == null) mimeType = ImageTypeEnum.JPEG; int xsMime; switch (mimeType) { default: case UNKNOWN: case JPEG: xsMime = XSLFPictureData.PICTURE_TYPE_JPEG; break; case GIF: xsMime = XSLFPictureData.PICTURE_TYPE_GIF; break; case PNG: xsMime = XSLFPictureData.PICTURE_TYPE_PNG; break; case TIFF: xsMime = XSLFPictureData.PICTURE_TYPE_TIFF; break; } byte pictureData[] = imgRenderer.getImageData(jasperReportsContext); int idx = ppt.addPicture(pictureData, xsMime); backgroundShape = slide.createPicture(idx); hyperlinkShape = backgroundShape; CTPicture ct = (CTPicture) backgroundShape.getXmlObject(); if (cropTop != 0 || cropRight != 0 || cropBottom != 0 || cropLeft != 0) { // CTRelativeRect rrect = ct.getBlipFill().getStretch().getFillRect(); CTRelativeRect rrect = ct.getBlipFill().addNewSrcRect(); rrect.setT((int) cropTop); rrect.setR((int) cropRight); rrect.setB((int) cropBottom); rrect.setL((int) cropLeft); } Rectangle2D rect = new Rectangle2D.Double(image.getX() + getOffsetX() + leftPadding, image.getY() + getOffsetY() + topPadding, availableImageWidth, availableImageHeight); backgroundShape.setAnchor(rect); } exportElementAttributes(backgroundShape, image, image.getLinePen(), image, hyperlinkShape); } protected static double getOffsetInPercent(double normalSize, double availableSize) { return -100000d * (availableSize - normalSize) / normalSize; } /** * */ protected void exportFrame(JRPrintFrame frame) throws JRException { Rectangle2D rect = new Rectangle2D.Double(frame.getX() + getOffsetX(), frame.getY() + getOffsetY(), frame.getWidth(), frame.getHeight()); XSLFAutoShape shape = PptxGraphics2D.getShape(rect, slide); exportElementAttributes(shape, frame, frame.getLineBox().getPen(), frame, null); setFrameElementsOffset(frame, false); frameIndexStack.add(Integer.valueOf(elementIndex)); exportElements(frame.getElements()); frameIndexStack.remove(frameIndexStack.size() - 1); restoreElementOffsets(); } /** * */ protected void exportGenericElement(JRGenericPrintElement element) { if (log.isDebugEnabled()) { log.debug("No PPTX-Shape generic element handler for " + element.getGenericType()); } } /** * */ public String getExporterPropertiesPrefix() { //FIXMEPPTX move this to abstract exporter return PPTX_EXPORTER_PROPERTIES_PREFIX; } /** * */ public String getExporterKey() { return PPTX_EXPORTER_KEY; } protected void setExporterHints() { if (jasperPrint.hasProperties() && jasperPrint.getPropertiesMap().containsProperty(JRXmlExporter.PROPERTY_REPLACE_INVALID_CHARS)) { // allows null values for the property invalidCharReplacement = jasperPrint.getProperty(JRXmlExporter.PROPERTY_REPLACE_INVALID_CHARS); } else { invalidCharReplacement = getPropertiesUtil().getProperty(JRXmlExporter.PROPERTY_REPLACE_INVALID_CHARS, jasperPrint); } } protected void embedFonts() throws JRException, IOException { RepositoryUtil ru = RepositoryUtil.getInstance(jasperReportsContext); List<FontFamily> ferList = jasperReportsContext.getExtensions(FontFamily.class); if (ferList == null || ferList.size() == 0) return; FontFactory fontfac = FontFactory.getInstance(); EOTWriter conv = new EOTWriter(true); // generate MicroTypeExpress (mtx) fonts CTEmbeddedFontList fontList = null; boolean anyFontsEmbedded = false; for (FontFamily ff : ferList) { if (!"embed".equals(ff.getExportFont(PPTX_EXPORTER_KEY))) { // don't export font continue; } anyFontsEmbedded = true; // "<p:font typeface=\"AllianzLogo\" pitchFamily=\"49\" charset=\"2\"/><p:regular r:id=\"rId13\"/>" FontFace ffTypes[] = { ff.getNormalFace(), ff.getBoldFace(), ff.getItalicFace(), ff.getBoldItalicFace() }; CTEmbeddedFontListEntry fntEntry = null; for (int i = 0; i < 4; i++) { if (ffTypes[i] == null) continue; String fileRelPath = ffTypes[i].getTtf(); String fntDataName = fileRelPath.replaceAll(".*/(.*).ttf", "$1.fntdata"); byte fontBytes[] = ru.getBytesFromLocation(fileRelPath); Font fonts[] = fontfac.loadFonts(fontBytes); assert (fonts != null && fonts.length == 1); WritableFontData eotFont = conv.convert(fonts[0]); PackagePartName partName; try { partName = PackagingURIHelper.createPartName("/ppt/fonts/" + fntDataName); } catch (InvalidFormatException e) { throw new IOException(e); } PackagePart part = ppt.getPackage().createPart(partName, "application/x-fontdata"); OutputStream partOs = part.getOutputStream(); eotFont.copyTo(partOs); partOs.close(); PackageRelationship prs = ppt.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font"); if (fontList == null) { fontList = ppt.getCTPresentation().addNewEmbeddedFontLst(); } if (fntEntry == null) { fntEntry = fontList.addNewEmbeddedFont(); CTTextFont fnt = fntEntry.addNewFont(); fnt.setTypeface(ff.getName()); // TODO set charset / pitchFamily } CTEmbeddedFontDataId fntId = null; switch (i) { case 0: fntId = fntEntry.addNewRegular(); break; case 1: fntId = fntEntry.addNewBold(); break; case 2: fntId = fntEntry.addNewItalic(); break; case 3: fntId = fntEntry.addNewBoldItalic(); break; } fntId.setId(prs.getId()); } } if (anyFontsEmbedded) { CTPresentation pres = ppt.getCTPresentation(); pres.setEmbedTrueTypeFonts(true); pres.setSaveSubsetFonts(true); } } protected int exportBackground() throws JRException { List<ExporterInputItem> items = exporterInput.getItems(); if (items == null || items.size() == 0) { return 0; } setCurrentExporterInputItem(items.get(0)); List<JRPrintPage> pages = jasperPrint.getPages(); List<JRPrintElement> backElem = new ArrayList<JRPrintElement>(); if (pages.size() >= 2) { // determine number of background elements List<JRPrintElement> pEl1 = pages.get(0).getElements(); List<JRPrintElement> pEl2 = pages.get(1).getElements(); for (int i = 0; i < pEl1.size(); i++) { JRPrintElement el1 = pEl1.get(i); if (pEl2.size() <= i) break; JRPrintElement el2 = pEl2.get(i); // reference identity doesn't work here // so we need to check for something in common // maybe bounds? if (el1.getX() == el2.getX() && el1.getY() == el2.getY() && el1.getWidth() == el2.getWidth() && el1.getHeight() == el2.getHeight() && el1.getClass().equals(el2.getClass())) { if (el1 instanceof JRTemplatePrintText) { JRTemplatePrintText jpr1 = (JRTemplatePrintText) el1; JRTemplatePrintText jpr2 = (JRTemplatePrintText) el2; JRStyledTextUtil jstu = JRStyledTextUtil.getInstance(getJasperReportsContext()); String str1 = jstu.getTruncatedText(jpr1); String str2 = jstu.getTruncatedText(jpr2); if (!str1.equals(str2)) break; // Special case - slide number fields in outline fonts // have to be rendered on every page if (str1.contains("{fld:slidenum}") && outlineFont(jpr1.getFontName(), getTextLocale(jpr1))) break; } backElem.add(el1); } else { break; } } } if (backElem.size() > 0) { XSLFSlideMaster master = ppt.getSlideMasters()[0]; slide = master; exportElements(backElem); } return backElem.size(); } public boolean outlineFont(String family, Locale locale) { return "curves".equals(exportFont(family, locale, true)); } public boolean embedFont(String family, Locale locale) { return "embed".equals(exportFont(family, locale, true)); } protected String exportFont(String family, Locale locale, boolean returnSpecial) { FontInfo fontInfo = FontUtil.getInstance(jasperReportsContext).getFontInfo(family, locale); if (fontInfo == null) return null; String mappedFont = fontInfo.getFontFamily().getExportFont(JRPptxExporter.PPTX_EXPORTER_KEY); boolean isSpecial = ("curves".equals(mappedFont) || "embed".equals(mappedFont)); return (mappedFont != null && (!isSpecial || returnSpecial)) ? mappedFont : family; } public String exportFont(String family, Locale locale) { return exportFont(family, locale, false); } public java.awt.Font loadFont(Map<Attribute, Object> attr, Locale locale) { String family = (String) attr.get(TextAttribute.FAMILY); FontInfo fontInfo = FontUtil.getInstance(jasperReportsContext).getFontInfo(family, locale); if (fontInfo == null || fontInfo.getFontFamily() == null) { return java.awt.Font.getFont(attr); } FontFamily ffamily = fontInfo.getFontFamily(); FontFace fface = null; if (fface == null && TextAttribute.WEIGHT_BOLD.equals(attr.get(TextAttribute.WEIGHT)) && TextAttribute.POSTURE_OBLIQUE.equals(attr.get(TextAttribute.POSTURE))) { fface = ffamily.getBoldItalicFace(); } if (fface == null && TextAttribute.WEIGHT_BOLD.equals(attr.get(TextAttribute.WEIGHT))) { fface = ffamily.getBoldFace(); } if (fface == null && TextAttribute.POSTURE_OBLIQUE.equals(attr.get(TextAttribute.POSTURE))) { fface = ffamily.getItalicFace(); } if (fface == null) { fface = ffamily.getNormalFace(); } if (fface == null) { return java.awt.Font.getFont(attr); } attr.remove(TextAttribute.FAMILY); return fface.getFont().deriveFont(attr); } }