From a7ea76cd827bd7bf29f7c0a1ef97b9a09460a853 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Fri, 10 Mar 2023 15:44:48 -0300 Subject: [PATCH 01/32] Support for PDFBox initial commit --- java/pom.xml | 11 + .../com/genexus/reports/PDFReportpdfbox.java | 2252 +++++++++++++++++ 2 files changed, 2263 insertions(+) create mode 100644 java/src/main/java/com/genexus/reports/PDFReportpdfbox.java diff --git a/java/pom.xml b/java/pom.xml index cad438cb5..2d93c46e9 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -126,6 +126,17 @@ itextasian 1.5.2 + + org.apache.pdfbox + pdfbox + 2.0.27 + + + * + * + + + com.sap.conn.jco sapjco3 diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java new file mode 100644 index 000000000..a9f0eb501 --- /dev/null +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -0,0 +1,2252 @@ +package com.genexus.reports; + +import java.awt.Color; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import com.genexus.CommonUtil; +import com.genexus.ModelContext; +import com.genexus.internet.HttpContext; +import com.genexus.platform.INativeFunctions; +import com.genexus.platform.NativeFunctions; +import com.genexus.util.TemporaryFiles; +import com.genexus.webpanels.HttpContextWeb; +import com.genexus.reports.fonts.PDFFont; +import com.genexus.reports.fonts.PDFFontDescriptor; +import com.genexus.reports.fonts.Type1FontMetrics; +import com.genexus.reports.fonts.Utilities; + +import org.apache.pdfbox.cos.*; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.common.PDStream; +import org.apache.pdfbox.pdmodel.font.*; +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.util.Matrix; + +public class PDFReportpdfbox implements IReportHandler{ + private int lineHeight, pageLines; + private org.apache.pdfbox.pdmodel.common.PDRectangle pageSize; // Contiene las dimensiones de la página + private int pageOrientation; // Indica la orientacion de las páginas + private PDType1Font font; + private PDType0Font baseFont; + private BarcodeUtil barcode = null; + private boolean fontUnderline; + private boolean fontStrikethru; + private int fontSize; + private boolean fontBold = false; + private boolean fontItalic = false; + private Color backColor, foreColor; + public static PrintStream DEBUG_STREAM = System.out; + private OutputStream outputStream = null; // Contiene el OutputStream de salida del reporte + //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página + private static ParseINI props = new ParseINI(); + private ParseINI printerSettings; + private String form; + private Vector stringTotalPages; // Contiene la lista de locations del parámetros {{Pages}} + private boolean isPageDirty; // Indica si la pagina NO se debe 'dispose()'ar pues se le va a agregar cosas al terminar el PDF + private int outputType = -1; // Indica el tipo de Output que se desea para el documento + private int printerOutputMode = -1; // Indica si se debe mostrar el cuadro de Impresion para la salida por impresora + private boolean modal = false; // Indica si el diálogo debe ser modal o no modal en + private String docName = "PDFReport.pdf"; // Nombre del documento a generar (se cambia con GxSetDocName) + private static INativeFunctions nativeCode = NativeFunctions.getInstance(); + private static Hashtable fontSubstitutes = new Hashtable<>(); // Contiene la tabla de substitutos de fonts (String <--> String) + private static String configurationFile = null; + private static String configurationTemplateFile = null; + private static String defaultRelativePrepend = null; // En aplicaciones web, contiene la ruta al root de la aplicación para ser agregado al inicio de las imagenes con path relativo + private static String defaultRelativePrependINI = null; + private static String webAppDir = null; + //private boolean containsSpecialMetrics = false; + //private Hashtable fontMetricsProps = new Hashtable(); + public static boolean DEBUG = false; + private PDDocument document; + private PDDocument writer; + private PDPageContentStream chunk; + private int currLine; + private int lastLine = 0; + private static String predefinedSearchPath = ""; // Contiene los predefinedSearchPaths + private float leftMargin; + private float topMargin; + private float bottomMargin; //If Margin Bottom is not specified 6 lines are assumed (nlines =6). + + private PDPageContentStream template; + private PDType0Font templateFont; + private int templateFontSize; + private boolean backFill = true; + private Color templateColorFill; + private int pages=0; + private boolean templateCreated = false; + public static float DASHES_UNITS_ON = 10; + public static float DASHES_UNITS_OFF = 10; + public static float DOTS_UNITS_OFF = 3; + public static float DOTS_UNITS_ON = 1; + public boolean lineCapProjectingSquare = true; + public boolean barcode128AsImage = true; + ConcurrentHashMap documentImages; + Matrix rundirection = new Matrix(1, 0, 0, 1, 0, 0); + public int justifiedType; + private HttpContext httpContext = null; + float[] STYLE_SOLID = new float[]{1,0};//0 + float[] STYLE_NONE = null;//1 + float[] STYLE_DOTTED, //2 + STYLE_DASHED, //3 + STYLE_LONG_DASHED, //4 + STYLE_LONG_DOT_DASHED; //5 + int STYLE_NONE_CONST=1; + + private enum VerticalAlign{ + TOP(0), + MIDDLE(1), + BOTTOM(2); + private int intValue; + VerticalAlign(int val) + { + this.intValue=val; + } + public int value(){ + return intValue; + } + } + + /** Setea el OutputStream a utilizar + * @param outputStream Stream a utilizar + */ + public void setOutputStream(OutputStream outputStream) + { + this.outputStream = outputStream; + } + + /** Busca la ubicación del Acrobat. Si no la encuentra tira una excepción + */ + private static String getAcrobatLocation() throws Exception + { + ParseINI props; + try + { + props = new ParseINI(Const.INI_FILE); + if(new File(Const.INI_FILE).length() == 0) + new File(Const.INI_FILE).delete(); + } + catch(IOException e) + { + props = new ParseINI(); + } + + // Primero debo obtener la ubicación + ejecutable del Acrobat + String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property + if(acrobatLocation == null) + { + if(NativeFunctions.isUnix()) + { // Si estoy en Unix no puedo ir a buscar el registry ;) + throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); + } + } + return acrobatLocation; + } + + /** Manda a imprimir el reporte a la impresora + * Si en las properties del PDFReport esta definida una GeneralProperty 'Acrobat Location' se + * utiliza esta property para obtener la ubicación + ejecutable del Acrobat, sino se busca en el Registry + * @param pdfFilename Nombre del reporte a imprimir (con extensión) + * @param silent Booleano que indica si se va a imprimir sin diálogo + * @exception Exception si no se puede realizar la operación + */ + public static void printReport(String pdfFilename, boolean silent) throws Exception + { + if(NativeFunctions.isWindows()) + { // En Windows obtenemos el full path + // En Linux esto no anda bien + pdfFilename = "\"" + new File(pdfFilename).getAbsolutePath() + "\""; + } + + String [] cmd = {}; + String acrobatLocation = null; + try + { + // Primero debo obtener la ubicación + ejecutable del Acrobat + acrobatLocation = getAcrobatLocation(); + }catch(Exception acrobatNotFound) + { + throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); + } + + //Se genera el PostScript + nativeCode.executeModal(acrobatLocation + " -toPostScript " + pdfFilename, false); + + //Se manda a imprimir a la impresora default + int pos = pdfFilename.lastIndexOf("."); + pdfFilename = pdfFilename.substring(0, pos) + ".ps"; + cmd = new String[] { "lp", pdfFilename}; + Runtime.getRuntime().exec(cmd); + } + + /** Muestra el reporte en pantalla + * @param filename nombre del PDF a mostrar + * @param modal indica si el PDF se va a mostrar en diálogo modal + * @exception Exception no se puede encontrar el Acrobat + */ + public static void showReport(String filename, boolean modal) throws Exception + { + if(NativeFunctions.isWindows()) + { // En Windows obtenemos el full path + // En Linux esto no anda bien + filename = "\"" + new File(filename).getAbsolutePath() + "\""; + } + String acrobatLocation; + try + { + // Primero debo obtener la ubicación + ejecutable del Acrobat + acrobatLocation = getAcrobatLocation(); + }catch(Exception acrobatNotFound) + { + throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); + } + + if(modal) + { + nativeCode.executeModal(acrobatLocation + " " + filename, true); + } + else + { + Runtime.getRuntime().exec(new String[] { acrobatLocation, filename}); + } + } + + private static char alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; + + public PDFReportpdfbox(ModelContext context) + { + document = null; + pageSize = null; + stringTotalPages = new Vector(); + documentImages = new ConcurrentHashMap(); + httpContext = (HttpContext) context.getHttpContext(); + + if(defaultRelativePrepend == null) + { + defaultRelativePrepend = httpContext.getDefaultPath(); + if(defaultRelativePrepend == null || defaultRelativePrepend.trim().equals("")) + defaultRelativePrepend = ""; + else + defaultRelativePrepend = defaultRelativePrepend.replace(alternateSeparator, File.separatorChar) + File.separatorChar; + defaultRelativePrependINI = defaultRelativePrepend; + if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) + { + configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; // Esto es para que en aplicaciones web el PDFReport.INI no quede visible en el server + configurationTemplateFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_TEMPLATE_FILE; + } + else + { + configurationFile = defaultRelativePrepend + Const.INI_FILE; + configurationTemplateFile = defaultRelativePrepend + Const.INI_TEMPLATE_FILE; + } + webAppDir = defaultRelativePrepend; + + if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) + { + // @cambio: 23/07/03 + // Para los reportes en el web, debemos tener en cuenta la preference 'Static Content Base URL' del modelo + // Pero SOLO la tenemos en cuenta si es un directorio relativo + // O sea, si la preference dice algo tipo /pepe, entonces vamos a buscar las + // imagenes relativas a %WebApp%/pepe, pero si la preference dice algo tipo + // 'http://otroServer/xxxyyy' entonces ahi no le damos bola a la preference! + // Además, para mantener compatibilidad con las aplicaciones hasta ahora, si la imagen + // no se encuentra all\uFFFDElo que hacemos es ir a buscarla a %WebApp% + + // @cambio: 12/09/17 + // Esto tambien se tiene que hacer para los reportes web que se llaman con submit + // (ese es el caso en el cual el getDefaultPath no es Empty) + + String staticContentBase = httpContext.getStaticContentBase(); + if(staticContentBase != null) + { + staticContentBase = staticContentBase.trim(); + if(staticContentBase.indexOf(':') == -1) + { // Si la staticContentBase es una ruta relativa + staticContentBase = staticContentBase.replace(alternateSeparator, File.separatorChar); + if(staticContentBase.startsWith(File.separator)) + { + staticContentBase = staticContentBase.substring(1); + } + if(!staticContentBase.equals("")) + { + defaultRelativePrepend += staticContentBase; + if(!defaultRelativePrepend.endsWith(File.separator)) + { + defaultRelativePrepend += File.separator; + } + } + } + } + } + } + if (firstTime) + { + loadProps(); + firstTime = false; + } + } + + private static boolean firstTime = true; + + private void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) + { + if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) + { + iniFile = defaultRelativePrependINI + Const.WEB_INF + File.separatorChar + iniFile; + } + else + { + iniFile = defaultRelativePrependINI + iniFile; + } + + try + { + this.form = form; + printerSettings = new ParseINI(iniFile); + } + catch(IOException e){ printerSettings = new ParseINI(); } + + mode = (mode==2)?3:0; + + printerSettings.setupProperty(form, Const.PRINTER, printer); + printerSettings.setupProperty(form, Const.MODE, mode + ""); + printerSettings.setupProperty(form, Const.ORIENTATION, orientation+ ""); + printerSettings.setupProperty(form, Const.PAPERSIZE, pageSize+ ""); + printerSettings.setupProperty(form, Const.PAPERLENGTH, pageLength+ ""); + printerSettings.setupProperty(form, Const.PAPERWIDTH, pageWidth+ ""); + printerSettings.setupProperty(form, Const.SCALE, scale+ ""); + printerSettings.setupProperty(form, Const.COPIES, copies+ ""); + printerSettings.setupProperty(form, Const.DEFAULTSOURCE, defSrc+ ""); + printerSettings.setupProperty(form, Const.PRINTQUALITY, quality+ ""); + printerSettings.setupProperty(form, Const.COLOR, color+ ""); + printerSettings.setupProperty(form, Const.DUPLEX, duplex+ ""); + } + + private void loadProps() + { + try{ + props = new ParseINI(configurationFile, configurationTemplateFile); + }catch(IOException e){ props = new ParseINI(); } + + props.setupGeneralProperty(Const.PDF_REPORT_INI_VERSION_ENTRY, Const.PDF_REPORT_INI_VERSION); + props.setupGeneralProperty(Const.EMBEED_SECTION, Const.EMBEED_DEFAULT); + props.setupGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, Const.EMBEED_DEFAULT); + props.setupGeneralProperty(Const.SEARCH_FONTS_ALWAYS, "false"); + props.setupGeneralProperty(Const.SEARCH_FONTS_ONCE, "true"); + props.setupGeneralProperty(Const.SERVER_PRINTING, "false"); + props.setupGeneralProperty(Const.ADJUST_TO_PAPER, "true"); + props.setupGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE, Const.DEFAULT_LINE_CAP_PROJECTING_SQUARE); + props.setupGeneralProperty(Const.BARCODE128_AS_IMAGE, Const.DEFAULT_BARCODE128_AS_IMAGE); + props.setupGeneralProperty("DEBUG", "false"); + props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); + props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); + props.setupGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER); + props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); + props.setupGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "."); + props.setupGeneralProperty(Const.LEADING, "2"); + props.setupGeneralProperty(Const.RUN_DIRECTION, Const.RUN_DIRECTION_LTR); + props.setupGeneralProperty(Const.JUSTIFIED_TYPE_ALL, "false"); + + props.setupGeneralProperty(Const.STYLE_DOTTED, Const.DEFAULT_STYLE_DOTTED); + props.setupGeneralProperty(Const.STYLE_DASHED, Const.DEFAULT_STYLE_DASHED); + props.setupGeneralProperty(Const.STYLE_LONG_DASHED, Const.DEFAULT_STYLE_LONG_DASHED); + props.setupGeneralProperty(Const.STYLE_LONG_DOT_DASHED, Const.DEFAULT_STYLE_LONG_DOT_DASHED); + + loadSubstituteTable(); // Cargo la tabla de substitutos de fonts + + if(props.getBooleanGeneralProperty("DEBUG", false)) + { + DEBUG = true; + DEBUG_STREAM = System.out; + } + else + { + DEBUG = false; + DEBUG_STREAM = new PrintStream(new com.genexus.util.NullOutputStream()); + } + + Utilities.addPredefinedSearchPaths(new String[]{System.getProperty("java.awt.fonts", "c:\\windows\\fonts"), + System.getProperty("com.ms.windir", "c:\\windows") + "\\fonts"}); + } + + public static final void addPredefinedSearchPaths(String [] predefinedPaths) + { + String predefinedPath = ""; + for(int i = 0; i < predefinedPaths.length; i++) + predefinedPath += predefinedPaths[i] + ";"; + predefinedSearchPath = predefinedPath + predefinedSearchPath; // SearchPath= los viejos más los nuevos + } + + public static final String getPredefinedSearchPaths() + { + return predefinedSearchPath; + } + + private void init() + { + try { + document = new PDDocument(); + document.addPage(new PDPage()); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(((ByteArrayOutputStream) outputStream).toByteArray()); + PDDocument document = PDDocument.load(byteArrayInputStream); + } + catch(Exception e) { + System.err.println(e.getMessage()); + } + } + + private void fin() + { + try { + document.save(outputStream); + document.close(); + outputStream.close(); + } + catch(Exception e) { + System.err.println(e.getMessage()); + } + } + + public void GxRVSetLanguage(String lang) + { + } + + public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) + { + } + + private float[] parsePattern(String patternStr) + { + if (patternStr!=null) + { + StringTokenizer st = new StringTokenizer(patternStr.trim(), ";"); + int length = st.countTokens(); + if (length>0) + { + int i = 0; + float[] pattern = new float[length]; + while(st.hasMoreTokens()) + { + pattern[i] = Float.parseFloat(st.nextToken()); + i++; + } + return pattern; + } + } + return null; + } + + private float [] getDashedPattern(int style) + { + switch(style) + { + case 0: return STYLE_SOLID; + case 1: return STYLE_NONE; + case 2: return STYLE_DOTTED; + case 3: return STYLE_DASHED; + case 4: return STYLE_LONG_DASHED; + case 5: return STYLE_LONG_DOT_DASHED; + default: + return STYLE_SOLID; + } + } + + /** + * @param hideCorners indica si se deben ocultar los triangulos de las esquinas cuando el lado que los une esta oculto. + */ + private void drawRectangle(PDPageContentStream cb, float x, float y, float w, float h, + int styleTop, int styleBottom, int styleRight, int styleLeft, + float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) + { + + + float[] dashPatternTop = getDashedPattern(styleTop); + float[] dashPatternBottom = getDashedPattern(styleBottom); + float[] dashPatternLeft = getDashedPattern(styleLeft); + float[] dashPatternRight = getDashedPattern(styleRight); + + try { + //-------------------bottom line--------------------- + if (styleBottom!=STYLE_NONE_CONST) + { + cb.setLineDashPattern(dashPatternBottom, 0); + } + + float b = 0.4477f; + if (radioBL>0) + { + cb.moveTo(x + radioBL, y); + } + else + { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) + { + cb.moveTo(x + penAux, y); + } + else + { + cb.moveTo(x, y); + } + } + + //-------------------bottom right corner--------------------- + + if (styleBottom!=STYLE_NONE_CONST)//si es null es Style None y no traza la linea + { + if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) + { + cb.lineTo(x + w - penAux, y); + } + else + { + cb.lineTo(x + w - radioBR, y); + } + if (radioBR>0 && styleRight!=STYLE_NONE_CONST) + { + cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + } + + //-------------------right line--------------------- + + if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) + { + cb.stroke(); + cb.setLineDashPattern(dashPatternRight, 0); + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) + { + cb.moveTo(x + w, y + penAux); + } + else + { + cb.moveTo(x + w, y + radioBR); + } + } + + //-------------------top right corner--------------------- + if (styleRight!=STYLE_NONE_CONST) + { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) + { + cb.lineTo (x + w, y + h - penAux); + } + else + { + cb.lineTo (x + w, y + h - radioTR); + } + if (radioTR>0 && styleTop!=STYLE_NONE_CONST) + { + cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + } + + //-------------------top line--------------------- + + if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) + { + cb.stroke(); + cb.setLineDashPattern(dashPatternTop, 0); + if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) + { + cb.moveTo(x + w - penAux, y + h); + } + else + { + cb.moveTo(x + w - radioTR, y + h); + } + } + + //-------------------top left corner--------------------- + if (styleTop!=STYLE_NONE_CONST) + { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) + { + cb.lineTo(x + penAux, y + h); + } + else + { + cb.lineTo(x + radioTL, y + h); + } + if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) + { + cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + } + + //-------------------left line--------------------- + + if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) + { + cb.stroke(); + cb.setLineDashPattern(dashPatternLeft, 0); + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) + { + cb.moveTo(x, y + h - penAux); + } + else + { + cb.moveTo(x, y + h - radioTL); + } + } + + //-------------------bottom left corner--------------------- + if (styleLeft!=STYLE_NONE_CONST) + { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) + { + cb.lineTo(x, y + penAux); + } + else + { + cb.lineTo(x, y + radioBL); + } + if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) + { + cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } + cb.stroke(); + } catch (IOException ioe) { + System.err.println(ioe.getMessage()); + } + } + + private void roundRectangle(PDPageContentStream cb, float x, float y, float w, float h, + float radioTL, float radioTR, float radioBL, float radioBR) + { + try { + //-------------------bottom line--------------------- + + float b = 0.4477f; + if (radioBL>0) + { + cb.moveTo(x + radioBL, y); + } + else + { + cb.moveTo(x, y); + } + + //-------------------bottom right corner--------------------- + + cb.lineTo(x + w - radioBR, y); + if (radioBR>0) + { + cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + + + cb.lineTo (x + w, y + h - radioTR); + if (radioTR>0) + { + cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + + cb.lineTo(x + radioTL, y + h); + if (radioTL>0) + { + cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + cb.lineTo(x, y + radioBL); + if (radioBL>0) + { + cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } catch (IOException ioe) { + System.err.println(ioe.getMessage()); + } + } + + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) + { + GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, 0, 0); + } + + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int style, int cornerRadius) + { + GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, style, style, style, style, cornerRadius, cornerRadius, cornerRadius, cornerRadius); + } + + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) + { + try{ + + PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + + float penAux = (float)convertScale(pen); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + cb.saveGraphicsState(); + + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.getUpperRightY() - topAux - topMargin -bottomMargin; + + cb.setLineWidth(penAux); + cb.setLineCapStyle(2); + + if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) + { + //Tengo que hacer eso para que el borde quede del mismo color que el fill si se indica que no se quiere borde, + //porque no funciona el setLineWidth + if (pen > 0) + cb.setStrokingColor(foreRed, foreGreen, foreBlue); + else + cb.setStrokingColor (backRed, backGreen, backBlue); + + cb.addRect(x1, y1, x2 - x1, y2 - y1); + + if (backMode!=0) + { + cb.setNonStrokingColor(new Color(backRed, backGreen, backBlue)); + cb.fillAndStroke(); + } + cb.closePath(); + cb.stroke(); + } + else + { + float w = x2 - x1; + float h = y2 - y1; + if (w < 0) + { + x1 += w; + w = -w; + } + if (h < 0) + { + y1 += h; + h = -h; + } + + float cRadioTL = (float)convertScale(cornerRadioTL); + float cRadioTR = (float)convertScale(cornerRadioTR); + float cRadioBL = (float)convertScale(cornerRadioBL); + float cRadioBR = (float)convertScale(cornerRadioBR); + + // Scale the radius if it's too large or to small to fit. + int max = (int)Math.min(w, h); + cRadioTL = Math.max(0, Math.min(cRadioTL, max/2)); + cRadioTR = Math.max(0, Math.min(cRadioTR, max/2)); + cRadioBL = Math.max(0, Math.min(cRadioBL, max/2)); + cRadioBR = Math.max(0, Math.min(cRadioBR, max/2)); + + if (backMode!=0) + { + //Interior del rectangulo + cb.setStrokingColor(backRed, backGreen, backBlue); + cb.setLineWidth(0); + roundRectangle(cb, x1, y1, w, h, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR); + cb.setNonStrokingColor(new Color(backRed, backGreen, backBlue)); + cb.fillAndStroke(); + cb.setLineWidth(penAux); + } + if (pen > 0) + { + //Bordes del rectangulo + cb.setStrokingColor(foreRed, foreGreen, foreBlue); + drawRectangle(cb, x1, y1, w, h, + styleTop, styleBottom, styleRight, styleLeft, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR, penAux, false); + } + } + cb.restoreGraphicsState(); + + if(DEBUG)DEBUG_STREAM.println("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); + } catch (Exception e) { + + } + } + + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) + { + GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); + } + + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) + { + try { + PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + + float widthAux = (float)convertScale(width); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + if(DEBUG)DEBUG_STREAM.println("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + + float x1, y1, x2, y2; + + x1 = leftAux + leftMargin; + y1 = pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.getUpperRightY() - topAux - topMargin -bottomMargin; + + cb.saveGraphicsState(); + cb.setStrokingColor(foreRed, foreGreen, foreBlue); + cb.setLineWidth(widthAux); + + if (lineCapProjectingSquare) + { + cb.setLineCapStyle(2); //Hace que lineas de width 10 por ejemplo que forman una esquina no quedan igual que en disenio porque "rellena" la esquina. + } + if (style!=0) + { + float[] dashPattern = getDashedPattern(style); + cb.setLineDashPattern(dashPattern, 0); + } + cb.moveTo(x1, y1); + cb.lineTo(x2, y2); + cb.stroke(); + + cb.restoreGraphicsState(); + } catch (Exception e){ + + } + } + + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom) + { + GxDrawBitMap(bitmap, left, top, right, bottom, 0); + } + + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) + { + try + { + PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + + //java.awt.Image image; + org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject image; + org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject imageRef; + try + { + if (documentImages != null && documentImages.containsKey(bitmap)) + { + image = documentImages.get(bitmap); + } + else + { + + if (!NativeFunctions.isWindows() && new File(bitmap).isAbsolute() && bitmap.startsWith(httpContext.getStaticContentBase())) + { + bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); + } + + if (!new File(bitmap).isAbsolute() && !bitmap.toLowerCase().startsWith("http:") && !bitmap.toLowerCase().startsWith("https:")) + { + if (bitmap.startsWith(httpContext.getStaticContentBase())) + { + bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); + } + // Si la ruta a la imagen NO es absoluta, en aplicaciones Web le agregamos al comienzo la ruta al root de la aplicación + // más la staticContentBaseURL si ésta es relativa. + image = PDImageXObject.createFromFile(defaultRelativePrepend + bitmap,document); + //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(defaultRelativePrepend + bitmap); + if(image == null) + { // Si all\uFFFDEno se encuentra la imagen, entonces la buscamos bajo el webAppDir (para mantener compatibilidad) + bitmap = webAppDir + bitmap; + image = PDImageXObject.createFromFile(bitmap,document); + //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); + } + else + { + bitmap = defaultRelativePrepend + bitmap; + } + } + else + { + image = PDImageXObject.createFromFile(bitmap,document); + //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); + } + } + } + catch(java.lang.IllegalArgumentException ex)//Puede ser una url absoluta + { + java.net.URL url= new java.net.URL(bitmap); + image = PDImageXObject.createFromFile(url.toString(),document); + } + + if (documentImages == null) + { + documentImages = new ConcurrentHashMap(); + } + documentImages.putIfAbsent(bitmap, image); + + + if(DEBUG)DEBUG_STREAM.println("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + + if(image != null) + { // Si la imagen NO se encuentra, no hago nada + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + float x = leftAux + leftMargin; + float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin; + + if (aspectRatio == 0) + cb.drawImage(image, x, y, image.getWidth(), image.getHeight()); + else + cb.drawImage(image, x, y, image.getWidth() * aspectRatio, image.getHeight() * aspectRatio); + cb.close(); + } + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } + } + + public String getSubstitute(String fontName) + { + Vector fontSubstitutesProcessed = new Vector<>(); + String newFontName = fontName; + while( fontSubstitutes.containsKey(newFontName)) + { + if (!fontSubstitutesProcessed.contains(newFontName)) + { + fontSubstitutesProcessed.addElement(newFontName); + newFontName = fontSubstitutes.get(newFontName); + } + else + { + return fontSubstitutes.get(newFontName); + } + } + return newFontName; + } + + public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) + { + boolean isCJK = false; + boolean embeedFont = isEmbeddedFont(fontName); + String originalFontName = fontName; + if (!embeedFont) + { + fontName = getSubstitute(fontName); // Veo si hay substitutos solo si el font no va a ir embebido + } + if(DEBUG) + { + String fontSubstitute = ""; + if (!originalFontName.equals(fontName)) + { + fontSubstitute = "Original Font: " + originalFontName + " Substitute"; + } + DEBUG_STREAM.println("GxAttris: "); + DEBUG_STREAM.println("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + DEBUG_STREAM.println("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + DEBUG_STREAM.println("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + } + + if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) + { + barcode = new Barcode128(); + barcode.setCodeType(Barcode128.CODE128); + } + else + { + barcode = null; + } + this.fontUnderline = fontUnderline; + this.fontStrikethru = fontStrikethru; + this.fontSize = fontSize; + this.fontBold = fontBold; + this.fontItalic = fontItalic; + foreColor = new Color(foreRed, foreGreen, foreBlue); + backColor = new Color(backRed, backGreen, backBlue); + + backFill = (backMode != 0); + try { + if (PDFFont.isType1(fontName)) + { + //Me fijo si es un Asian font + for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) + { + if(Type1FontMetrics.CJKNames[i][0].equalsIgnoreCase(fontName) || + Type1FontMetrics.CJKNames[i][1].equalsIgnoreCase(fontName)) + { + String style = ""; + if (fontBold && fontItalic) + style = "BoldItalic"; + else + { + if (fontItalic) + style = "Italic"; + if (fontBold) + style = "Bold"; + } + setAsianFont(fontName, style); + isCJK = true; + break; + } + } + if (!isCJK) + { + int style = 0; + if (fontBold && fontItalic) + style = style + 3; + else + { + if (fontItalic) + style = style + 2; + if (fontBold) + style = style + 1; + } + for(int i=0;i= 2 && !((align & 16) == 16) && htmlformat != 1) + { + if (valign == PDFReportpdfbox.VerticalAlign.TOP.value()) + bottom = top + (int)reconvertScale(lineHeight); + else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) + top = bottom - (int)reconvertScale(lineHeight); + //if valign == middle, no se cambia ni top ni bottom + } + + float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; + //Al bottom de los textos se le resta espacio entre el texto y el borde del textblock, + //porque en el reporte genexus la x,y de un + //text es la x,y del cuadro que contiene el texto, y la api de itext espera la x,y del texto en si. + //Generalmente el cuadro es mas grande que lo que ocupa el texto realmente (depende del tipo de font) + //captionHeight esta convertido, bottom y top no. + float topAux = (float)convertScale(top) + ((float)convertScale(bottom-top) - captionHeight)/2; + + + float startHeight = bottomAux - topAux - captionHeight; + + float leftAux = (float)convertScale(left); + float rightAux = (float)convertScale(right); + int alignment = align & 3; + boolean autoResize = (align & 256) == 256; + + if (htmlformat == 1) + { + StyleSheet styles = new StyleSheet(); + Hashtable locations = getFontLocations(); + for (Enumeration e = locations.keys(); e.hasMoreElements() ;) + { + String fontName = (String)e.nextElement(); + String fontPath = (String)locations.get(fontName); + if (fontPath.equals("")) + { + fontPath = PDFFontDescriptor.getTrueTypeFontLocation(fontName, props); + } + if (!fontPath.equals("")) + { + FontFactory.register(fontPath, fontName); + styles.loadTagStyle("body", "face", fontName); + + if (isEmbeddedFont(fontName)){ + styles.loadTagStyle("body", "encoding", BaseFont.IDENTITY_H); + } + else{ + styles.loadTagStyle("body", "encoding", BaseFont.WINANSI); + } + } + } + + //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. + bottomAux = (float)convertScale(bottom); + topAux = (float)convertScale(top); + + ColumnText Col = new ColumnText(cb); + int colAlignment = columnAlignment(alignment); + if (colAlignment!=0) + Col.setAlignment(colAlignment); + ColumnText simulationCol = new ColumnText(null); + float drawingPageHeight = (float)this.pageSize.getTop() - topMargin - bottomMargin; + //Col.setSimpleColumn(llx, lly, urx, ury); + Col.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); + simulationCol.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); + + try + { + ArrayList objects = HTMLWorker.parseToList(new StringReader(sTxt), styles); + for (int k = 0; k < objects.size(); ++k) + { + if (pageHeightExceeded(bottomAux, drawingPageHeight)) + { + simulationCol.addElement((Element)objects.get(k)); + simulationCol.go(true); + + if (simulationCol.getYLine() < bottomMargin) + { + GxEndPage(); + GxStartPage(); + simulationCol = new ColumnText(null); + simulationCol.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); + simulationCol.addElement((Element)objects.get(k)); + + Col = new ColumnText(cb); + if (colAlignment!=0) + Col.setAlignment(colAlignment); + Col.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); + + bottomAux = bottomAux - drawingPageHeight; + } + } + if (objects.get(k) instanceof Paragraph && colAlignment!=0) + ((Paragraph)objects.get(k)).setAlignment(colAlignment); + + Col.addElement((Element)objects.get(k)); + Col.go(); + } + }catch(Exception de){ + System.out.println("ERROR printing HTML text " + de.getMessage()); + } + } + else + if (barcode!=null) + { + if(DEBUG)DEBUG_STREAM.println("Barcode: --> " + barcode.getClass().getName()); + try + { + barcode.setCode(sTxt); + barcode.setTextAlignment(alignment); + com.lowagie.text.Rectangle rectangle = new com.lowagie.text.Rectangle(0, 0); + //El rectangulo tiene tamaño ok. + switch (alignment) + { + case 1: // Center Alignment + rectangle = new com.lowagie.text.Rectangle((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + (float)this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin, + (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, + (float)this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 2: // Right Alignment + rectangle = new com.lowagie.text.Rectangle(rightAux + leftMargin - rectangleWidth, + (float)this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin, + rightAux + leftMargin, + (float)this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 0: // Left Alignment + rectangle = new com.lowagie.text.Rectangle(leftAux + leftMargin, + (float)this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin, + leftAux + leftMargin + rectangleWidth, + (float)this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); + break; + } + barcode.setAltText(""); + barcode.setBaseline(0); + //barcode.Size = 0; + + if (fontSize < Const.LARGE_FONT_SIZE) + barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_SMALL_FONT); + else + barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_LARGE_FONT); + + PDImageXObject imageCode = barcode.createImageWithBarcode(cb, backFill ? backColor : null, foreColor); + imageCode.setAbsolutePosition(leftAux + leftMargin, rectangle.getBottom()); + barcode.setBarHeight(rectangle.getHeight()); + imageCode.scaleToFit(rectangle.getWidth(), rectangle.getHeight()); + document.add(imageCode); + } + catch (Exception ex) + { + if(DEBUG)DEBUG_STREAM.println("Error generating Barcode: --> " + barcode.getClass().getName() + ex.getMessage()); + if(DEBUG)ex.printStackTrace (); + } + } + else + { + + if(backFill) + { + com.lowagie.text.Rectangle rectangle = new com.lowagie.text.Rectangle(0,0); + //Si el texto tiene background lo dibujo de esta forma + switch(alignment) + { + case 1: // Center Alignment + rectangle = new com.lowagie.text.Rectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); + break; + case 2: // Right Alignment + rectangle = new com.lowagie.text.Rectangle(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , rightAux + leftMargin, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); + break; + case 0: // Left Alignment + rectangle = new com.lowagie.text.Rectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); + break; + } + rectangle.setBackgroundColor(backColor); + try + { + document.add(rectangle); + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } + } + + float underlineSeparation = lineHeight / 5;//Separacion entre el texto y la linea del subrayado + int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation/4); + com.lowagie.text.Rectangle underline; + + //Si el texto esta subrayado + if (fontUnderline) + { + underline = new com.lowagie.text.Rectangle(0,0); + + switch(alignment) + { + case 1: // Center Alignment + underline = new com.lowagie.text.Rectangle( + (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, + (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + break; + case 2: // Right Alignment + underline = new com.lowagie.text.Rectangle( rightAux + leftMargin - rectangleWidth , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, + rightAux + leftMargin, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + break; + case 0: // Left Alignment + underline = new com.lowagie.text.Rectangle( leftAux + leftMargin , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, + leftAux + leftMargin + rectangleWidth, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + break; + } + underline.setBackgroundColor(foreColor); + try + { + document.add(underline); + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } + } + + //Si el texto esta tachado + if (fontStrikethru) + { + underline = new com.lowagie.text.Rectangle(0,0); + float strikethruSeparation = lineHeight / 2; + + switch(alignment) + { + case 1: // Center Alignment + underline = new com.lowagie.text.Rectangle( + (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, + (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + break; + case 2: // Right Alignment + underline = new com.lowagie.text.Rectangle( rightAux + leftMargin - rectangleWidth , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, + rightAux + leftMargin, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + break; + case 0: // Left Alignment + underline = new com.lowagie.text.Rectangle( leftAux + leftMargin , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, + leftAux + leftMargin + rectangleWidth, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + break; + } + underline.setBackgroundColor(foreColor); + try + { + document.add(underline); + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } + } + + if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) + {// Si el texto es la cantidad de páginas del documento + if (!templateCreated) + { + template = cb.createTemplate(right - left, bottom - top); + templateCreated = true; + } + cb.addTemplate(template, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin); + templateFont = baseFont; + templateFontSize = fontSize; + templateColorFill = foreColor; + return; + } + + float textBlockWidth = rightAux - leftAux; + float TxtWidth = baseFont.getWidthPoint(sTxt, fontSize); + boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; + boolean wrap = ((align & 16) == 16); + + //Justified + if (wrap || justified) + { + //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. + bottomAux = (float)convertScale(bottomOri); + topAux = (float)convertScale(topOri); + + //La constante 2 para LEADING indica la separacion que se deja entre un renglon y otro. (es lo que mas se asemeja a la api vieja). + float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); + Paragraph p = new Paragraph(sTxt, font); + + float llx = leftAux + leftMargin; + float lly = (float)this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin; + float urx = rightAux + leftMargin; + float ury = (float)this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin; + + try{ + DrawColumnText(cb, llx, lly, urx, ury, p, leading, runDirection, valign, alignment); + } + catch (Exception e) + { + e.printStackTrace(System.err); + } + } + else //no wrap + { + startHeight=0; + if (!autoResize) + { + //Va quitando el ultimo char del texto hasta que llega a un string cuyo ancho se pasa solo por un caracter + //del ancho del textblock ("se pasa solo por un caracter": esto es porque en el caso general es ese el texto que + //mas se parece a lo que se disenia en genexus). + String newsTxt = sTxt; + while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) + { + sTxt = newsTxt; + newsTxt = newsTxt.substring(0, newsTxt.length()-1); + TxtWidth = baseFont.getWidthPoint(newsTxt, fontSize); + } + } + + Phrase phrase = new Phrase(sTxt, font); + switch(alignment) + { + case 1: // Center Alignment + ColumnText.showTextAligned(cb, cb.ALIGN_CENTER, phrase, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); + break; + case 2: // Right Alignment + ColumnText.showTextAligned(cb, cb.ALIGN_RIGHT, phrase, rightAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + ColumnText.showTextAligned(cb, cb.ALIGN_LEFT, phrase, leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); + break; + } + } + } + } + boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ + return bottomAux > drawingPageHeight; + } + PDPageContentStream SimulateDrawColumnText(PDPageContentStream cb, PDRectangle rect, PDPageContentStream p, float leading, int runDirection, int alignment) throws DocumentException + { + // Recordar que p es un parrafo + ColumnText Col = new ColumnText(cb); + Col.setRunDirection(runDirection); + Col.setAlignment(alignment); + Col.setLeading(leading, 1); + Col.setSimpleColumn(rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()); + Col.addText(p); + Col.go(true); + return Col; + } + void DrawColumnText(PdfContentByte cb, float llx, float lly, float urx, float ury, Paragraph p, float leading, int runDirection, int valign, int alignment) throws DocumentException + { + Rectangle rect = new Rectangle(llx, lly, urx, ury); + ColumnText ct = SimulateDrawColumnText(cb, rect, p, leading, runDirection, alignment);//add the column in simulation mode + float y = ct.getYLine(); + int linesCount = ct.getLinesWritten(); + + //calculate a new rectangle for valign = middle + if (valign == PDFReportItext.VerticalAlign.MIDDLE.value()) + ury = ury - ((y - lly) / 2) + leading; + else if (valign == PDFReportItext.VerticalAlign.BOTTOM.value()) + ury = ury - (y - lly- leading); + else if (valign == PDFReportItext.VerticalAlign.TOP.value()) + ury = ury + leading/2; + + rect = new Rectangle(llx, lly, urx, ury); //Rectangle for new ury + + ColumnText Col = new ColumnText(cb); + Col.setRunDirection(runDirection); + if (linesCount <= 1) + Col.setLeading(0, 1); + else + Col.setLeading(leading, 1); + Col.setSimpleColumn(rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()); + + Col.setAlignment(columnAlignment(alignment)); + Col.addText(p); + Col.go(); + } + private int columnAlignment(int alignment) + { + if (alignment == Element.ALIGN_JUSTIFIED) + return justifiedType; + else + return alignment; + } + public void GxClearAttris() + { + } + + public static final double PAGE_SCALE_Y = 20; // Indica la escala de la página + public static final double PAGE_SCALE_X = 20; // Indica la escala de la página + public static final double GX_PAGE_SCALE_Y_OLD = 15.45; + public static final double GX_PAGE_SCALE_Y = 14.4; // Indica la escala de la página, GeneXus lleva otra escala para el tamaño de la hoja, (variando este parametro, se agranda o achica el tamaño imprimible por GeneXus) + //Por ejemplo: si en genexus se tiene un reporte con Paper Height de 1169 (A4) centésimos de pulgada (1/100 inch), + //en el parámetro pageLength llega 16834 que esta en Twips (16834 = 1169*14.4). 1 twip = 1/1440 inch. + //Con el valor anterior 15.45 estaba quedando un margen bottom fijo que no se podia eliminar (incluso seteando mb 0). + private static double TO_CM_SCALE =28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) + public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) + { + PPP = gxYPage[0]; + loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + + if(outputStream != null) + { + if (output.equalsIgnoreCase("PRN")) + outputType = Const.OUTPUT_STREAM_PRINTER; + else + outputType = Const.OUTPUT_STREAM; + } + else + { + if(output.equalsIgnoreCase("SCR")) + outputType = Const.OUTPUT_SCREEN; + else if(output.equalsIgnoreCase("PRN")) + outputType = Const.OUTPUT_PRINTER; + else outputType = Const.OUTPUT_FILE; + + if(outputType == Const.OUTPUT_FILE) + TemporaryFiles.getInstance().removeFileFromList(docName); + else + { + String tempPrefix = docName; + String tempExtension = "pdf"; + int tempIndex = docName.lastIndexOf('.'); + if(tempIndex != -1) + { + tempPrefix = docName.substring(0, tempIndex); + tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); + } + docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); + } + try + { + setOutputStream(new FileOutputStream(docName)); + }catch(IOException accessError) + { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream + accessError.printStackTrace(System.err); + outputStream = new com.genexus.util.NullOutputStream(); + outputType = Const.OUTPUT_FILE; // Hago esto para no tener lios con el Acrobat + } + } + printerOutputMode = mode; + + boolean ret; + ret = props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); + ret = props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); + ret = props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); + leftMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.LEFT_MARGIN)).doubleValue()); + topMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.TOP_MARGIN)).doubleValue()); + bottomMargin = (float) (Double.valueOf(props.getGeneralProperty(Const.BOTTOM_MARGIN)).doubleValue()); + + lineCapProjectingSquare = props.getGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE).equals("true"); + barcode128AsImage = props.getGeneralProperty(Const.BARCODE128_AS_IMAGE).equals("true"); + STYLE_DOTTED = parsePattern(props.getGeneralProperty(Const.STYLE_DOTTED)); + STYLE_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_DASHED)); + STYLE_LONG_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DASHED)); + STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); + + runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); + + if (props.getBooleanGeneralProperty(Const.JUSTIFIED_TYPE_ALL, false)) + justifiedType = Element.ALIGN_JUSTIFIED_ALL; + else + justifiedType = Element.ALIGN_JUSTIFIED; + + //Se ignora el parametro orientation para el calculo del pageSize, los valores de alto y ancho ya vienen invertidos si Orientation=2=landscape. + this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); + gxXPage[0] = (int)this.pageSize.getRight(); + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); // Cuanto menor sea GX_PAGE_SCALE_Y, GeneXus imprime mayor parte de cada hoja + else + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); // Cuanto menor sea GX_PAGE_SCALE_Y, GeneXus imprime mayor parte de cada hoja + + + //Ahora chequeamos que el margen asociado en el PDFReport.INI sea correcto, y si es inválido, asociamos el que sea por defecto + //if(leftMargin > this.pageSize.width || topMargin > this.pageSize.height) + //{ // Si el margen asociado es mayor que el tamaño de la página, entonces asociamos los márgenes por default + + //float leftMargin = (float) (TO_CM_SCALE * Double.valueOf(Const.DEFAULT_LEFT_MARGIN).doubleValue()); + //float topMargin = (float) (TO_CM_SCALE * Double.valueOf(Const.DEFAULT_TOP_MARGIN).doubleValue()); + + //float rightMargin = 0; + //float bottomMargin = 0; + //System.err.println("Invalid page Margin... Resetting to defaults"); + //} + + + document = new Document(this.pageSize,0,0,0,0); + + init(); + + //if(DEBUG)DEBUG_STREAM.println("GxPrintInit ---> Size:" + this.pageSize + " Orientation: " + (pageOrientation == PDFPage.PORTRAIT ? "Portrait" : "Landscape")); + + return true; + } + + private com.lowagie.text.Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) + { + if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) + { + if (length == 23818 && width == 16834) + return PageSize.A3; + else if (length == 16834 && width == 11909) + return PageSize.A4; + else if (length == 11909 && width == 8395) + return PageSize.A5; + else if (length == 20016 && width == 5731) + return PageSize.B4; + else if (length == 14170 && width == 9979) + return PageSize.B5; + else if (length == 15120 && width == 10440) + return PageSize.EXECUTIVE; + else if (length == 20160 && width == 12240) + return PageSize.LEGAL; + else if (length == 15840 && width == 12240) + return PageSize.LETTER; + else + return new com.lowagie.text.Rectangle((int)(width / PAGE_SCALE_X) , (int)(length / PAGE_SCALE_Y) ); + } + return new com.lowagie.text.Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); + } + + public int getPageLines() + { + if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); + return pageLines; + } + public int getLineHeight() + { + if(DEBUG)DEBUG_STREAM.println("getLineHeight: --> " + this.lineHeight); + return this.lineHeight; + } + public void setPageLines(int P_lines) + { + if(DEBUG)DEBUG_STREAM.println("setPageLines: " + P_lines); + pageLines = P_lines; + } + public void setLineHeight(int lineHeight) + { + + if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); + this.lineHeight = lineHeight; + } + + int M_top ; + int M_bot ; + + public int getM_top() + { + return M_top; + } + + public int getM_bot() + { + return M_bot; + } + + public void setM_top(int M_top) + { + this.M_top = M_top; + } + + public void setM_bot(int M_bot) + { + this.M_bot = M_bot; + } + + public void GxEndPage() + { + //if(DEBUG)DEBUG_STREAM.println("GxEndPage"); + + //if(document != null && !isPageDirty) + // document.dispose(); +// if(document == null) GxStartPage(); // Si la página esta vacú}, la agrego primero al PDF. Esto hace que haya una hoja vacú} al final, as\uFFFDEque lo saco +// document = null; // La nueva página est\uFFFDEvacú} + } + + public void GxEndDocument() + { + if(document.getPageNumber() == 0) + { // Si no hay ninguna página en el documento, agrego una vacia} + writer.setPageEmpty(false); + } + + //Ahora proceso los comandos GeneXus {{Pages}} + if (template != null) + { + template.beginText(); + template.setFontAndSize(templateFont, templateFontSize); + template.setTextMatrix(0,0); + template.setColorFill(templateColorFill); + template.showText(String.valueOf(pages)); + template.endText(); + } + int copies = 1; + try + { + copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); + if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); + writer.addViewerPreference(PdfName.NUMCOPIES, new PdfNumber(copies)); + + int duplex= Integer.parseInt(printerSettings.getProperty(form, Const.DUPLEX)); + PdfName duplexValue; + switch (duplex){ + case 1: duplexValue = PdfName.SIMPLEX; break; + case 2: duplexValue = PdfName.DUPLEX; break; + case 3: duplexValue = PdfName.DUPLEXFLIPSHORTEDGE;break; + case 4: duplexValue = PdfName.DUPLEXFLIPLONGEDGE;break; + default: duplexValue = PdfName.NONE; + } + if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue.toString()); + writer.addViewerPreference(PdfName.DUPLEX, duplexValue); + } + catch(Exception ex) + { + ex.printStackTrace(System.err); + } + + String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); + boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); + if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) + { + //writer.addJavaScript("if (this.external)\n");//Specifies whether the current document is being viewed in the Acrobat application or in an external window (such as a web browser). + //writer.addJavaScript("app.alert('SI es externa' + this.external);"); + + + writer.addJavaScript("var pp = this.getPrintParams();\n"); + //writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + String printerAux=printerSettings.getProperty(form, Const.PRINTER); + String printer = replace(printerAux, "\\", "\\\\"); + + if (printer!=null && !printer.equals("")) + { + writer.addJavaScript("pp.printerName = \"" + printer + "\";\n"); + } + + if (fit) + { + writer.addJavaScript("pp.pageHandling = pp.constants.handling.fit;\n"); + } + else + { + writer.addJavaScript("pp.pageHandling = pp.constants.handling.none;\n"); + } + + if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0"))//Show printer dialog Never + { + writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + //No print dialog is displayed. During printing a progress monitor and cancel + //dialog is displayed and removed automatically when printing is complete. + for(int i = 0; i < copies; i++) + { + writer.addJavaScript("this.print(pp);\n"); + } + } + else //Show printer dialog is sent directly to printer | always + { + writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.full;\n"); + //Displays the print dialog allowing the user to change print settings and requiring + //the user to press OK to continue. During printing a progress monitor and cancel + //dialog is displayed and removed automatically when printing is complete. + writer.addJavaScript("this.print(pp);\n"); + } + + } + + document.close(); + + if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); + //showInformation(); + //ParseINI props = pdf.getPDF().props; + //pdf.end(); + + try{ props.save(); } catch(IOException e) { ; } + + + // OK, ahora que ya terminamos el PDF, vemos si tenemos que mostrarlo en pantalla + switch(outputType) + { + case Const.OUTPUT_SCREEN: + try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo + try{ showReport(docName, modal); } catch(Exception e) + { // Si no se puede mostrar el reporte + e.printStackTrace(); + } +// Comento la próxima lú‹ea, porque por manejo interno del Acrobat, si ya habú} una instancia del +// Acrobat corriendo, el modal no funciona (x que el proceso levantado le avisa al que ya estaba abierto qu\uFFFDE +// archivo abrir y luego se mata automáticamente) +// if(modal)if(new File(docName).delete())TemporaryFiles.getInstance().removeFileFromList(docName); // Intento eliminar el docName aqu\uFFFDE + break; + case Const.OUTPUT_PRINTER: + try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo + try{ + if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) + { + printReport(docName, this.printerOutputMode == 1); + } + } catch(Exception e){ // Si no se puede mostrar el reporte + e.printStackTrace(); + } + break; + case Const.OUTPUT_FILE: + try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo + break; + case Const.OUTPUT_STREAM: + case Const.OUTPUT_STREAM_PRINTER: + default: break; + } + outputStream = null; + } + + public void GxEndPrinter() + { + //DEBUG.println("Processing..."); + } + public void GxStartPage() + { + //try + //{ + boolean ret = document.newPage(); + pages = pages +1; + //} + //catch(DocumentException de) { + // System.err.println(de.getMessage()); + //} + } + + public void GxStartDoc() + { + //DEBUG.println("Processing..."); + } + public void GxSetDocFormat(String format) + { + //DEBUG.println("Processing..."); + } + + public void GxSetDocName(String docName) + { + this.docName = docName.trim(); + if(this.docName.indexOf('.') < 0) + this.docName += ".pdf"; + if(!new File(docName).isAbsolute()) + { // Si el nombre del documento es relativo, veo si hay que agregarle el outputDir + String outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").replace(alternateSeparator, File.separatorChar).trim(); + if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) + { + if(!outputDir.endsWith(File.separator)) + { + outputDir += File.separator; + } + new File(outputDir).mkdirs(); + this.docName = outputDir + this.docName; + } + else + { + if (ModelContext.getModelContext() != null) + { + HttpContext webContext = (HttpContext) ModelContext.getModelContext().getHttpContext(); + if ((webContext != null) && (webContext instanceof HttpContextWeb)) + { + outputDir = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + File.separator; + this.docName = outputDir + this.docName; + } + } + } + } + if(this.docName.indexOf('.') < 0) + this.docName += ".pdf"; + if(DEBUG)DEBUG_STREAM.println("GxSetDocName: '" + this.docName + "'"); + } + + public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) + { + //DEBUG.println("Processing..."); + return true; + } + + public boolean GxPrnCfg( String ini ) + { + //DEBUG.println("Processing..."); + return true; + } + + public boolean GxIsAlive() + { + return false; + } + + public boolean GxIsAliveDoc() + { + return true; + } + + + private int page; + public int getPage() + { + return page; + } + + public void setPage(int page) + { + this.page = page; + } + + public boolean getModal() + { + return modal; + } + public void setModal(boolean modal) + { + this.modal = modal; + } + + public void cleanup() {} + + public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) + { + } + + + /** Carga la tabla de substitutos + */ + private void loadSubstituteTable() + { + // Primero leemos la tabla de substitutos del Registry + Hashtable> tempInverseMappings = new Hashtable<>(); + + // Seteo algunos Mappings que Acrobat toma como Type1 + for(int i = 0; i < Const.FONT_SUBSTITUTES_TTF_TYPE1.length; i++) + fontSubstitutes.put(Const.FONT_SUBSTITUTES_TTF_TYPE1[i][0], Const.FONT_SUBSTITUTES_TTF_TYPE1[i][1]); + + // Ahora inserto los mappings extra del PDFReport.INI (si es que hay) + // Los font substitutes del PDFReport.INI se encuentran bajo la seccion + // indicada por Const.FONT_SUBSTITUTES_SECTION y son pares oldFont -> newFont + Hashtable otherMappings = props.getSection(Const.FONT_SUBSTITUTES_SECTION); + if(otherMappings != null) + for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) + { + String fontName = (String)enumera.nextElement(); + fontSubstitutes.put(fontName, (String)otherMappings.get(fontName)); + if(tempInverseMappings.containsKey(fontName)) // Con esto solucionamos el tema de la recursión de Fonts -> Fonts + { // x ej: Si tenú} Font1-> Font2, y ahora tengo Font2->Font3, pongo cambio el 1º por Font1->Font3 + String fontSubstitute = (String)otherMappings.get(fontName); + for(Enumeration enum2 = tempInverseMappings.get(fontName).elements(); enum2.hasMoreElements();) + fontSubstitutes.put(enum2.nextElement(), fontSubstitute); + } + } + } + + + /** Estos métodos no hacen nada en este contexto + */ + public void GxPrintMax() { ; } + public void GxPrintNormal() { ; } + public void GxPrintOnTop() { ; } + public void GxPrnCmd(String cmd) { ; } + + + public void showInformation() + { + } + + public static final double SCALE_FACTOR = 72; + private double PPP = 96; + private double convertScale(int value) + { + double result = value * SCALE_FACTOR / PPP; + return result; + } + + private double convertScale(double value) + { + double result = value * SCALE_FACTOR / PPP; + return result; + } + + private float reconvertScale(float value) + { + float result = value / (float)(SCALE_FACTOR / PPP); + return result; + } + + class FontProps + { + public int horizontal; + public int vertical; + } + + /** + * Helper method for toString() + * @param s source string + * @param f string to remove + * @param t string to replace f + * @return string with f replaced by t + */ + private static String replace(String s,String f,String t) { + StringBuffer b = new StringBuffer(); + int p = 0, c=0; + + while(c>-1) { + if((c = s.indexOf(f,p)) > -1) { + b.append(s.substring(p,c)); + b.append(t); + p=c+1; + } + } + + // include any remaining text + if(p Date: Tue, 14 Mar 2023 15:06:11 -0300 Subject: [PATCH 02/32] progress --- .../com/genexus/reports/PDFReportpdfbox.java | 227 ++++++------------ 1 file changed, 71 insertions(+), 156 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index a9f0eb501..948546461 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -19,14 +19,21 @@ import com.genexus.reports.fonts.Type1FontMetrics; import com.genexus.reports.fonts.Utilities; +import com.lowagie.text.Paragraph; import org.apache.pdfbox.cos.*; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.PDResources; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.font.*; +import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.graphics.state.PDTextState; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry; import org.apache.pdfbox.util.Matrix; public class PDFReportpdfbox implements IReportHandler{ @@ -88,7 +95,7 @@ public class PDFReportpdfbox implements IReportHandler{ public boolean lineCapProjectingSquare = true; public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; - Matrix rundirection = new Matrix(1, 0, 0, 1, 0, 0); + Matrix runDirection = new Matrix(1, 0, 0, 1, 0, 0); public int justifiedType; private HttpContext httpContext = null; float[] STYLE_SOLID = new float[]{1,0};//0 @@ -1321,155 +1328,40 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) if (htmlformat == 1) { - StyleSheet styles = new StyleSheet(); - Hashtable locations = getFontLocations(); - for (Enumeration e = locations.keys(); e.hasMoreElements() ;) - { - String fontName = (String)e.nextElement(); - String fontPath = (String)locations.get(fontName); - if (fontPath.equals("")) - { - fontPath = PDFFontDescriptor.getTrueTypeFontLocation(fontName, props); - } - if (!fontPath.equals("")) - { - FontFactory.register(fontPath, fontName); - styles.loadTagStyle("body", "face", fontName); - - if (isEmbeddedFont(fontName)){ - styles.loadTagStyle("body", "encoding", BaseFont.IDENTITY_H); - } - else{ - styles.loadTagStyle("body", "encoding", BaseFont.WINANSI); - } - } - } - - //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. - bottomAux = (float)convertScale(bottom); - topAux = (float)convertScale(top); - - ColumnText Col = new ColumnText(cb); - int colAlignment = columnAlignment(alignment); - if (colAlignment!=0) - Col.setAlignment(colAlignment); - ColumnText simulationCol = new ColumnText(null); - float drawingPageHeight = (float)this.pageSize.getTop() - topMargin - bottomMargin; - //Col.setSimpleColumn(llx, lly, urx, ury); - Col.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); - simulationCol.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); - - try - { - ArrayList objects = HTMLWorker.parseToList(new StringReader(sTxt), styles); - for (int k = 0; k < objects.size(); ++k) - { - if (pageHeightExceeded(bottomAux, drawingPageHeight)) - { - simulationCol.addElement((Element)objects.get(k)); - simulationCol.go(true); - - if (simulationCol.getYLine() < bottomMargin) - { - GxEndPage(); - GxStartPage(); - simulationCol = new ColumnText(null); - simulationCol.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); - simulationCol.addElement((Element)objects.get(k)); - - Col = new ColumnText(cb); - if (colAlignment!=0) - Col.setAlignment(colAlignment); - Col.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); - - bottomAux = bottomAux - drawingPageHeight; - } - } - if (objects.get(k) instanceof Paragraph && colAlignment!=0) - ((Paragraph)objects.get(k)).setAlignment(colAlignment); - - Col.addElement((Element)objects.get(k)); - Col.go(); - } - }catch(Exception de){ - System.out.println("ERROR printing HTML text " + de.getMessage()); - } + //Por ahora no soportamos la impresion de HTML } else if (barcode!=null) { - if(DEBUG)DEBUG_STREAM.println("Barcode: --> " + barcode.getClass().getName()); - try - { - barcode.setCode(sTxt); - barcode.setTextAlignment(alignment); - com.lowagie.text.Rectangle rectangle = new com.lowagie.text.Rectangle(0, 0); - //El rectangulo tiene tamaño ok. - switch (alignment) - { - case 1: // Center Alignment - rectangle = new com.lowagie.text.Rectangle((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, - (float)this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin, - (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, - (float)this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); - break; - case 2: // Right Alignment - rectangle = new com.lowagie.text.Rectangle(rightAux + leftMargin - rectangleWidth, - (float)this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin, - rightAux + leftMargin, - (float)this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); - break; - case 0: // Left Alignment - rectangle = new com.lowagie.text.Rectangle(leftAux + leftMargin, - (float)this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin, - leftAux + leftMargin + rectangleWidth, - (float)this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); - break; - } - barcode.setAltText(""); - barcode.setBaseline(0); - //barcode.Size = 0; - - if (fontSize < Const.LARGE_FONT_SIZE) - barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_SMALL_FONT); - else - barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_LARGE_FONT); - - PDImageXObject imageCode = barcode.createImageWithBarcode(cb, backFill ? backColor : null, foreColor); - imageCode.setAbsolutePosition(leftAux + leftMargin, rectangle.getBottom()); - barcode.setBarHeight(rectangle.getHeight()); - imageCode.scaleToFit(rectangle.getWidth(), rectangle.getHeight()); - document.add(imageCode); - } - catch (Exception ex) - { - if(DEBUG)DEBUG_STREAM.println("Error generating Barcode: --> " + barcode.getClass().getName() + ex.getMessage()); - if(DEBUG)ex.printStackTrace (); - } + //Por ahora no soportamos la impresion de barcodes } else { if(backFill) { - com.lowagie.text.Rectangle rectangle = new com.lowagie.text.Rectangle(0,0); + PDRectangle rectangle = new PDRectangle(0,0); //Si el texto tiene background lo dibujo de esta forma switch(alignment) { case 1: // Center Alignment - rectangle = new com.lowagie.text.Rectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); + rectangle = new PDRectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); break; case 2: // Right Alignment - rectangle = new com.lowagie.text.Rectangle(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , rightAux + leftMargin, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); + rectangle = new PDRectangle(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , rightAux + leftMargin, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); break; case 0: // Left Alignment - rectangle = new com.lowagie.text.Rectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); + rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); break; } - rectangle.setBackgroundColor(backColor); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.setNonStrokingColor(backColor); // set background color to yellow + contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); + contentStream.fill(); + contentStream.close(); try { - document.add(rectangle); + document.getPage(page).setMediaBox(rectangle); } catch(Exception e) { @@ -1479,39 +1371,43 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) float underlineSeparation = lineHeight / 5;//Separacion entre el texto y la linea del subrayado int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation/4); - com.lowagie.text.Rectangle underline; + PDRectangle underline; //Si el texto esta subrayado if (fontUnderline) { - underline = new com.lowagie.text.Rectangle(0,0); + underline = new PDRectangle(0,0); switch(alignment) { case 1: // Center Alignment - underline = new com.lowagie.text.Rectangle( + underline = new PDRectangle( (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; case 2: // Right Alignment - underline = new com.lowagie.text.Rectangle( rightAux + leftMargin - rectangleWidth , + underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; case 0: // Left Alignment - underline = new com.lowagie.text.Rectangle( leftAux + leftMargin , + underline = new PDRectangle( leftAux + leftMargin , this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, leftAux + leftMargin + rectangleWidth, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; } - underline.setBackgroundColor(foreColor); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.setNonStrokingColor(foreColor); // set background color to yellow + contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); + contentStream.fill(); + contentStream.close(); try { - document.add(underline); + document.getPage(page).setMediaBox(underline); } catch(Exception e) { @@ -1522,35 +1418,39 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) //Si el texto esta tachado if (fontStrikethru) { - underline = new com.lowagie.text.Rectangle(0,0); + underline = new PDRectangle(0,0); float strikethruSeparation = lineHeight / 2; switch(alignment) { case 1: // Center Alignment - underline = new com.lowagie.text.Rectangle( + underline = new PDRectangle( (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; case 2: // Right Alignment - underline = new com.lowagie.text.Rectangle( rightAux + leftMargin - rectangleWidth , + underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; case 0: // Left Alignment - underline = new com.lowagie.text.Rectangle( leftAux + leftMargin , + underline = new PDRectangle( leftAux + leftMargin , this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, leftAux + leftMargin + rectangleWidth, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } - underline.setBackgroundColor(foreColor); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.setNonStrokingColor(foreColor); // set background color to yellow + contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); + contentStream.fill(); + contentStream.close(); try { - document.add(underline); + document.getPage(page).setMediaBox(underline); } catch(Exception e) { @@ -1562,10 +1462,15 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) {// Si el texto es la cantidad de páginas del documento if (!templateCreated) { - template = cb.createTemplate(right - left, bottom - top); + PDFormXObject template = new PDFormXObject(document); + template.setResources(new PDResources()); + template.setBBox(new PDRectangle(right - left, bottom - top)); templateCreated = true; } - cb.addTemplate(template, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin); + PDFormXObject form = new PDFormXObject(document); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); + contentStream.drawForm(form); // draw the form onto th templateFont = baseFont; templateFontSize = fontSize; templateColorFill = foreColor; @@ -1573,7 +1478,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } float textBlockWidth = rightAux - leftAux; - float TxtWidth = baseFont.getWidthPoint(sTxt, fontSize); + float TxtWidth = baseFont.getStringWidth(sTxt)/ 1000 * fontSize; boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; boolean wrap = ((align & 16) == 16); @@ -1586,14 +1491,19 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) //La constante 2 para LEADING indica la separacion que se deja entre un renglon y otro. (es lo que mas se asemeja a la api vieja). float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); - Paragraph p = new Paragraph(sTxt, font); - - float llx = leftAux + leftMargin; - float lly = (float)this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin; - float urx = rightAux + leftMargin; - float ury = (float)this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin; + PDAnnotationText annotation = new PDAnnotationText(); + annotation.setContents(sTxt); + annotation.setDefaultAppearance("/" + font.getName() + " " + fontSize +" Tf 0 g"); + annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, + rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); try{ + document.getPage(page).getAnnotations().add(annotation); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.beginText(); + contentStream.showText(annotation.getContents()); + contentStream.endText(); + contentStream.close(); DrawColumnText(cb, llx, lly, urx, ury, p, leading, runDirection, valign, alignment); } catch (Exception e) @@ -1614,22 +1524,27 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) { sTxt = newsTxt; newsTxt = newsTxt.substring(0, newsTxt.length()-1); - TxtWidth = baseFont.getWidthPoint(newsTxt, fontSize); + TxtWidth = baseFont.getStringWidth(newsTxt) / 1000 * fontSize; } } - Phrase phrase = new Phrase(sTxt, font); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.beginText(); + contentStream.setFont(font, 12); + contentStream.showText(sTxt); + contentStream.endText(); + switch(alignment) { case 1: // Center Alignment - ColumnText.showTextAligned(cb, cb.ALIGN_CENTER, phrase, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); + ColumnText.showTextAligned(cb, cb.ALIGN_CENTER, phrase, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); break; case 2: // Right Alignment - ColumnText.showTextAligned(cb, cb.ALIGN_RIGHT, phrase, rightAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); + ColumnText.showTextAligned(cb, cb.ALIGN_RIGHT, phrase, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); break; case 0: // Left Alignment case 3: // Justified, only one text line - ColumnText.showTextAligned(cb, cb.ALIGN_LEFT, phrase, leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); + ColumnText.showTextAligned(cb, cb.ALIGN_LEFT, phrase, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); break; } } @@ -1650,7 +1565,7 @@ PDPageContentStream SimulateDrawColumnText(PDPageContentStream cb, PDRectangle r Col.go(true); return Col; } - void DrawColumnText(PdfContentByte cb, float llx, float lly, float urx, float ury, Paragraph p, float leading, int runDirection, int valign, int alignment) throws DocumentException + void DrawColumnText(PDPageContentStream cb, float llx, float lly, float urx, float ury, float leading, Matrix runDirection, int valign, int alignment) throws DocumentException { Rectangle rect = new Rectangle(llx, lly, urx, ury); ColumnText ct = SimulateDrawColumnText(cb, rect, p, leading, runDirection, alignment);//add the column in simulation mode From dcd1d7cb5dc1d16696529482004f8bf53c6e1cbb Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 15 Mar 2023 15:11:46 -0300 Subject: [PATCH 03/32] static code analysis ok --- .../com/genexus/reports/PDFReportpdfbox.java | 681 ++++++++++-------- 1 file changed, 364 insertions(+), 317 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 948546461..750e05b47 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -19,21 +19,18 @@ import com.genexus.reports.fonts.Type1FontMetrics; import com.genexus.reports.fonts.Utilities; -import com.lowagie.text.Paragraph; import org.apache.pdfbox.cos.*; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.PDResources; +import org.apache.pdfbox.pdmodel.*; +import org.apache.pdfbox.pdmodel.common.PDPageLabelRange; +import org.apache.pdfbox.pdmodel.common.PDPageLabels; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.font.*; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; -import org.apache.pdfbox.pdmodel.graphics.state.PDTextState; +import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceEntry; +import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences; import org.apache.pdfbox.util.Matrix; public class PDFReportpdfbox implements IReportHandler{ @@ -42,7 +39,7 @@ public class PDFReportpdfbox implements IReportHandler{ private int pageOrientation; // Indica la orientacion de las páginas private PDType1Font font; private PDType0Font baseFont; - private BarcodeUtil barcode = null; + //private BarcodeUtil barcode = null; por ahora no soportamos barcode private boolean fontUnderline; private boolean fontStrikethru; private int fontSize; @@ -72,7 +69,7 @@ public class PDFReportpdfbox implements IReportHandler{ //private Hashtable fontMetricsProps = new Hashtable(); public static boolean DEBUG = false; private PDDocument document; - private PDDocument writer; + private PDDocumentCatalog writer; private PDPageContentStream chunk; private int currLine; private int lastLine = 0; @@ -95,7 +92,7 @@ public class PDFReportpdfbox implements IReportHandler{ public boolean lineCapProjectingSquare = true; public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; - Matrix runDirection = new Matrix(1, 0, 0, 1, 0, 0); + public int runDirection = 0; public int justifiedType; private HttpContext httpContext = null; float[] STYLE_SOLID = new float[]{1,0};//0 @@ -965,12 +962,11 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { - barcode = new Barcode128(); - barcode.setCodeType(Barcode128.CODE128); + // Por ahora no soportamos barcode } else { - barcode = null; + // Por ahora no soportamos barcode } this.fontUnderline = fontUnderline; this.fontStrikethru = fontStrikethru; @@ -1271,291 +1267,320 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { - boolean printRectangle = false; - if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) - printRectangle = true; - - if (printRectangle && (border == 1 || backFill)) - { - GxDrawRect(left, top, right, bottom, border, foreColor.getRed(), foreColor.getGreen(), foreColor.getBlue(), backFill ? 1 : 0, backColor.getRed(), backColor.getGreen(), backColor.getBlue(), 0, 0); - } + try{ + boolean printRectangle = false; + if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) + printRectangle = true; - PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); - sTxt = CommonUtil.rtrim(sTxt); - - COSDictionary fontDict = baseFont.getCOSObject(); - COSDictionary newFontDict = new COSDictionary(fontDict); - newFontDict.setFloat(COSName.SIZE, fontSize); - PDType0Font auxFont = new PDType0Font(newFontDict); - cb.setFont(font,fontSize); - - cb.setNonStrokingColor(foreColor); - int arabicOptions = 0; - float captionHeight = auxFont.getFontDescriptor().getCapHeight(); - float rectangleWidth = auxFont.getStringWidth(sTxt); - float lineHeight = auxFont.getFontDescriptor().getFontBoundingBox().getUpperRightY() - auxFont.getFontDescriptor().getFontBoundingBox().getLowerLeftX(); - float textBlockHeight = (float)convertScale(bottom-top); - int linesCount = (int)(textBlockHeight/lineHeight); - int bottomOri = bottom; - int topOri = top; - - //Si se tiene un campo con mas de una linea y no tiene wrap, no es justify, y no es html, se simula que el campo tiene una sola linea - //asignando al bottom el top mas el lineHeight - if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) - { - if (valign == PDFReportpdfbox.VerticalAlign.TOP.value()) - bottom = top + (int)reconvertScale(lineHeight); - else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) - top = bottom - (int)reconvertScale(lineHeight); - //if valign == middle, no se cambia ni top ni bottom - } + if (printRectangle && (border == 1 || backFill)) + { + GxDrawRect(left, top, right, bottom, border, foreColor.getRed(), foreColor.getGreen(), foreColor.getBlue(), backFill ? 1 : 0, backColor.getRed(), backColor.getGreen(), backColor.getBlue(), 0, 0); + } - float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; - //Al bottom de los textos se le resta espacio entre el texto y el borde del textblock, - //porque en el reporte genexus la x,y de un - //text es la x,y del cuadro que contiene el texto, y la api de itext espera la x,y del texto en si. - //Generalmente el cuadro es mas grande que lo que ocupa el texto realmente (depende del tipo de font) - //captionHeight esta convertido, bottom y top no. - float topAux = (float)convertScale(top) + ((float)convertScale(bottom-top) - captionHeight)/2; + PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + sTxt = CommonUtil.rtrim(sTxt); + + COSDictionary fontDict = baseFont.getCOSObject(); + COSDictionary newFontDict = new COSDictionary(fontDict); + newFontDict.setFloat(COSName.SIZE, fontSize); + PDType0Font auxFont = new PDType0Font(newFontDict); + cb.setFont(font,fontSize); + + cb.setNonStrokingColor(foreColor); + int arabicOptions = 0; + float captionHeight = auxFont.getFontDescriptor().getCapHeight(); + float rectangleWidth = auxFont.getStringWidth(sTxt); + float lineHeight = auxFont.getFontDescriptor().getFontBoundingBox().getUpperRightY() - auxFont.getFontDescriptor().getFontBoundingBox().getLowerLeftX(); + float textBlockHeight = (float)convertScale(bottom-top); + int linesCount = (int)(textBlockHeight/lineHeight); + int bottomOri = bottom; + int topOri = top; + + //Si se tiene un campo con mas de una linea y no tiene wrap, no es justify, y no es html, se simula que el campo tiene una sola linea + //asignando al bottom el top mas el lineHeight + if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) + { + if (valign == PDFReportpdfbox.VerticalAlign.TOP.value()) + bottom = top + (int)reconvertScale(lineHeight); + else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) + top = bottom - (int)reconvertScale(lineHeight); + //if valign == middle, no se cambia ni top ni bottom + } + float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; + //Al bottom de los textos se le resta espacio entre el texto y el borde del textblock, + //porque en el reporte genexus la x,y de un + //text es la x,y del cuadro que contiene el texto, y la api de itext espera la x,y del texto en si. + //Generalmente el cuadro es mas grande que lo que ocupa el texto realmente (depende del tipo de font) + //captionHeight esta convertido, bottom y top no. + float topAux = (float)convertScale(top) + ((float)convertScale(bottom-top) - captionHeight)/2; - float startHeight = bottomAux - topAux - captionHeight; - float leftAux = (float)convertScale(left); - float rightAux = (float)convertScale(right); - int alignment = align & 3; - boolean autoResize = (align & 256) == 256; + float startHeight = bottomAux - topAux - captionHeight; - if (htmlformat == 1) - { - //Por ahora no soportamos la impresion de HTML - } - else - if (barcode!=null) - { - //Por ahora no soportamos la impresion de barcodes - } - else - { + float leftAux = (float)convertScale(left); + float rightAux = (float)convertScale(right); + int alignment = align & 3; + boolean autoResize = (align & 256) == 256; - if(backFill) + if (htmlformat == 1) { - PDRectangle rectangle = new PDRectangle(0,0); - //Si el texto tiene background lo dibujo de esta forma - switch(alignment) - { - case 1: // Center Alignment - rectangle = new PDRectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); - break; - case 2: // Right Alignment - rectangle = new PDRectangle(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , rightAux + leftMargin, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); - break; - case 0: // Left Alignment - rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); - break; - } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.setNonStrokingColor(backColor); // set background color to yellow - contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); - contentStream.fill(); - contentStream.close(); - try - { - document.getPage(page).setMediaBox(rectangle); - } - catch(Exception e) - { - System.err.println(e.getMessage()); - } + //Por ahora no soportamos la impresion de HTML } - - float underlineSeparation = lineHeight / 5;//Separacion entre el texto y la linea del subrayado - int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation/4); - PDRectangle underline; - - //Si el texto esta subrayado - if (fontUnderline) + else + if (1 == 2)//(barcode!=null) { - underline = new PDRectangle(0,0); - - switch(alignment) - { - case 1: // Center Alignment - underline = new PDRectangle( - (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, - (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); - break; - case 2: // Right Alignment - underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, - rightAux + leftMargin, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); - break; - case 0: // Left Alignment - underline = new PDRectangle( leftAux + leftMargin , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, - leftAux + leftMargin + rectangleWidth, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); - break; - } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.setNonStrokingColor(foreColor); // set background color to yellow - contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); - contentStream.fill(); - contentStream.close(); - try - { - document.getPage(page).setMediaBox(underline); - } - catch(Exception e) - { - System.err.println(e.getMessage()); - } + //Por ahora no soportamos la impresion de barcodes } - - //Si el texto esta tachado - if (fontStrikethru) + else { - underline = new PDRectangle(0,0); - float strikethruSeparation = lineHeight / 2; - switch(alignment) - { - case 1: // Center Alignment - underline = new PDRectangle( - (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, - (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); - break; - case 2: // Right Alignment - underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, - rightAux + leftMargin, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); - break; - case 0: // Left Alignment - underline = new PDRectangle( leftAux + leftMargin , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, - leftAux + leftMargin + rectangleWidth, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); - break; - } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.setNonStrokingColor(foreColor); // set background color to yellow - contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); - contentStream.fill(); - contentStream.close(); - try - { - document.getPage(page).setMediaBox(underline); - } - catch(Exception e) + if(backFill) { - System.err.println(e.getMessage()); + PDRectangle rectangle = new PDRectangle(0,0); + //Si el texto tiene background lo dibujo de esta forma + switch(alignment) + { + case 1: // Center Alignment + rectangle = new PDRectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); + break; + case 2: // Right Alignment + rectangle = new PDRectangle(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , rightAux + leftMargin, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); + break; + case 0: // Left Alignment + rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); + break; + } + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.setNonStrokingColor(backColor); // set background color to yellow + contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); + contentStream.fill(); + contentStream.close(); + try + { + document.getPage(page).setMediaBox(rectangle); + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } } - } - if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) - {// Si el texto es la cantidad de páginas del documento - if (!templateCreated) + float underlineSeparation = lineHeight / 5;//Separacion entre el texto y la linea del subrayado + int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation/4); + PDRectangle underline; + + //Si el texto esta subrayado + if (fontUnderline) { - PDFormXObject template = new PDFormXObject(document); - template.setResources(new PDResources()); - template.setBBox(new PDRectangle(right - left, bottom - top)); - templateCreated = true; - } - PDFormXObject form = new PDFormXObject(document); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); - contentStream.drawForm(form); // draw the form onto th - templateFont = baseFont; - templateFontSize = fontSize; - templateColorFill = foreColor; - return; - } + underline = new PDRectangle(0,0); - float textBlockWidth = rightAux - leftAux; - float TxtWidth = baseFont.getStringWidth(sTxt)/ 1000 * fontSize; - boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; - boolean wrap = ((align & 16) == 16); + switch(alignment) + { + case 1: // Center Alignment + underline = new PDRectangle( + (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, + (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + break; + case 2: // Right Alignment + underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, + rightAux + leftMargin, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + break; + case 0: // Left Alignment + underline = new PDRectangle( leftAux + leftMargin , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, + leftAux + leftMargin + rectangleWidth, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + break; + } + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.setNonStrokingColor(foreColor); // set background color to yellow + contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); + contentStream.fill(); + contentStream.close(); + try + { + document.getPage(page).setMediaBox(underline); + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } + } - //Justified - if (wrap || justified) - { - //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. - bottomAux = (float)convertScale(bottomOri); - topAux = (float)convertScale(topOri); - - //La constante 2 para LEADING indica la separacion que se deja entre un renglon y otro. (es lo que mas se asemeja a la api vieja). - float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); - PDAnnotationText annotation = new PDAnnotationText(); - annotation.setContents(sTxt); - annotation.setDefaultAppearance("/" + font.getName() + " " + fontSize +" Tf 0 g"); - annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, - rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); + //Si el texto esta tachado + if (fontStrikethru) + { + underline = new PDRectangle(0,0); + float strikethruSeparation = lineHeight / 2; - try{ - document.getPage(page).getAnnotations().add(annotation); + switch(alignment) + { + case 1: // Center Alignment + underline = new PDRectangle( + (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, + (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + break; + case 2: // Right Alignment + underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, + rightAux + leftMargin, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + break; + case 0: // Left Alignment + underline = new PDRectangle( leftAux + leftMargin , + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, + leftAux + leftMargin + rectangleWidth, + this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + break; + } PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.beginText(); - contentStream.showText(annotation.getContents()); - contentStream.endText(); + contentStream.setNonStrokingColor(foreColor); // set background color to yellow + contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); + contentStream.fill(); contentStream.close(); - DrawColumnText(cb, llx, lly, urx, ury, p, leading, runDirection, valign, alignment); + try + { + document.getPage(page).setMediaBox(underline); + } + catch(Exception e) + { + System.err.println(e.getMessage()); + } } - catch (Exception e) - { - e.printStackTrace(System.err); + + if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) + {// Si el texto es la cantidad de páginas del documento + if (!templateCreated) + { + PDFormXObject template = new PDFormXObject(document); + template.setResources(new PDResources()); + template.setBBox(new PDRectangle(right - left, bottom - top)); + templateCreated = true; + } + PDFormXObject form = new PDFormXObject(document); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); + contentStream.drawForm(form); // draw the form onto th + templateFont = baseFont; + templateFontSize = fontSize; + templateColorFill = foreColor; + return; } - } - else //no wrap - { - startHeight=0; - if (!autoResize) + + float textBlockWidth = rightAux - leftAux; + float TxtWidth = baseFont.getStringWidth(sTxt)/ 1000 * fontSize; + boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; + boolean wrap = ((align & 16) == 16); + + //Justified + if (wrap || justified) { - //Va quitando el ultimo char del texto hasta que llega a un string cuyo ancho se pasa solo por un caracter - //del ancho del textblock ("se pasa solo por un caracter": esto es porque en el caso general es ese el texto que - //mas se parece a lo que se disenia en genexus). - String newsTxt = sTxt; - while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) + //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. + bottomAux = (float)convertScale(bottomOri); + topAux = (float)convertScale(topOri); + + //La constante 2 para LEADING indica la separacion que se deja entre un renglon y otro. (es lo que mas se asemeja a la api vieja). + float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); + PDAnnotationText annotation = new PDAnnotationText(); + String alignmentString; + switch(alignment) { + case 1: + alignmentString = "center"; + break; + case 2: + alignmentString = "right"; + break; + default: + alignmentString = "left"; + } + annotation.setDefaultAppearance("/" + font.getName() + " " + fontSize + " Tf " + leading + " TL 0 g " + alignmentString + " <>BDC q BT /F1 " + fontSize + " Tf " + leading + " TL Tj ET Q EMC"); + annotation.setContents(sTxt); + annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, + rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); + try{ + document.getPage(page).getAnnotations().add(annotation); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.beginText(); + contentStream.showText(annotation.getContents()); + contentStream.endText(); + contentStream.close(); + } + catch (Exception e) { - sTxt = newsTxt; - newsTxt = newsTxt.substring(0, newsTxt.length()-1); - TxtWidth = baseFont.getStringWidth(newsTxt) / 1000 * fontSize; + e.printStackTrace(System.err); } } + else //no wrap + { + startHeight=0; + if (!autoResize) + { + //Va quitando el ultimo char del texto hasta que llega a un string cuyo ancho se pasa solo por un caracter + //del ancho del textblock ("se pasa solo por un caracter": esto es porque en el caso general es ese el texto que + //mas se parece a lo que se disenia en genexus). + String newsTxt = sTxt; + while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) + { + sTxt = newsTxt; + newsTxt = newsTxt.substring(0, newsTxt.length()-1); + TxtWidth = baseFont.getStringWidth(newsTxt) / 1000 * fontSize; + } + } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.beginText(); - contentStream.setFont(font, 12); - contentStream.showText(sTxt); - contentStream.endText(); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + contentStream.beginText(); + contentStream.setFont(baseFont, fontSize); - switch(alignment) - { - case 1: // Center Alignment - ColumnText.showTextAligned(cb, cb.ALIGN_CENTER, phrase, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); - break; - case 2: // Right Alignment - ColumnText.showTextAligned(cb, cb.ALIGN_RIGHT, phrase, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); - break; - case 0: // Left Alignment - case 3: // Justified, only one text line - ColumnText.showTextAligned(cb, cb.ALIGN_LEFT, phrase, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); - break; + switch(alignment) + { + case 1: // Center Alignment + float x = ((leftAux + rightAux) / 2) + leftMargin; + float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + contentStream.newLineAtOffset(x, y); + cb.setHorizontalScaling(1f); + contentStream.showText(sTxt); + contentStream.endText(); + contentStream.close(); + break; + case 2: // Right Alignment + x = rightAux + leftMargin; + y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + contentStream.newLineAtOffset(x, y); + contentStream.showText(sTxt); + cb.setHorizontalScaling(1f); + contentStream.endText(); + contentStream.close(); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + x = (leftAux + rightAux) / 2 + leftMargin; + y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + cb.newLineAtOffset(x, y); + cb.setHorizontalScaling(1f); + cb.showText(sTxt); + cb.endText(); + break; + } } } + } catch (Exception e){ + System.err.println(e.getMessage()); } } boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ return bottomAux > drawingPageHeight; } - PDPageContentStream SimulateDrawColumnText(PDPageContentStream cb, PDRectangle rect, PDPageContentStream p, float leading, int runDirection, int alignment) throws DocumentException + + /* + ColumnText SimulateDrawColumnText(PdfContentByte cb, Rectangle rect, Paragraph p, float leading, int runDirection, int alignment) throws DocumentException { - // Recordar que p es un parrafo ColumnText Col = new ColumnText(cb); Col.setRunDirection(runDirection); Col.setAlignment(alignment); @@ -1565,6 +1590,8 @@ PDPageContentStream SimulateDrawColumnText(PDPageContentStream cb, PDRectangle r Col.go(true); return Col; } + */ + /* void DrawColumnText(PDPageContentStream cb, float llx, float lly, float urx, float ury, float leading, Matrix runDirection, int valign, int alignment) throws DocumentException { Rectangle rect = new Rectangle(llx, lly, urx, ury); @@ -1594,6 +1621,10 @@ else if (valign == PDFReportItext.VerticalAlign.TOP.value()) Col.addText(p); Col.go(); } + + */ + + /* private int columnAlignment(int alignment) { if (alignment == Element.ALIGN_JUSTIFIED) @@ -1601,6 +1632,9 @@ private int columnAlignment(int alignment) else return alignment; } + + */ + public void GxClearAttris() { } @@ -1676,14 +1710,10 @@ else if(output.equalsIgnoreCase("PRN")) runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); - if (props.getBooleanGeneralProperty(Const.JUSTIFIED_TYPE_ALL, false)) - justifiedType = Element.ALIGN_JUSTIFIED_ALL; - else - justifiedType = Element.ALIGN_JUSTIFIED; //Se ignora el parametro orientation para el calculo del pageSize, los valores de alto y ancho ya vienen invertidos si Orientation=2=landscape. this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); - gxXPage[0] = (int)this.pageSize.getRight(); + gxXPage[0] = (int)this.pageSize.getUpperRightX (); if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); // Cuanto menor sea GX_PAGE_SCALE_Y, GeneXus imprime mayor parte de cada hoja else @@ -1702,8 +1732,8 @@ else if(output.equalsIgnoreCase("PRN")) //System.err.println("Invalid page Margin... Resetting to defaults"); //} - - document = new Document(this.pageSize,0,0,0,0); + document = new PDDocument(); + document.addPage(new PDPage(this.pageSize)); init(); @@ -1712,30 +1742,30 @@ else if(output.equalsIgnoreCase("PRN")) return true; } - private com.lowagie.text.Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) + private PDRectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) { if (length == 23818 && width == 16834) - return PageSize.A3; + return PDRectangle.A3; else if (length == 16834 && width == 11909) - return PageSize.A4; + return PDRectangle.A4; else if (length == 11909 && width == 8395) - return PageSize.A5; + return PDRectangle.A5; else if (length == 20016 && width == 5731) - return PageSize.B4; + return new PDRectangle(250f, 353f); else if (length == 14170 && width == 9979) - return PageSize.B5; + return new PDRectangle(176f, 250f); else if (length == 15120 && width == 10440) - return PageSize.EXECUTIVE; + return new PDRectangle(184.15f, 266.7f); else if (length == 20160 && width == 12240) - return PageSize.LEGAL; + return PDRectangle.LEGAL; else if (length == 15840 && width == 12240) - return PageSize.LETTER; + return PDRectangle.LETTER; else - return new com.lowagie.text.Rectangle((int)(width / PAGE_SCALE_X) , (int)(length / PAGE_SCALE_Y) ); + return new PDRectangle((int)(width / PAGE_SCALE_X) , (int)(length / PAGE_SCALE_Y) ); } - return new com.lowagie.text.Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); + return new PDRectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); } public int getPageLines() @@ -1795,39 +1825,58 @@ public void GxEndPage() public void GxEndDocument() { - if(document.getPageNumber() == 0) + if(document.getNumberOfPages() == 0) { // Si no hay ninguna página en el documento, agrego una vacia} - writer.setPageEmpty(false); + document.addPage(new PDPage(this.pageSize)); } //Ahora proceso los comandos GeneXus {{Pages}} if (template != null) { - template.beginText(); - template.setFontAndSize(templateFont, templateFontSize); - template.setTextMatrix(0,0); - template.setColorFill(templateColorFill); - template.showText(String.valueOf(pages)); - template.endText(); + try{ + for (PDPage page : document.getPages()){ + template = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true); + template.beginText(); + template.setFont(baseFont, fontSize); + template.setTextMatrix(new Matrix()); + template.setNonStrokingColor(templateColorFill); + template.showText(String.valueOf(pages)); + template.endText(); + } + } catch (IOException e){ } + } int copies = 1; try { copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); - writer.addViewerPreference(PdfName.NUMCOPIES, new PdfNumber(copies)); + + writer = document.getDocumentCatalog(); + COSDictionary dict = writer.getViewerPreferences().getCOSObject(); + if (dict == null) {dict = new COSDictionary();} + PDViewerPreferences viewerPreferences = new PDViewerPreferences(dict); + viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); + dict.setInt("NumCopies", copies); + writer.setViewerPreferences(viewerPreferences); int duplex= Integer.parseInt(printerSettings.getProperty(form, Const.DUPLEX)); - PdfName duplexValue; + COSName duplexValue; switch (duplex){ - case 1: duplexValue = PdfName.SIMPLEX; break; - case 2: duplexValue = PdfName.DUPLEX; break; - case 3: duplexValue = PdfName.DUPLEXFLIPSHORTEDGE;break; - case 4: duplexValue = PdfName.DUPLEXFLIPLONGEDGE;break; - default: duplexValue = PdfName.NONE; + case 1: duplexValue = COSName.HELV; break; + case 2: duplexValue = COSName.DUPLEX; break; + case 3: duplexValue = COSName.DUPLEX;break; + case 4: duplexValue = COSName.DUPLEX;break; + default: duplexValue = COSName.NONE; } - if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue.toString()); - writer.addViewerPreference(PdfName.DUPLEX, duplexValue); + if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue); + writer = document.getDocumentCatalog(); + dict = writer.getViewerPreferences().getCOSObject(); + if (dict == null) {dict = new COSDictionary();} + viewerPreferences = new PDViewerPreferences(dict); + viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); + dict.setName(COSName.DUPLEX, duplexValue.toString()); + writer.setViewerPreferences(viewerPreferences); } catch(Exception ex) { @@ -1841,48 +1890,52 @@ public void GxEndDocument() //writer.addJavaScript("if (this.external)\n");//Specifies whether the current document is being viewed in the Acrobat application or in an external window (such as a web browser). //writer.addJavaScript("app.alert('SI es externa' + this.external);"); - - writer.addJavaScript("var pp = this.getPrintParams();\n"); + PDActionJavaScript jsAction = new PDActionJavaScript(); + jsAction.setAction("var pp = this.getPrintParams();\n"); //writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); String printerAux=printerSettings.getProperty(form, Const.PRINTER); String printer = replace(printerAux, "\\", "\\\\"); if (printer!=null && !printer.equals("")) { - writer.addJavaScript("pp.printerName = \"" + printer + "\";\n"); + jsAction.setAction("pp.printerName = \"" + printer + "\";\n"); } if (fit) { - writer.addJavaScript("pp.pageHandling = pp.constants.handling.fit;\n"); + jsAction.setAction("pp.pageHandling = pp.constants.handling.fit;\n"); } else { - writer.addJavaScript("pp.pageHandling = pp.constants.handling.none;\n"); + jsAction.setAction("pp.pageHandling = pp.constants.handling.none;\n"); } if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0"))//Show printer dialog Never { - writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + jsAction.setAction("pp.interactive = pp.constants.interactionLevel.automatic;\n"); //No print dialog is displayed. During printing a progress monitor and cancel //dialog is displayed and removed automatically when printing is complete. for(int i = 0; i < copies; i++) { - writer.addJavaScript("this.print(pp);\n"); + jsAction.setAction("this.print(pp);\n"); } } else //Show printer dialog is sent directly to printer | always { - writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.full;\n"); + jsAction.setAction("pp.interactive = pp.constants.interactionLevel.full;\n"); //Displays the print dialog allowing the user to change print settings and requiring //the user to press OK to continue. During printing a progress monitor and cancel //dialog is displayed and removed automatically when printing is complete. - writer.addJavaScript("this.print(pp);\n"); + jsAction.setAction("this.print(pp);\n"); } } + try { + document.close(); + } catch (IOException e) { + System.err.println(e.getMessage()); + } - document.close(); if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); //showInformation(); @@ -1901,10 +1954,10 @@ public void GxEndDocument() { // Si no se puede mostrar el reporte e.printStackTrace(); } -// Comento la próxima lú‹ea, porque por manejo interno del Acrobat, si ya habú} una instancia del -// Acrobat corriendo, el modal no funciona (x que el proceso levantado le avisa al que ya estaba abierto qu\uFFFDE -// archivo abrir y luego se mata automáticamente) -// if(modal)if(new File(docName).delete())TemporaryFiles.getInstance().removeFileFromList(docName); // Intento eliminar el docName aqu\uFFFDE + // Comento la próxima lú‹ea, porque por manejo interno del Acrobat, si ya habú} una instancia del + // Acrobat corriendo, el modal no funciona (x que el proceso levantado le avisa al que ya estaba abierto qu\uFFFDE + // archivo abrir y luego se mata automáticamente) + // if(modal)if(new File(docName).delete())TemporaryFiles.getInstance().removeFileFromList(docName); // Intento eliminar el docName aqu\uFFFDE break; case Const.OUTPUT_PRINTER: try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo @@ -1933,14 +1986,8 @@ public void GxEndPrinter() } public void GxStartPage() { - //try - //{ - boolean ret = document.newPage(); + document.addPage(new PDPage()); pages = pages +1; - //} - //catch(DocumentException de) { - // System.err.println(de.getMessage()); - //} } public void GxStartDoc() From 4d3bcbc55e9baffdb3bbf16968aa03c3751229c4 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Thu, 16 Mar 2023 11:17:04 -0300 Subject: [PATCH 04/32] Code cleaning and minor fixes --- .../com/genexus/reports/PDFReportpdfbox.java | 488 ++++-------------- 1 file changed, 88 insertions(+), 400 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 750e05b47..249061241 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -2,6 +2,7 @@ import java.awt.Color; import java.io.*; +import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.util.*; @@ -19,10 +20,9 @@ import com.genexus.reports.fonts.Type1FontMetrics; import com.genexus.reports.fonts.Utilities; +import com.lowagie.text.pdf.BaseFont; import org.apache.pdfbox.cos.*; import org.apache.pdfbox.pdmodel.*; -import org.apache.pdfbox.pdmodel.common.PDPageLabelRange; -import org.apache.pdfbox.pdmodel.common.PDPageLabels; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.font.*; @@ -35,8 +35,7 @@ public class PDFReportpdfbox implements IReportHandler{ private int lineHeight, pageLines; - private org.apache.pdfbox.pdmodel.common.PDRectangle pageSize; // Contiene las dimensiones de la página - private int pageOrientation; // Indica la orientacion de las páginas + private PDRectangle pageSize; private PDType1Font font; private PDType0Font baseFont; //private BarcodeUtil barcode = null; por ahora no soportamos barcode @@ -47,37 +46,29 @@ public class PDFReportpdfbox implements IReportHandler{ private boolean fontItalic = false; private Color backColor, foreColor; public static PrintStream DEBUG_STREAM = System.out; - private OutputStream outputStream = null; // Contiene el OutputStream de salida del reporte - //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página + private OutputStream outputStream = null; private static ParseINI props = new ParseINI(); private ParseINI printerSettings; private String form; - private Vector stringTotalPages; // Contiene la lista de locations del parámetros {{Pages}} - private boolean isPageDirty; // Indica si la pagina NO se debe 'dispose()'ar pues se le va a agregar cosas al terminar el PDF - private int outputType = -1; // Indica el tipo de Output que se desea para el documento - private int printerOutputMode = -1; // Indica si se debe mostrar el cuadro de Impresion para la salida por impresora - private boolean modal = false; // Indica si el diálogo debe ser modal o no modal en - private String docName = "PDFReport.pdf"; // Nombre del documento a generar (se cambia con GxSetDocName) + private Vector stringTotalPages; + private int outputType = -1; + private int printerOutputMode = -1; + private boolean modal = false; + private String docName = "PDFReport.pdf"; private static INativeFunctions nativeCode = NativeFunctions.getInstance(); - private static Hashtable fontSubstitutes = new Hashtable<>(); // Contiene la tabla de substitutos de fonts (String <--> String) + private static Hashtable fontSubstitutes = new Hashtable<>(); private static String configurationFile = null; private static String configurationTemplateFile = null; - private static String defaultRelativePrepend = null; // En aplicaciones web, contiene la ruta al root de la aplicación para ser agregado al inicio de las imagenes con path relativo + private static String defaultRelativePrepend = null; private static String defaultRelativePrependINI = null; private static String webAppDir = null; - //private boolean containsSpecialMetrics = false; - //private Hashtable fontMetricsProps = new Hashtable(); public static boolean DEBUG = false; private PDDocument document; private PDDocumentCatalog writer; - private PDPageContentStream chunk; - private int currLine; - private int lastLine = 0; - private static String predefinedSearchPath = ""; // Contiene los predefinedSearchPaths + private static String predefinedSearchPath = ""; private float leftMargin; private float topMargin; - private float bottomMargin; //If Margin Bottom is not specified 6 lines are assumed (nlines =6). - + private float bottomMargin; private PDPageContentStream template; private PDType0Font templateFont; private int templateFontSize; @@ -85,22 +76,17 @@ public class PDFReportpdfbox implements IReportHandler{ private Color templateColorFill; private int pages=0; private boolean templateCreated = false; - public static float DASHES_UNITS_ON = 10; - public static float DASHES_UNITS_OFF = 10; - public static float DOTS_UNITS_OFF = 3; - public static float DOTS_UNITS_ON = 1; public boolean lineCapProjectingSquare = true; public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; public int runDirection = 0; - public int justifiedType; private HttpContext httpContext = null; float[] STYLE_SOLID = new float[]{1,0};//0 - float[] STYLE_NONE = null;//1 - float[] STYLE_DOTTED, //2 - STYLE_DASHED, //3 - STYLE_LONG_DASHED, //4 - STYLE_LONG_DOT_DASHED; //5 + float[] STYLE_NONE = null; + float[] STYLE_DOTTED, + STYLE_DASHED, + STYLE_LONG_DASHED, + STYLE_LONG_DOT_DASHED; int STYLE_NONE_CONST=1; private enum VerticalAlign{ @@ -117,16 +103,11 @@ public int value(){ } } - /** Setea el OutputStream a utilizar - * @param outputStream Stream a utilizar - */ public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; } - /** Busca la ubicación del Acrobat. Si no la encuentra tira una excepción - */ private static String getAcrobatLocation() throws Exception { ParseINI props; @@ -140,31 +121,21 @@ private static String getAcrobatLocation() throws Exception { props = new ParseINI(); } - - // Primero debo obtener la ubicación + ejecutable del Acrobat String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property if(acrobatLocation == null) { if(NativeFunctions.isUnix()) - { // Si estoy en Unix no puedo ir a buscar el registry ;) + { throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); } } return acrobatLocation; } - /** Manda a imprimir el reporte a la impresora - * Si en las properties del PDFReport esta definida una GeneralProperty 'Acrobat Location' se - * utiliza esta property para obtener la ubicación + ejecutable del Acrobat, sino se busca en el Registry - * @param pdfFilename Nombre del reporte a imprimir (con extensión) - * @param silent Booleano que indica si se va a imprimir sin diálogo - * @exception Exception si no se puede realizar la operación - */ public static void printReport(String pdfFilename, boolean silent) throws Exception { if(NativeFunctions.isWindows()) - { // En Windows obtenemos el full path - // En Linux esto no anda bien + { pdfFilename = "\"" + new File(pdfFilename).getAbsolutePath() + "\""; } @@ -172,17 +143,12 @@ public static void printReport(String pdfFilename, boolean silent) throws Except String acrobatLocation = null; try { - // Primero debo obtener la ubicación + ejecutable del Acrobat acrobatLocation = getAcrobatLocation(); }catch(Exception acrobatNotFound) { throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); } - - //Se genera el PostScript nativeCode.executeModal(acrobatLocation + " -toPostScript " + pdfFilename, false); - - //Se manda a imprimir a la impresora default int pos = pdfFilename.lastIndexOf("."); pdfFilename = pdfFilename.substring(0, pos) + ".ps"; cmd = new String[] { "lp", pdfFilename}; @@ -197,20 +163,17 @@ public static void printReport(String pdfFilename, boolean silent) throws Except public static void showReport(String filename, boolean modal) throws Exception { if(NativeFunctions.isWindows()) - { // En Windows obtenemos el full path - // En Linux esto no anda bien + { filename = "\"" + new File(filename).getAbsolutePath() + "\""; } String acrobatLocation; try { - // Primero debo obtener la ubicación + ejecutable del Acrobat acrobatLocation = getAcrobatLocation(); }catch(Exception acrobatNotFound) { throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); } - if(modal) { nativeCode.executeModal(acrobatLocation + " " + filename, true); @@ -241,7 +204,7 @@ public PDFReportpdfbox(ModelContext context) defaultRelativePrependINI = defaultRelativePrepend; if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) { - configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; // Esto es para que en aplicaciones web el PDFReport.INI no quede visible en el server + configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; configurationTemplateFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_TEMPLATE_FILE; } else @@ -253,25 +216,12 @@ public PDFReportpdfbox(ModelContext context) if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) { - // @cambio: 23/07/03 - // Para los reportes en el web, debemos tener en cuenta la preference 'Static Content Base URL' del modelo - // Pero SOLO la tenemos en cuenta si es un directorio relativo - // O sea, si la preference dice algo tipo /pepe, entonces vamos a buscar las - // imagenes relativas a %WebApp%/pepe, pero si la preference dice algo tipo - // 'http://otroServer/xxxyyy' entonces ahi no le damos bola a la preference! - // Además, para mantener compatibilidad con las aplicaciones hasta ahora, si la imagen - // no se encuentra all\uFFFDElo que hacemos es ir a buscarla a %WebApp% - - // @cambio: 12/09/17 - // Esto tambien se tiene que hacer para los reportes web que se llaman con submit - // (ese es el caso en el cual el getDefaultPath no es Empty) - String staticContentBase = httpContext.getStaticContentBase(); if(staticContentBase != null) { staticContentBase = staticContentBase.trim(); if(staticContentBase.indexOf(':') == -1) - { // Si la staticContentBase es una ruta relativa + { staticContentBase = staticContentBase.replace(alternateSeparator, File.separatorChar); if(staticContentBase.startsWith(File.separator)) { @@ -362,7 +312,7 @@ private void loadProps() props.setupGeneralProperty(Const.STYLE_LONG_DASHED, Const.DEFAULT_STYLE_LONG_DASHED); props.setupGeneralProperty(Const.STYLE_LONG_DOT_DASHED, Const.DEFAULT_STYLE_LONG_DOT_DASHED); - loadSubstituteTable(); // Cargo la tabla de substitutos de fonts + loadSubstituteTable(); if(props.getBooleanGeneralProperty("DEBUG", false)) { @@ -384,7 +334,7 @@ public static final void addPredefinedSearchPaths(String [] predefinedPaths) String predefinedPath = ""; for(int i = 0; i < predefinedPaths.length; i++) predefinedPath += predefinedPaths[i] + ";"; - predefinedSearchPath = predefinedPath + predefinedSearchPath; // SearchPath= los viejos más los nuevos + predefinedSearchPath = predefinedPath + predefinedSearchPath; } public static final String getPredefinedSearchPaths() @@ -397,33 +347,15 @@ private void init() try { document = new PDDocument(); document.addPage(new PDPage()); - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(((ByteArrayOutputStream) outputStream).toByteArray()); - PDDocument document = PDDocument.load(byteArrayInputStream); } catch(Exception e) { System.err.println(e.getMessage()); } } - private void fin() - { - try { - document.save(outputStream); - document.close(); - outputStream.close(); - } - catch(Exception e) { - System.err.println(e.getMessage()); - } - } + public void GxRVSetLanguage(String lang) {} - public void GxRVSetLanguage(String lang) - { - } - - public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) - { - } + public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) {} private float[] parsePattern(String patternStr) { @@ -468,15 +400,12 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl int styleTop, int styleBottom, int styleRight, int styleLeft, float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) { - - float[] dashPatternTop = getDashedPattern(styleTop); float[] dashPatternBottom = getDashedPattern(styleBottom); float[] dashPatternLeft = getDashedPattern(styleLeft); float[] dashPatternRight = getDashedPattern(styleRight); try { - //-------------------bottom line--------------------- if (styleBottom!=STYLE_NONE_CONST) { cb.setLineDashPattern(dashPatternBottom, 0); @@ -498,10 +427,7 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.moveTo(x, y); } } - - //-------------------bottom right corner--------------------- - - if (styleBottom!=STYLE_NONE_CONST)//si es null es Style None y no traza la linea + if (styleBottom!=STYLE_NONE_CONST) { if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) { @@ -516,9 +442,6 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); } } - - //-------------------right line--------------------- - if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) { cb.stroke(); @@ -532,8 +455,6 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.moveTo(x + w, y + radioBR); } } - - //-------------------top right corner--------------------- if (styleRight!=STYLE_NONE_CONST) { if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) @@ -549,9 +470,6 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); } } - - //-------------------top line--------------------- - if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) { cb.stroke(); @@ -565,8 +483,6 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.moveTo(x + w - radioTR, y + h); } } - - //-------------------top left corner--------------------- if (styleTop!=STYLE_NONE_CONST) { if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) @@ -582,9 +498,6 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); } } - - //-------------------left line--------------------- - if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) { cb.stroke(); @@ -598,8 +511,6 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl cb.moveTo(x, y + h - radioTL); } } - - //-------------------bottom left corner--------------------- if (styleLeft!=STYLE_NONE_CONST) { if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) @@ -625,8 +536,6 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f float radioTL, float radioTR, float radioBL, float radioBR) { try { - //-------------------bottom line--------------------- - float b = 0.4477f; if (radioBL>0) { @@ -636,22 +545,16 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f { cb.moveTo(x, y); } - - //-------------------bottom right corner--------------------- - cb.lineTo(x + w - radioBR, y); if (radioBR>0) { cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); } - - cb.lineTo (x + w, y + h - radioTR); if (radioTR>0) { cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); } - cb.lineTo(x + radioTL, y + h); if (radioTL>0) { @@ -681,7 +584,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { try{ - PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); float penAux = (float)convertScale(pen); @@ -703,8 +605,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) { - //Tengo que hacer eso para que el borde quede del mismo color que el fill si se indica que no se quiere borde, - //porque no funciona el setLineWidth if (pen > 0) cb.setStrokingColor(foreRed, foreGreen, foreBlue); else @@ -740,7 +640,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo float cRadioBL = (float)convertScale(cornerRadioBL); float cRadioBR = (float)convertScale(cornerRadioBR); - // Scale the radius if it's too large or to small to fit. int max = (int)Math.min(w, h); cRadioTL = Math.max(0, Math.min(cRadioTL, max/2)); cRadioTR = Math.max(0, Math.min(cRadioTR, max/2)); @@ -749,7 +648,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo if (backMode!=0) { - //Interior del rectangulo cb.setStrokingColor(backRed, backGreen, backBlue); cb.setLineWidth(0); roundRectangle(cb, x1, y1, w, h, @@ -761,7 +659,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo } if (pen > 0) { - //Bordes del rectangulo cb.setStrokingColor(foreRed, foreGreen, foreBlue); drawRectangle(cb, x1, y1, w, h, styleTop, styleBottom, styleRight, styleLeft, @@ -779,7 +676,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) { - GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); + GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); } public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) @@ -808,7 +705,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int if (lineCapProjectingSquare) { - cb.setLineCapStyle(2); //Hace que lineas de width 10 por ejemplo que forman una esquina no quedan igual que en disenio porque "rellena" la esquina. + cb.setLineCapStyle(2); } if (style!=0) { @@ -835,10 +732,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom try { PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); - - //java.awt.Image image; - org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject image; - org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject imageRef; + PDImageXObject image; try { if (documentImages != null && documentImages.containsKey(bitmap)) @@ -859,15 +753,11 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom { bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); } - // Si la ruta a la imagen NO es absoluta, en aplicaciones Web le agregamos al comienzo la ruta al root de la aplicación - // más la staticContentBaseURL si ésta es relativa. image = PDImageXObject.createFromFile(defaultRelativePrepend + bitmap,document); - //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(defaultRelativePrepend + bitmap); if(image == null) - { // Si all\uFFFDEno se encuentra la imagen, entonces la buscamos bajo el webAppDir (para mantener compatibilidad) + { bitmap = webAppDir + bitmap; image = PDImageXObject.createFromFile(bitmap,document); - //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); } else { @@ -877,19 +767,18 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom else { image = PDImageXObject.createFromFile(bitmap,document); - //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); } } } - catch(java.lang.IllegalArgumentException ex)//Puede ser una url absoluta + catch(java.lang.IllegalArgumentException ex) { - java.net.URL url= new java.net.URL(bitmap); + URL url= new java.net.URL(bitmap); image = PDImageXObject.createFromFile(url.toString(),document); } if (documentImages == null) { - documentImages = new ConcurrentHashMap(); + documentImages = new ConcurrentHashMap<>(); } documentImages.putIfAbsent(bitmap, image); @@ -897,7 +786,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom if(DEBUG)DEBUG_STREAM.println("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); if(image != null) - { // Si la imagen NO se encuentra, no hago nada + { float rightAux = (float)convertScale(right); float bottomAux = (float)convertScale(bottom); float leftAux = (float)convertScale(left); @@ -907,9 +796,9 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin; if (aspectRatio == 0) - cb.drawImage(image, x, y, image.getWidth(), image.getHeight()); + cb.drawImage(image, x, y, rightAux - leftAux, bottomAux - topAux); else - cb.drawImage(image, x, y, image.getWidth() * aspectRatio, image.getHeight() * aspectRatio); + cb.drawImage(image, x, y, (rightAux - leftAux) * aspectRatio, (bottomAux - topAux) * aspectRatio); cb.close(); } } @@ -945,7 +834,7 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo String originalFontName = fontName; if (!embeedFont) { - fontName = getSubstitute(fontName); // Veo si hay substitutos solo si el font no va a ir embebido + fontName = getSubstitute(fontName); } if(DEBUG) { @@ -980,7 +869,6 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo try { if (PDFFont.isType1(fontName)) { - //Me fijo si es un Asian font for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) { if(Type1FontMetrics.CJKNames[i][0].equalsIgnoreCase(fontName) || @@ -1020,6 +908,14 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo fontName = PDFFont.base14[i][1+style].substring(1); break; } + COSDictionary dict = new COSDictionary(); + dict.setItem(COSName.TYPE, COSName.FONT); + dict.setItem(COSName.SUBTYPE, COSName.TYPE0); + dict.setItem(COSName.BASE_FONT, COSName.getPDFName(fontName)); + dict.setItem(COSName.ENCODING, COSName.WIN_ANSI_ENCODING); + dict.setItem(COSName.DESCENDANT_FONTS, new COSArray()); + dict.setBoolean(COSName.getPDFName("Embedded"), false); + baseFont = new PDType0Font(dict); } switch (fontName.trim().toUpperCase()) { @@ -1072,7 +968,7 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } } else - {//Si el Font es true type + { String style = ""; if (fontBold && fontItalic) style = ",BoldItalic"; @@ -1092,26 +988,14 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo fontPath = PDFFontDescriptor.getTrueTypeFontLocation(fontName, props); if (fontPath.equals("")) { - COSDictionary fontDict = new COSDictionary(); - fontDict.setItem(COSName.TYPE, COSName.FONT); - fontDict.setItem(COSName.SUBTYPE, COSName.TYPE1); - fontDict.setItem(COSName.BASE_FONT, COSName.getPDFName("Helvetica")); - fontDict.setItem(COSName.ENCODING, COSName.getPDFName("WinAnsiEncoding")); - COSDictionary fontDescriptor = new COSDictionary(); - fontDescriptor.setItem(COSName.TYPE, COSName.FONT_DESC); - fontDescriptor.setItem(COSName.FONT_NAME, COSName.getPDFName("Helvetica")); - fontDescriptor.setItem(COSName.FONT_FAMILY, new COSString("Helvetica")); - fontDescriptor.setItem(COSName.FONT_WEIGHT, COSInteger.ONE); - COSArray fontBBox = new COSArray(); - fontBBox.add(new COSFloat(-166)); - fontBBox.add(new COSFloat(-225)); - fontBBox.add(new COSFloat(1000)); - fontBBox.add(new COSFloat(931)); - fontDescriptor.setItem(COSName.ASCENT, new COSFloat(718)); - fontDescriptor.setItem(COSName.DESCENT, new COSFloat(-207)); - fontDict.setItem(COSName.FONT_DESC, fontDescriptor); - - baseFont = new PDType0Font(fontDict); + COSDictionary dict = new COSDictionary(); + dict.setItem(COSName.TYPE, COSName.FONT); + dict.setItem(COSName.SUBTYPE, COSName.TYPE0); + dict.setItem(COSName.BASE_FONT, COSName.HELV); + dict.setItem(COSName.ENCODING, COSName.WIN_ANSI_ENCODING); + dict.setItem(COSName.DESCENDANT_FONTS, new COSArray()); + dict.setItem(COSName.FONT_FILE2, COSNull.NULL); + baseFont = new PDType0Font(dict); foundFont = false; } } @@ -1122,15 +1006,7 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo baseFont = PDType0Font.load(document,new File(fontPath)); } else - {//No se embebe el font - COSDictionary fontDict = new COSDictionary(); - fontDict.setName(COSName.TYPE, "Font"); - fontDict.setName(COSName.SUBTYPE, "TrueType"); - fontDict.setItem(COSName.DESC, null); - byte[] fontBytes = Files.readAllBytes(Paths.get(fontPath + style)); - PDStream fontStream = new PDStream(document, new ByteArrayInputStream(fontBytes)); - fontDict.setItem(COSName.FONT_FILE2, fontStream); - baseFont = new PDType0Font(fontDict); + { baseFont = PDType0Font.load(); } } } @@ -1296,23 +1172,15 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in int bottomOri = bottom; int topOri = top; - //Si se tiene un campo con mas de una linea y no tiene wrap, no es justify, y no es html, se simula que el campo tiene una sola linea - //asignando al bottom el top mas el lineHeight if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) { if (valign == PDFReportpdfbox.VerticalAlign.TOP.value()) bottom = top + (int)reconvertScale(lineHeight); else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) top = bottom - (int)reconvertScale(lineHeight); - //if valign == middle, no se cambia ni top ni bottom } float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; - //Al bottom de los textos se le resta espacio entre el texto y el borde del textblock, - //porque en el reporte genexus la x,y de un - //text es la x,y del cuadro que contiene el texto, y la api de itext espera la x,y del texto en si. - //Generalmente el cuadro es mas grande que lo que ocupa el texto realmente (depende del tipo de font) - //captionHeight esta convertido, bottom y top no. float topAux = (float)convertScale(top) + ((float)convertScale(bottom-top) - captionHeight)/2; @@ -1338,7 +1206,6 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) if(backFill) { PDRectangle rectangle = new PDRectangle(0,0); - //Si el texto tiene background lo dibujo de esta forma switch(alignment) { case 1: // Center Alignment @@ -1366,11 +1233,10 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } - float underlineSeparation = lineHeight / 5;//Separacion entre el texto y la linea del subrayado + float underlineSeparation = lineHeight / 5; int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation/4); PDRectangle underline; - //Si el texto esta subrayado if (fontUnderline) { underline = new PDRectangle(0,0); @@ -1412,7 +1278,6 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } - //Si el texto esta tachado if (fontStrikethru) { underline = new PDRectangle(0,0); @@ -1441,7 +1306,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) break; } PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.setNonStrokingColor(foreColor); // set background color to yellow + contentStream.setNonStrokingColor(foreColor); contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); contentStream.close(); @@ -1456,7 +1321,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) - {// Si el texto es la cantidad de páginas del documento + { if (!templateCreated) { PDFormXObject template = new PDFormXObject(document); @@ -1467,7 +1332,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) PDFormXObject form = new PDFormXObject(document); PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); - contentStream.drawForm(form); // draw the form onto th + contentStream.drawForm(form); templateFont = baseFont; templateFontSize = fontSize; templateColorFill = foreColor; @@ -1479,14 +1344,11 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; boolean wrap = ((align & 16) == 16); - //Justified if (wrap || justified) { - //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. bottomAux = (float)convertScale(bottomOri); topAux = (float)convertScale(topOri); - //La constante 2 para LEADING indica la separacion que se deja entre un renglon y otro. (es lo que mas se asemeja a la api vieja). float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); PDAnnotationText annotation = new PDAnnotationText(); String alignmentString; @@ -1517,14 +1379,11 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) e.printStackTrace(System.err); } } - else //no wrap + else { startHeight=0; if (!autoResize) { - //Va quitando el ultimo char del texto hasta que llega a un string cuyo ancho se pasa solo por un caracter - //del ancho del textblock ("se pasa solo por un caracter": esto es porque en el caso general es ese el texto que - //mas se parece a lo que se disenia en genexus). String newsTxt = sTxt; while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) { @@ -1578,75 +1437,13 @@ boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ return bottomAux > drawingPageHeight; } - /* - ColumnText SimulateDrawColumnText(PdfContentByte cb, Rectangle rect, Paragraph p, float leading, int runDirection, int alignment) throws DocumentException - { - ColumnText Col = new ColumnText(cb); - Col.setRunDirection(runDirection); - Col.setAlignment(alignment); - Col.setLeading(leading, 1); - Col.setSimpleColumn(rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()); - Col.addText(p); - Col.go(true); - return Col; - } - */ - /* - void DrawColumnText(PDPageContentStream cb, float llx, float lly, float urx, float ury, float leading, Matrix runDirection, int valign, int alignment) throws DocumentException - { - Rectangle rect = new Rectangle(llx, lly, urx, ury); - ColumnText ct = SimulateDrawColumnText(cb, rect, p, leading, runDirection, alignment);//add the column in simulation mode - float y = ct.getYLine(); - int linesCount = ct.getLinesWritten(); - - //calculate a new rectangle for valign = middle - if (valign == PDFReportItext.VerticalAlign.MIDDLE.value()) - ury = ury - ((y - lly) / 2) + leading; - else if (valign == PDFReportItext.VerticalAlign.BOTTOM.value()) - ury = ury - (y - lly- leading); - else if (valign == PDFReportItext.VerticalAlign.TOP.value()) - ury = ury + leading/2; - - rect = new Rectangle(llx, lly, urx, ury); //Rectangle for new ury - - ColumnText Col = new ColumnText(cb); - Col.setRunDirection(runDirection); - if (linesCount <= 1) - Col.setLeading(0, 1); - else - Col.setLeading(leading, 1); - Col.setSimpleColumn(rect.getLeft(), rect.getBottom(), rect.getRight(), rect.getTop()); - - Col.setAlignment(columnAlignment(alignment)); - Col.addText(p); - Col.go(); - } + public void GxClearAttris() {} - */ - - /* - private int columnAlignment(int alignment) - { - if (alignment == Element.ALIGN_JUSTIFIED) - return justifiedType; - else - return alignment; - } - - */ - - public void GxClearAttris() - { - } - - public static final double PAGE_SCALE_Y = 20; // Indica la escala de la página - public static final double PAGE_SCALE_X = 20; // Indica la escala de la página + public static final double PAGE_SCALE_Y = 20; + public static final double PAGE_SCALE_X = 20; public static final double GX_PAGE_SCALE_Y_OLD = 15.45; - public static final double GX_PAGE_SCALE_Y = 14.4; // Indica la escala de la página, GeneXus lleva otra escala para el tamaño de la hoja, (variando este parametro, se agranda o achica el tamaño imprimible por GeneXus) - //Por ejemplo: si en genexus se tiene un reporte con Paper Height de 1169 (A4) centésimos de pulgada (1/100 inch), - //en el parámetro pageLength llega 16834 que esta en Twips (16834 = 1169*14.4). 1 twip = 1/1440 inch. - //Con el valor anterior 15.45 estaba quedando un margen bottom fijo que no se podia eliminar (incluso seteando mb 0). - private static double TO_CM_SCALE =28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) + public static final double GX_PAGE_SCALE_Y = 14.4; + private static double TO_CM_SCALE =28.6; public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { PPP = gxYPage[0]; @@ -1685,10 +1482,10 @@ else if(output.equalsIgnoreCase("PRN")) { setOutputStream(new FileOutputStream(docName)); }catch(IOException accessError) - { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream + { accessError.printStackTrace(System.err); outputStream = new com.genexus.util.NullOutputStream(); - outputType = Const.OUTPUT_FILE; // Hago esto para no tener lios con el Acrobat + outputType = Const.OUTPUT_FILE; } } printerOutputMode = mode; @@ -1710,35 +1507,18 @@ else if(output.equalsIgnoreCase("PRN")) runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); - - //Se ignora el parametro orientation para el calculo del pageSize, los valores de alto y ancho ya vienen invertidos si Orientation=2=landscape. this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); gxXPage[0] = (int)this.pageSize.getUpperRightX (); if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) - gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); // Cuanto menor sea GX_PAGE_SCALE_Y, GeneXus imprime mayor parte de cada hoja + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); else - gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); // Cuanto menor sea GX_PAGE_SCALE_Y, GeneXus imprime mayor parte de cada hoja - - - //Ahora chequeamos que el margen asociado en el PDFReport.INI sea correcto, y si es inválido, asociamos el que sea por defecto - //if(leftMargin > this.pageSize.width || topMargin > this.pageSize.height) - //{ // Si el margen asociado es mayor que el tamaño de la página, entonces asociamos los márgenes por default - - //float leftMargin = (float) (TO_CM_SCALE * Double.valueOf(Const.DEFAULT_LEFT_MARGIN).doubleValue()); - //float topMargin = (float) (TO_CM_SCALE * Double.valueOf(Const.DEFAULT_TOP_MARGIN).doubleValue()); - - //float rightMargin = 0; - //float bottomMargin = 0; - //System.err.println("Invalid page Margin... Resetting to defaults"); - //} + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); document = new PDDocument(); document.addPage(new PDPage(this.pageSize)); init(); - //if(DEBUG)DEBUG_STREAM.println("GxPrintInit ---> Size:" + this.pageSize + " Orientation: " + (pageOrientation == PDFPage.PORTRAIT ? "Portrait" : "Landscape")); - return true; } @@ -1813,24 +1593,14 @@ public void setM_bot(int M_bot) this.M_bot = M_bot; } - public void GxEndPage() - { - //if(DEBUG)DEBUG_STREAM.println("GxEndPage"); - - //if(document != null && !isPageDirty) - // document.dispose(); -// if(document == null) GxStartPage(); // Si la página esta vacú}, la agrego primero al PDF. Esto hace que haya una hoja vacú} al final, as\uFFFDEque lo saco -// document = null; // La nueva página est\uFFFDEvacú} - } + public void GxEndPage() {} public void GxEndDocument() { if(document.getNumberOfPages() == 0) - { // Si no hay ninguna página en el documento, agrego una vacia} + { document.addPage(new PDPage(this.pageSize)); } - - //Ahora proceso los comandos GeneXus {{Pages}} if (template != null) { try{ @@ -1887,12 +1657,8 @@ public void GxEndDocument() boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { - //writer.addJavaScript("if (this.external)\n");//Specifies whether the current document is being viewed in the Acrobat application or in an external window (such as a web browser). - //writer.addJavaScript("app.alert('SI es externa' + this.external);"); - PDActionJavaScript jsAction = new PDActionJavaScript(); jsAction.setAction("var pp = this.getPrintParams();\n"); - //writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); String printerAux=printerSettings.getProperty(form, Const.PRINTER); String printer = replace(printerAux, "\\", "\\\\"); @@ -1913,19 +1679,14 @@ public void GxEndDocument() if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0"))//Show printer dialog Never { jsAction.setAction("pp.interactive = pp.constants.interactionLevel.automatic;\n"); - //No print dialog is displayed. During printing a progress monitor and cancel - //dialog is displayed and removed automatically when printing is complete. for(int i = 0; i < copies; i++) { jsAction.setAction("this.print(pp);\n"); } } - else //Show printer dialog is sent directly to printer | always + else { jsAction.setAction("pp.interactive = pp.constants.interactionLevel.full;\n"); - //Displays the print dialog allowing the user to change print settings and requiring - //the user to press OK to continue. During printing a progress monitor and cancel - //dialog is displayed and removed automatically when printing is complete. jsAction.setAction("this.print(pp);\n"); } @@ -1936,42 +1697,32 @@ public void GxEndDocument() System.err.println(e.getMessage()); } - if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); - //showInformation(); - //ParseINI props = pdf.getPDF().props; - //pdf.end(); try{ props.save(); } catch(IOException e) { ; } - - // OK, ahora que ya terminamos el PDF, vemos si tenemos que mostrarlo en pantalla switch(outputType) { case Const.OUTPUT_SCREEN: - try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo - try{ showReport(docName, modal); } catch(Exception e) - { // Si no se puede mostrar el reporte + try{ outputStream.close(); } catch(IOException e) { } + try{ showReport(docName, modal); } + catch(Exception e) { e.printStackTrace(); } - // Comento la próxima lú‹ea, porque por manejo interno del Acrobat, si ya habú} una instancia del - // Acrobat corriendo, el modal no funciona (x que el proceso levantado le avisa al que ya estaba abierto qu\uFFFDE - // archivo abrir y luego se mata automáticamente) - // if(modal)if(new File(docName).delete())TemporaryFiles.getInstance().removeFileFromList(docName); // Intento eliminar el docName aqu\uFFFDE break; case Const.OUTPUT_PRINTER: - try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo + try{ outputStream.close(); } catch(IOException e) { } try{ if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) { printReport(docName, this.printerOutputMode == 1); } - } catch(Exception e){ // Si no se puede mostrar el reporte + } catch(Exception e){ e.printStackTrace(); } break; case Const.OUTPUT_FILE: - try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo + try{ outputStream.close(); } catch(IOException e) { ; } break; case Const.OUTPUT_STREAM: case Const.OUTPUT_STREAM_PRINTER: @@ -1980,24 +1731,15 @@ public void GxEndDocument() outputStream = null; } - public void GxEndPrinter() - { - //DEBUG.println("Processing..."); - } + public void GxEndPrinter() {} public void GxStartPage() { document.addPage(new PDPage()); pages = pages +1; } - public void GxStartDoc() - { - //DEBUG.println("Processing..."); - } - public void GxSetDocFormat(String format) - { - //DEBUG.println("Processing..."); - } + public void GxStartDoc() {} + public void GxSetDocFormat(String format) {} public void GxSetDocName(String docName) { @@ -2005,7 +1747,7 @@ public void GxSetDocName(String docName) if(this.docName.indexOf('.') < 0) this.docName += ".pdf"; if(!new File(docName).isAbsolute()) - { // Si el nombre del documento es relativo, veo si hay que agregarle el outputDir + { String outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").replace(alternateSeparator, File.separatorChar).trim(); if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) { @@ -2036,13 +1778,11 @@ public void GxSetDocName(String docName) public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { - //DEBUG.println("Processing..."); return true; } public boolean GxPrnCfg( String ini ) { - //DEBUG.println("Processing..."); return true; } @@ -2056,7 +1796,6 @@ public boolean GxIsAliveDoc() return true; } - private int page; public int getPage() { @@ -2079,33 +1818,25 @@ public void setModal(boolean modal) public void cleanup() {} - public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) - { - } - + public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) {} /** Carga la tabla de substitutos */ private void loadSubstituteTable() { - // Primero leemos la tabla de substitutos del Registry Hashtable> tempInverseMappings = new Hashtable<>(); - // Seteo algunos Mappings que Acrobat toma como Type1 for(int i = 0; i < Const.FONT_SUBSTITUTES_TTF_TYPE1.length; i++) fontSubstitutes.put(Const.FONT_SUBSTITUTES_TTF_TYPE1[i][0], Const.FONT_SUBSTITUTES_TTF_TYPE1[i][1]); - // Ahora inserto los mappings extra del PDFReport.INI (si es que hay) - // Los font substitutes del PDFReport.INI se encuentran bajo la seccion - // indicada por Const.FONT_SUBSTITUTES_SECTION y son pares oldFont -> newFont Hashtable otherMappings = props.getSection(Const.FONT_SUBSTITUTES_SECTION); if(otherMappings != null) for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) { String fontName = (String)enumera.nextElement(); fontSubstitutes.put(fontName, (String)otherMappings.get(fontName)); - if(tempInverseMappings.containsKey(fontName)) // Con esto solucionamos el tema de la recursión de Fonts -> Fonts - { // x ej: Si tenú} Font1-> Font2, y ahora tengo Font2->Font3, pongo cambio el 1º por Font1->Font3 + if(tempInverseMappings.containsKey(fontName)) + { String fontSubstitute = (String)otherMappings.get(fontName); for(Enumeration enum2 = tempInverseMappings.get(fontName).elements(); enum2.hasMoreElements();) fontSubstitutes.put(enum2.nextElement(), fontSubstitute); @@ -2121,10 +1852,7 @@ private void loadSubstituteTable() public void GxPrintOnTop() { ; } public void GxPrnCmd(String cmd) { ; } - - public void showInformation() - { - } + public void showInformation() {} public static final double SCALE_FACTOR = 72; private double PPP = 96; @@ -2146,12 +1874,6 @@ private float reconvertScale(float value) return result; } - class FontProps - { - public int horizontal; - public int vertical; - } - /** * Helper method for toString() * @param s source string @@ -2171,44 +1893,10 @@ private static String replace(String s,String f,String t) { } } - // include any remaining text if(p Date: Tue, 21 Mar 2023 10:48:46 -0300 Subject: [PATCH 05/32] Small fixes --- .../com/genexus/reports/PDFReportpdfbox.java | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 249061241..40848d42e 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -3,8 +3,6 @@ import java.awt.Color; import java.io.*; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -20,11 +18,9 @@ import com.genexus.reports.fonts.Type1FontMetrics; import com.genexus.reports.fonts.Utilities; -import com.lowagie.text.pdf.BaseFont; import org.apache.pdfbox.cos.*; import org.apache.pdfbox.pdmodel.*; import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.apache.pdfbox.pdmodel.common.PDStream; import org.apache.pdfbox.pdmodel.font.*; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; @@ -1006,7 +1002,11 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo baseFont = PDType0Font.load(document,new File(fontPath)); } else - { baseFont = PDType0Font.load(); + { + baseFont = PDType0Font.load(document,new File(fontPath + style)); + COSDictionary dict = baseFont.getCOSObject(); + dict.setItem(COSName.ENCODING, COSName.IDENTITY_H); + dict.setItem(COSName.FONT_FILE2, COSNull.NULL); } } } @@ -1159,14 +1159,14 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in COSDictionary fontDict = baseFont.getCOSObject(); COSDictionary newFontDict = new COSDictionary(fontDict); newFontDict.setFloat(COSName.SIZE, fontSize); - PDType0Font auxFont = new PDType0Font(newFontDict); - cb.setFont(font,fontSize); + PDType0Font font = new PDType0Font(newFontDict); + cb.setFont(font,fontSize); cb.setNonStrokingColor(foreColor); int arabicOptions = 0; - float captionHeight = auxFont.getFontDescriptor().getCapHeight(); - float rectangleWidth = auxFont.getStringWidth(sTxt); - float lineHeight = auxFont.getFontDescriptor().getFontBoundingBox().getUpperRightY() - auxFont.getFontDescriptor().getFontBoundingBox().getLowerLeftX(); + float captionHeight = font.getFontDescriptor().getCapHeight(); + float rectangleWidth = font.getStringWidth(sTxt); + float lineHeight = font.getFontDescriptor().getFontBoundingBox().getUpperRightY() - font.getFontDescriptor().getFontBoundingBox().getLowerLeftX(); float textBlockHeight = (float)convertScale(bottom-top); int linesCount = (int)(textBlockHeight/lineHeight); int bottomOri = bottom; @@ -1219,7 +1219,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) break; } PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.setNonStrokingColor(backColor); // set background color to yellow + contentStream.setNonStrokingColor(backColor); contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); contentStream.fill(); contentStream.close(); @@ -1657,39 +1657,41 @@ public void GxEndDocument() boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { - PDActionJavaScript jsAction = new PDActionJavaScript(); - jsAction.setAction("var pp = this.getPrintParams();\n"); + PDDocumentCatalog catalog = document.getDocumentCatalog(); + StringBuffer jsActions = new StringBuffer(); + jsActions.append("var pp = this.getPrintParams();\n"); String printerAux=printerSettings.getProperty(form, Const.PRINTER); String printer = replace(printerAux, "\\", "\\\\"); if (printer!=null && !printer.equals("")) { - jsAction.setAction("pp.printerName = \"" + printer + "\";\n"); + jsActions.append("pp.printerName = \"" + printer + "\";\n"); } if (fit) { - jsAction.setAction("pp.pageHandling = pp.constants.handling.fit;\n"); + jsActions.append("pp.pageHandling = pp.constants.handling.fit;\n"); } else { - jsAction.setAction("pp.pageHandling = pp.constants.handling.none;\n"); + jsActions.append("pp.pageHandling = pp.constants.handling.none;\n"); } - if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0"))//Show printer dialog Never + if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")) { - jsAction.setAction("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + jsActions.append("pp.interactive = pp.constants.interactionLevel.automatic;\n"); for(int i = 0; i < copies; i++) { - jsAction.setAction("this.print(pp);\n"); + jsActions.append("this.print(pp);\n"); } } else { - jsAction.setAction("pp.interactive = pp.constants.interactionLevel.full;\n"); - jsAction.setAction("this.print(pp);\n"); + jsActions.append("pp.interactive = pp.constants.interactionLevel.full;\n"); + jsActions.append("this.print(pp);\n"); } - + PDActionJavaScript openActions = new PDActionJavaScript(jsActions.toString()); + catalog.setOpenAction(openActions); } try { document.close(); From 5b1f53394ff0e65ae3ce0fff14acbc8076267756 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 22 Mar 2023 12:35:14 -0300 Subject: [PATCH 06/32] Various fixes --- .../com/genexus/reports/PDFReportpdfbox.java | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 40848d42e..4c68cbd2b 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -66,6 +66,7 @@ public class PDFReportpdfbox implements IReportHandler{ private float topMargin; private float bottomMargin; private PDPageContentStream template; + private PDFormXObject formXObjecttemplate; private PDType0Font templateFont; private int templateFontSize; private boolean backFill = true; @@ -187,7 +188,7 @@ public PDFReportpdfbox(ModelContext context) document = null; pageSize = null; stringTotalPages = new Vector(); - documentImages = new ConcurrentHashMap(); + documentImages = new ConcurrentHashMap<>(); httpContext = (HttpContext) context.getHttpContext(); if(defaultRelativePrepend == null) @@ -342,7 +343,6 @@ private void init() { try { document = new PDDocument(); - document.addPage(new PDPage()); } catch(Exception e) { System.err.println(e.getMessage()); @@ -1324,9 +1324,10 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) { if (!templateCreated) { - PDFormXObject template = new PDFormXObject(document); - template.setResources(new PDResources()); - template.setBBox(new PDRectangle(right - left, bottom - top)); + formXObjecttemplate = new PDFormXObject(document); + template = new PDPageContentStream(document, formXObjecttemplate, outputStream); + formXObjecttemplate.setResources(new PDResources()); + formXObjecttemplate.setBBox(new PDRectangle(right - left, bottom - top)); templateCreated = true; } PDFormXObject form = new PDFormXObject(document); @@ -1514,9 +1515,6 @@ else if(output.equalsIgnoreCase("PRN")) else gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); - document = new PDDocument(); - document.addPage(new PDPage(this.pageSize)); - init(); return true; @@ -1565,7 +1563,6 @@ public void setPageLines(int P_lines) } public void setLineHeight(int lineHeight) { - if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); this.lineHeight = lineHeight; } @@ -1600,21 +1597,25 @@ public void GxEndDocument() if(document.getNumberOfPages() == 0) { document.addPage(new PDPage(this.pageSize)); + pages++; } if (template != null) { try{ + template.beginText(); + template.setFont(baseFont, fontSize); + template.setTextMatrix(new Matrix()); + template.setNonStrokingColor(templateColorFill); + template.showText(String.valueOf(pages)); + template.endText(); + template.close(); for (PDPage page : document.getPages()){ - template = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true); - template.beginText(); - template.setFont(baseFont, fontSize); - template.setTextMatrix(new Matrix()); - template.setNonStrokingColor(templateColorFill); - template.showText(String.valueOf(pages)); - template.endText(); - } - } catch (IOException e){ } + PDPageContentStream templatePainter = new PDPageContentStream(document, page); + templatePainter.drawForm(formXObjecttemplate); + templatePainter.close(); + } + } catch (IOException e){ System.err.println(e.getMessage()); } } int copies = 1; try @@ -1623,8 +1624,10 @@ public void GxEndDocument() if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); writer = document.getDocumentCatalog(); - COSDictionary dict = writer.getViewerPreferences().getCOSObject(); - if (dict == null) {dict = new COSDictionary();} + + COSDictionary dict = new COSDictionary(); + if (writer.getViewerPreferences() != null && writer.getViewerPreferences().getCOSObject() != null) + dict = writer.getViewerPreferences().getCOSObject(); PDViewerPreferences viewerPreferences = new PDViewerPreferences(dict); viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); dict.setInt("NumCopies", copies); @@ -1694,6 +1697,8 @@ public void GxEndDocument() catalog.setOpenAction(openActions); } try { + String pdfFilename = new File(docName).getAbsolutePath(); + document.save(pdfFilename); document.close(); } catch (IOException e) { System.err.println(e.getMessage()); @@ -1737,7 +1742,7 @@ public void GxEndPrinter() {} public void GxStartPage() { document.addPage(new PDPage()); - pages = pages +1; + pages++; } public void GxStartDoc() {} @@ -1846,7 +1851,6 @@ private void loadSubstituteTable() } } - /** Estos métodos no hacen nada en este contexto */ public void GxPrintMax() { ; } From c59c8367262027708d7cfad8bd5454d368c36a56 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 22 Mar 2023 15:46:38 -0300 Subject: [PATCH 07/32] close streams and added dependencies --- java/pom.xml | 6 - .../com/genexus/reports/PDFReportpdfbox.java | 113 ++++++++++-------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/java/pom.xml b/java/pom.xml index 8d0ac0f60..3c6fb199d 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -114,12 +114,6 @@ org.apache.pdfbox pdfbox 2.0.27 - - - * - * - - com.sap.conn.jco diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 4c68cbd2b..9e15546bc 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -579,8 +579,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { - try{ - PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ float penAux = (float)convertScale(pen); float rightAux = (float)convertScale(right); @@ -677,8 +676,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { - try { - PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ float widthAux = (float)convertScale(width); float rightAux = (float)convertScale(right); @@ -725,9 +723,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { - try - { - PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ PDImageXObject image; try { @@ -1143,7 +1139,7 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { - try{ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ boolean printRectangle = false; if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) printRectangle = true; @@ -1153,7 +1149,6 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in GxDrawRect(left, top, right, bottom, border, foreColor.getRed(), foreColor.getGreen(), foreColor.getBlue(), backFill ? 1 : 0, backColor.getRed(), backColor.getGreen(), backColor.getBlue(), 0, 0); } - PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page)); sTxt = CommonUtil.rtrim(sTxt); COSDictionary fontDict = baseFont.getCOSObject(); @@ -1218,14 +1213,15 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); contentStream.setNonStrokingColor(backColor); contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); contentStream.fill(); contentStream.close(); try { - document.getPage(page).setMediaBox(rectangle); + document.getPage(page - 1).setMediaBox(rectangle); + contentStream.close(); } catch(Exception e) { @@ -1263,14 +1259,15 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); contentStream.setNonStrokingColor(foreColor); // set background color to yellow contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); contentStream.close(); try { - document.getPage(page).setMediaBox(underline); + document.getPage(page - 1).setMediaBox(underline); + contentStream.close(); } catch(Exception e) { @@ -1305,14 +1302,15 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); contentStream.setNonStrokingColor(foreColor); contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); contentStream.close(); try { - document.getPage(page).setMediaBox(underline); + document.getPage(page - 1).setMediaBox(underline); + contentStream.close(); } catch(Exception e) { @@ -1331,9 +1329,10 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) templateCreated = true; } PDFormXObject form = new PDFormXObject(document); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); contentStream.drawForm(form); + contentStream.close(); templateFont = baseFont; templateFontSize = fontSize; templateColorFill = foreColor; @@ -1368,8 +1367,8 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); try{ - document.getPage(page).getAnnotations().add(annotation); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + document.getPage(page - 1).getAnnotations().add(annotation); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); contentStream.beginText(); contentStream.showText(annotation.getContents()); contentStream.endText(); @@ -1394,39 +1393,46 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.beginText(); - contentStream.setFont(baseFont, fontSize); + try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1))){ - switch(alignment) - { - case 1: // Center Alignment - float x = ((leftAux + rightAux) / 2) + leftMargin; - float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.newLineAtOffset(x, y); - cb.setHorizontalScaling(1f); - contentStream.showText(sTxt); - contentStream.endText(); - contentStream.close(); - break; - case 2: // Right Alignment - x = rightAux + leftMargin; - y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.newLineAtOffset(x, y); - contentStream.showText(sTxt); - cb.setHorizontalScaling(1f); - contentStream.endText(); - contentStream.close(); - break; - case 0: // Left Alignment - case 3: // Justified, only one text line - x = (leftAux + rightAux) / 2 + leftMargin; - y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - cb.newLineAtOffset(x, y); - cb.setHorizontalScaling(1f); - cb.showText(sTxt); - cb.endText(); - break; + switch(alignment) + { + case 1: // Center Alignment + float x = ((leftAux + rightAux) / 2) + leftMargin; + float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + contentStream.setHorizontalScaling(1f); + contentStream.setFont(baseFont, fontSize); + contentStream.beginText(); + contentStream.newLineAtOffset(x, y); + contentStream.showText(sTxt); + contentStream.endText(); + contentStream.close(); + break; + case 2: // Right Alignment + x = rightAux + leftMargin; + y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + contentStream.setHorizontalScaling(1f); + contentStream.setFont(baseFont, fontSize); + contentStream.beginText(); + contentStream.newLineAtOffset(x, y); + contentStream.showText(sTxt); + contentStream.endText(); + contentStream.close(); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + x = (leftAux + rightAux) / 2 + leftMargin; + y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + contentStream.setHorizontalScaling(1f); + contentStream.setFont(baseFont, fontSize); + contentStream.beginText(); + contentStream.newLineAtOffset(x, y); + contentStream.showText(sTxt); + contentStream.endText(); + break; + } + } catch (Exception e) { + System.err.println(e.getMessage()); } } } @@ -1610,11 +1616,12 @@ public void GxEndDocument() template.endText(); template.close(); for (PDPage page : document.getPages()){ - PDPageContentStream templatePainter = new PDPageContentStream(document, page); - templatePainter.drawForm(formXObjecttemplate); - templatePainter.close(); + try (PDPageContentStream templatePainter = new PDPageContentStream(document, page)) { + templatePainter.drawForm(formXObjecttemplate); + } } + template.close(); } catch (IOException e){ System.err.println(e.getMessage()); } } int copies = 1; From b2b4d1c6152f4e1d14e513316fd7f882ccf54b7e Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Thu, 23 Mar 2023 16:56:26 -0300 Subject: [PATCH 08/32] Initial parent and children refactoring --- .../com/genexus/reports/GXReportPainter.java | 769 ++++++++++++++++++ .../com/genexus/reports/PDFReportItext.java | 551 ++----------- .../com/genexus/reports/PDFReportpdfbox.java | 479 ++--------- 3 files changed, 886 insertions(+), 913 deletions(-) create mode 100644 java/src/main/java/com/genexus/reports/GXReportPainter.java diff --git a/java/src/main/java/com/genexus/reports/GXReportPainter.java b/java/src/main/java/com/genexus/reports/GXReportPainter.java new file mode 100644 index 000000000..a5e395996 --- /dev/null +++ b/java/src/main/java/com/genexus/reports/GXReportPainter.java @@ -0,0 +1,769 @@ +package com.genexus.reports; + +import com.genexus.ModelContext; +import com.genexus.internet.HttpContext; +import com.genexus.platform.INativeFunctions; +import com.genexus.platform.NativeFunctions; +import com.genexus.reports.fonts.Utilities; +import com.genexus.webpanels.HttpContextWeb; + +import java.awt.*; +import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class GXReportPainter implements IReportHandler{ + protected int lineHeight, pageLines; + protected int pageOrientation; // Indica la orientacion de las páginas + + protected boolean fontUnderline; + protected boolean fontStrikethru; + protected int fontSize; + protected boolean fontBold = false; + protected boolean fontItalic = false; + protected Color backColor, foreColor; + public static PrintStream DEBUG_STREAM; + protected OutputStream outputStream = null; // Contiene el OutputStream de salida del reporte + //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página + protected static ParseINI props; + protected ParseINI printerSettings; + protected String form; + protected Vector stringTotalPages; // Contiene la lista de locations del parámetros {{Pages}} + protected boolean isPageDirty; // Indica si la pagina NO se debe 'dispose()'ar pues se le va a agregar cosas al terminar el PDF + protected int outputType = -1; // Indica el tipo de Output que se desea para el documento + protected int printerOutputMode = -1; // Indica si se debe mostrar el cuadro de Impresion para la salida por impresora + protected boolean modal = false; // Indica si el diálogo debe ser modal o no modal en + protected String docName = "PDFReport.pdf"; // Nombre del documento a generar (se cambia con GxSetDocName) + private static INativeFunctions nativeCode = NativeFunctions.getInstance(); + private static Hashtable fontSubstitutes = new Hashtable<>(); // Contiene la tabla de substitutos de fonts (String <--> String) + private static String configurationFile = null; + private static String configurationTemplateFile = null; + private static String defaultRelativePrepend = null; // En aplicaciones web, contiene la ruta al root de la aplicación para ser agregado al inicio de las imagenes con path relativo + private static String defaultRelativePrependINI = null; + private static String webAppDir = null; + //private boolean containsSpecialMetrics = false; + //private Hashtable fontMetricsProps = new Hashtable(); + public static boolean DEBUG = false; + protected int currLine; + protected int lastLine = 0; + private static String predefinedSearchPath = ""; // Contiene los predefinedSearchPaths + protected float leftMargin; + protected float topMargin; + protected float bottomMargin; //If Margin Bottom is not specified 6 lines are assumed (nlines =6). + protected int templateFontSize; + protected boolean backFill = true; + protected Color templateColorFill; + protected int pages=0; + protected boolean templateCreated = false; + public static float DASHES_UNITS_ON = 10; + public static float DASHES_UNITS_OFF = 10; + public static float DOTS_UNITS_OFF = 3; + public static float DOTS_UNITS_ON = 1; + public boolean lineCapProjectingSquare = true; + public boolean barcode128AsImage = true; + public int justifiedType; + protected HttpContext httpContext = null; + float[] STYLE_SOLID = new float[]{1,0};//0 + float[] STYLE_NONE = null;//1 + float[] STYLE_DOTTED, //2 + STYLE_DASHED, //3 + STYLE_LONG_DASHED, //4 + STYLE_LONG_DOT_DASHED; //5 + int STYLE_NONE_CONST=1; + + protected enum VerticalAlign{ + TOP(0), + MIDDLE(1), + BOTTOM(2); + private int intValue; + VerticalAlign(int val) + { + this.intValue=val; + } + public int value(){ + return intValue; + } + } + protected static char alternateSeparator; + + static { + props = new ParseINI(); + alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; + DEBUG_STREAM = System.out; + } + + /** Setea el OutputStream a utilizar + * @param outputStream Stream a utilizar + */ + protected void setOutputStream(OutputStream outputStream) + { + this.outputStream = outputStream; + } + + /** Busca la ubicación del Acrobat. Si no la encuentra tira una excepción + */ + protected static String getAcrobatLocation() throws Exception + { + ParseINI props; + try + { + props = new ParseINI(Const.INI_FILE); + if(new File(Const.INI_FILE).length() == 0) + new File(Const.INI_FILE).delete(); + } + catch(IOException e) + { + props = new ParseINI(); + } + + // Primero debo obtener la ubicación + ejecutable del Acrobat + String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property + if(acrobatLocation == null) + { + if(NativeFunctions.isUnix()) + { // Si estoy en Unix no puedo ir a buscar el registry ;) + throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); + } + } + return acrobatLocation; + } + + /** Manda a imprimir el reporte a la impresora + * Si en las properties del PDFReport esta definida una GeneralProperty 'Acrobat Location' se + * utiliza esta property para obtener la ubicación + ejecutable del Acrobat, sino se busca en el Registry + * @param pdfFilename Nombre del reporte a imprimir (con extensión) + * @param silent Booleano que indica si se va a imprimir sin diálogo + * @exception Exception si no se puede realizar la operación + */ + public static void printReport(String pdfFilename, boolean silent) throws Exception + { + if(NativeFunctions.isWindows()) + { // En Windows obtenemos el full path + // En Linux esto no anda bien + pdfFilename = "\"" + new File(pdfFilename).getAbsolutePath() + "\""; + } + + String [] cmd = {}; + String acrobatLocation = null; + try + { + // Primero debo obtener la ubicación + ejecutable del Acrobat + acrobatLocation = getAcrobatLocation(); + }catch(Exception acrobatNotFound) + { + throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); + } + + //Se genera el PostScript + nativeCode.executeModal(acrobatLocation + " -toPostScript " + pdfFilename, false); + + //Se manda a imprimir a la impresora default + int pos = pdfFilename.lastIndexOf("."); + pdfFilename = pdfFilename.substring(0, pos) + ".ps"; + cmd = new String[] { "lp", pdfFilename}; + Runtime.getRuntime().exec(cmd); + } + + /** Muestra el reporte en pantalla + * @param filename nombre del PDF a mostrar + * @param modal indica si el PDF se va a mostrar en diálogo modal + * @exception Exception no se puede encontrar el Acrobat + */ + public static void showReport(String filename, boolean modal) throws Exception + { + if(NativeFunctions.isWindows()) + { // En Windows obtenemos el full path + // En Linux esto no anda bien + filename = "\"" + new File(filename).getAbsolutePath() + "\""; + } + String acrobatLocation; + try + { + // Primero debo obtener la ubicación + ejecutable del Acrobat + acrobatLocation = getAcrobatLocation(); + }catch(Exception acrobatNotFound) + { + throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); + } + + if(modal) + { + nativeCode.executeModal(acrobatLocation + " " + filename, true); + } + else + { + Runtime.getRuntime().exec(new String[] { acrobatLocation, filename}); + } + } + public GXReportPainter(ModelContext context) + { + //document = null; + //pageSize = null; + stringTotalPages = new Vector(); + httpContext = (HttpContext) context.getHttpContext(); + + if(defaultRelativePrepend == null) + { + defaultRelativePrepend = httpContext.getDefaultPath(); + if(defaultRelativePrepend == null || defaultRelativePrepend.trim().equals("")) + defaultRelativePrepend = ""; + else + defaultRelativePrepend = defaultRelativePrepend.replace(alternateSeparator, File.separatorChar) + File.separatorChar; + defaultRelativePrependINI = defaultRelativePrepend; + if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) + { + configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; // Esto es para que en aplicaciones web el PDFReport.INI no quede visible en el server + configurationTemplateFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_TEMPLATE_FILE; + } + else + { + configurationFile = defaultRelativePrepend + Const.INI_FILE; + configurationTemplateFile = defaultRelativePrepend + Const.INI_TEMPLATE_FILE; + } + webAppDir = defaultRelativePrepend; + + if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) + { + // @cambio: 23/07/03 + // Para los reportes en el web, debemos tener en cuenta la preference 'Static Content Base URL' del modelo + // Pero SOLO la tenemos en cuenta si es un directorio relativo + // O sea, si la preference dice algo tipo /pepe, entonces vamos a buscar las + // imagenes relativas a %WebApp%/pepe, pero si la preference dice algo tipo + // 'http://otroServer/xxxyyy' entonces ahi no le damos bola a la preference! + // Además, para mantener compatibilidad con las aplicaciones hasta ahora, si la imagen + // no se encuentra all\uFFFDElo que hacemos es ir a buscarla a %WebApp% + + // @cambio: 12/09/17 + // Esto tambien se tiene que hacer para los reportes web que se llaman con submit + // (ese es el caso en el cual el getDefaultPath no es Empty) + + String staticContentBase = httpContext.getStaticContentBase(); + if(staticContentBase != null) + { + staticContentBase = staticContentBase.trim(); + if(staticContentBase.indexOf(':') == -1) + { // Si la staticContentBase es una ruta relativa + staticContentBase = staticContentBase.replace(alternateSeparator, File.separatorChar); + if(staticContentBase.startsWith(File.separator)) + { + staticContentBase = staticContentBase.substring(1); + } + if(!staticContentBase.equals("")) + { + defaultRelativePrepend += staticContentBase; + if(!defaultRelativePrepend.endsWith(File.separator)) + { + defaultRelativePrepend += File.separator; + } + } + } + } + } + } + if (firstTime) + { + loadProps(); + firstTime = false; + } + } + + private static boolean firstTime = true; + + protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) + { + if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) + { + iniFile = defaultRelativePrependINI + Const.WEB_INF + File.separatorChar + iniFile; + } + else + { + iniFile = defaultRelativePrependINI + iniFile; + } + + try + { + this.form = form; + printerSettings = new ParseINI(iniFile); + } + catch(IOException e){ printerSettings = new ParseINI(); } + + mode = (mode==2)?3:0; + + printerSettings.setupProperty(form, Const.PRINTER, printer); + printerSettings.setupProperty(form, Const.MODE, mode + ""); + printerSettings.setupProperty(form, Const.ORIENTATION, orientation+ ""); + printerSettings.setupProperty(form, Const.PAPERSIZE, pageSize+ ""); + printerSettings.setupProperty(form, Const.PAPERLENGTH, pageLength+ ""); + printerSettings.setupProperty(form, Const.PAPERWIDTH, pageWidth+ ""); + printerSettings.setupProperty(form, Const.SCALE, scale+ ""); + printerSettings.setupProperty(form, Const.COPIES, copies+ ""); + printerSettings.setupProperty(form, Const.DEFAULTSOURCE, defSrc+ ""); + printerSettings.setupProperty(form, Const.PRINTQUALITY, quality+ ""); + printerSettings.setupProperty(form, Const.COLOR, color+ ""); + printerSettings.setupProperty(form, Const.DUPLEX, duplex+ ""); + } + + protected void loadProps() + { + try{ + props = new ParseINI(configurationFile, configurationTemplateFile); + }catch(IOException e){ props = new ParseINI(); } + + props.setupGeneralProperty(Const.PDF_REPORT_INI_VERSION_ENTRY, Const.PDF_REPORT_INI_VERSION); + props.setupGeneralProperty(Const.EMBEED_SECTION, Const.EMBEED_DEFAULT); + props.setupGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, Const.EMBEED_DEFAULT); + props.setupGeneralProperty(Const.SEARCH_FONTS_ALWAYS, "false"); + props.setupGeneralProperty(Const.SEARCH_FONTS_ONCE, "true"); + props.setupGeneralProperty(Const.SERVER_PRINTING, "false"); + props.setupGeneralProperty(Const.ADJUST_TO_PAPER, "true"); + props.setupGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE, Const.DEFAULT_LINE_CAP_PROJECTING_SQUARE); + props.setupGeneralProperty(Const.BARCODE128_AS_IMAGE, Const.DEFAULT_BARCODE128_AS_IMAGE); + props.setupGeneralProperty("DEBUG", "false"); + props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); + props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); + props.setupGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER); + props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); + props.setupGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "."); + props.setupGeneralProperty(Const.LEADING, "2"); + props.setupGeneralProperty(Const.RUN_DIRECTION, Const.RUN_DIRECTION_LTR); + props.setupGeneralProperty(Const.JUSTIFIED_TYPE_ALL, "false"); + + props.setupGeneralProperty(Const.STYLE_DOTTED, Const.DEFAULT_STYLE_DOTTED); + props.setupGeneralProperty(Const.STYLE_DASHED, Const.DEFAULT_STYLE_DASHED); + props.setupGeneralProperty(Const.STYLE_LONG_DASHED, Const.DEFAULT_STYLE_LONG_DASHED); + props.setupGeneralProperty(Const.STYLE_LONG_DOT_DASHED, Const.DEFAULT_STYLE_LONG_DOT_DASHED); + + loadSubstituteTable(); // Cargo la tabla de substitutos de fonts + + if(props.getBooleanGeneralProperty("DEBUG", false)) + { + DEBUG = true; + DEBUG_STREAM = System.out; + } + else + { + DEBUG = false; + DEBUG_STREAM = new PrintStream(new com.genexus.util.NullOutputStream()); + } + + Utilities.addPredefinedSearchPaths(new String[]{System.getProperty("java.awt.fonts", "c:\\windows\\fonts"), + System.getProperty("com.ms.windir", "c:\\windows") + "\\fonts"}); + } + + public static final void addPredefinedSearchPaths(String [] predefinedPaths) + { + String predefinedPath = ""; + for(int i = 0; i < predefinedPaths.length; i++) + predefinedPath += predefinedPaths[i] + ";"; + predefinedSearchPath = predefinedPath + predefinedSearchPath; // SearchPath= los viejos más los nuevos + } + + public static final String getPredefinedSearchPaths() + { + return predefinedSearchPath; + } + + protected abstract void init(); + + + public void GxRVSetLanguage(String lang) {} + + public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) {} + + protected float[] parsePattern(String patternStr) + { + if (patternStr!=null) + { + StringTokenizer st = new StringTokenizer(patternStr.trim(), ";"); + int length = st.countTokens(); + if (length>0) + { + int i = 0; + float[] pattern = new float[length]; + while(st.hasMoreTokens()) + { + pattern[i] = Float.parseFloat(st.nextToken()); + i++; + } + return pattern; + } + } + return null; + } + + protected float [] getDashedPattern(int style) + { + switch(style) + { + case 0: return STYLE_SOLID; + case 1: return STYLE_NONE; + case 2: return STYLE_DOTTED; + case 3: return STYLE_DASHED; + case 4: return STYLE_LONG_DASHED; + case 5: return STYLE_LONG_DOT_DASHED; + default: + return STYLE_SOLID; + } + } + + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) + { + GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, 0, 0); + } + + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int style, int cornerRadius) + { + GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, style, style, style, style, cornerRadius, cornerRadius, cornerRadius, cornerRadius); + } + public abstract void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR); + + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) + { + GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); + } + + public abstract void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style); + + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom) + { + GxDrawBitMap(bitmap, left, top, right, bottom, 0); + } + + public abstract void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio); + + public String getSubstitute(String fontName) + { + Vector fontSubstitutesProcessed = new Vector<>(); + String newFontName = fontName; + while( fontSubstitutes.containsKey(newFontName)) + { + if (!fontSubstitutesProcessed.contains(newFontName)) + { + fontSubstitutesProcessed.addElement(newFontName); + newFontName = fontSubstitutes.get(newFontName); + } + else + { + return fontSubstitutes.get(newFontName); + } + } + return newFontName; + } + + public abstract void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue); + + protected String getFontLocation(String fontName) + { + String fontPath = props.getProperty(Const.MS_FONT_LOCATION, fontName, ""); + if (fontPath.equals("")) + { + fontPath = props.getProperty(Const.SUN_FONT_LOCATION, fontName, ""); + } + return fontPath; + } + @SuppressWarnings("unchecked") + protected Hashtable getFontLocations() + { + Hashtable msLocations = props.getSection(Const.MS_FONT_LOCATION); + Hashtable sunLocations = props.getSection(Const.SUN_FONT_LOCATION); + Hashtable locations = new Hashtable(); + if (msLocations != null) + { + for (Enumeration e = msLocations.keys(); e.hasMoreElements() ;) + { + Object key = e.nextElement(); + locations.put(key, msLocations.get(key)); + } + } + if (sunLocations != null) + { + for (Enumeration e = sunLocations.keys(); e.hasMoreElements() ;) + { + Object key = e.nextElement(); + locations.put(key, sunLocations.get(key)); + } + } + return locations; + } + + protected boolean isEmbeddedFont(String realFontName) { + boolean generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); + boolean generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); + return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, realFontName, generalEmbeedNotSpecified); + } + + public abstract void setAsianFont(String fontName, String style); + + /** + * @deprecated + */ + public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align) + { + GxDrawText(sTxt, left, top, right, bottom, align, 0); + } + public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat) + { + GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, 0); + } + public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border) + { + GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, border, 0); + } + public abstract void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign); + boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ + return bottomAux > drawingPageHeight; + } + + public void GxClearAttris() {} + + public static final double PAGE_SCALE_Y = 20; // Indica la escala de la página + public static final double PAGE_SCALE_X = 20; // Indica la escala de la página + public static final double GX_PAGE_SCALE_Y_OLD = 15.45; + public static final double GX_PAGE_SCALE_Y = 14.4; // Indica la escala de la página, GeneXus lleva otra escala para el tamaño de la hoja, (variando este parametro, se agranda o achica el tamaño imprimible por GeneXus) + //Por ejemplo: si en genexus se tiene un reporte con Paper Height de 1169 (A4) centésimos de pulgada (1/100 inch), + //en el parámetro pageLength llega 16834 que esta en Twips (16834 = 1169*14.4). 1 twip = 1/1440 inch. + //Con el valor anterior 15.45 estaba quedando un margen bottom fijo que no se podia eliminar (incluso seteando mb 0). + private static double TO_CM_SCALE =28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) + public abstract boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex); + + public int getPageLines() + { + if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); + return pageLines; + } + public int getLineHeight() + { + if(DEBUG)DEBUG_STREAM.println("getLineHeight: --> " + this.lineHeight); + return this.lineHeight; + } + public void setPageLines(int P_lines) + { + if(DEBUG)DEBUG_STREAM.println("setPageLines: " + P_lines); + pageLines = P_lines; + } + public void setLineHeight(int lineHeight) + { + + if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); + this.lineHeight = lineHeight; + } + + int M_top ; + int M_bot ; + + public int getM_top() + { + return M_top; + } + + public int getM_bot() + { + return M_bot; + } + + public void setM_top(int M_top) + { + this.M_top = M_top; + } + + public void setM_bot(int M_bot) + { + this.M_bot = M_bot; + } + + public abstract void GxEndPage(); + + public abstract void GxEndDocument(); + + public void GxEndPrinter() {} + public abstract void GxStartPage(); + + public void GxStartDoc() + { + //DEBUG.println("Processing..."); + } + public void GxSetDocFormat(String format) + { + //DEBUG.println("Processing..."); + } + + public void GxSetDocName(String docName) + { + this.docName = docName.trim(); + if(this.docName.indexOf('.') < 0) + this.docName += ".pdf"; + if(!new File(docName).isAbsolute()) + { // Si el nombre del documento es relativo, veo si hay que agregarle el outputDir + String outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").replace(alternateSeparator, File.separatorChar).trim(); + if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) + { + if(!outputDir.endsWith(File.separator)) + { + outputDir += File.separator; + } + new File(outputDir).mkdirs(); + this.docName = outputDir + this.docName; + } + else + { + if (ModelContext.getModelContext() != null) + { + HttpContext webContext = (HttpContext) ModelContext.getModelContext().getHttpContext(); + if ((webContext != null) && (webContext instanceof HttpContextWeb)) + { + outputDir = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + File.separator; + this.docName = outputDir + this.docName; + } + } + } + } + if(this.docName.indexOf('.') < 0) + this.docName += ".pdf"; + if(DEBUG)DEBUG_STREAM.println("GxSetDocName: '" + this.docName + "'"); + } + + public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) + { + //DEBUG.println("Processing..."); + return true; + } + + public boolean GxPrnCfg( String ini ) + { + //DEBUG.println("Processing..."); + return true; + } + + public boolean GxIsAlive() + { + return false; + } + + public boolean GxIsAliveDoc() + { + return true; + } + + + protected int page; + public int getPage() + { + return page; + } + + public void setPage(int page) + { + this.page = page; + } + + public boolean getModal() + { + return modal; + } + public void setModal(boolean modal) + { + this.modal = modal; + } + + public void cleanup() {} + + public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) + { + } + + + /** Carga la tabla de substitutos + */ + protected void loadSubstituteTable() + { + // Primero leemos la tabla de substitutos del Registry + Hashtable> tempInverseMappings = new Hashtable<>(); + + // Seteo algunos Mappings que Acrobat toma como Type1 + for(int i = 0; i < Const.FONT_SUBSTITUTES_TTF_TYPE1.length; i++) + fontSubstitutes.put(Const.FONT_SUBSTITUTES_TTF_TYPE1[i][0], Const.FONT_SUBSTITUTES_TTF_TYPE1[i][1]); + + // Ahora inserto los mappings extra del PDFReport.INI (si es que hay) + // Los font substitutes del PDFReport.INI se encuentran bajo la seccion + // indicada por Const.FONT_SUBSTITUTES_SECTION y son pares oldFont -> newFont + Hashtable otherMappings = props.getSection(Const.FONT_SUBSTITUTES_SECTION); + if(otherMappings != null) + for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) + { + String fontName = (String)enumera.nextElement(); + fontSubstitutes.put(fontName, (String)otherMappings.get(fontName)); + if(tempInverseMappings.containsKey(fontName)) // Con esto solucionamos el tema de la recursión de Fonts -> Fonts + { // x ej: Si tenú} Font1-> Font2, y ahora tengo Font2->Font3, pongo cambio el 1º por Font1->Font3 + String fontSubstitute = (String)otherMappings.get(fontName); + for(Enumeration enum2 = tempInverseMappings.get(fontName).elements(); enum2.hasMoreElements();) + fontSubstitutes.put(enum2.nextElement(), fontSubstitute); + } + } + } + + + /** Estos métodos no hacen nada en este contexto + */ + public void GxPrintMax() { ; } + public void GxPrintNormal() { ; } + public void GxPrintOnTop() { ; } + public void GxPrnCmd(String cmd) { ; } + + + public void showInformation() + { + } + + public static final double SCALE_FACTOR = 72; + protected double PPP = 96; + protected double convertScale(int value) + { + double result = value * SCALE_FACTOR / PPP; + return result; + } + + protected double convertScale(double value) + { + double result = value * SCALE_FACTOR / PPP; + return result; + } + + protected float reconvertScale(float value) + { + float result = value / (float)(SCALE_FACTOR / PPP); + return result; + } + + class FontProps + { + public int horizontal; + public int vertical; + } + + /** + * Helper method for toString() + * @param s source string + * @param f string to remove + * @param t string to replace f + * @return string with f replaced by t + */ + protected static String replace(String s,String f,String t) { + StringBuffer b = new StringBuffer(); + int p = 0, c=0; + + while(c>-1) { + if((c = s.indexOf(f,p)) > -1) { + b.append(s.substring(p,c)); + b.append(t); + p=c+1; + } + } + + // include any remaining text + if(p fontSubstitutes = new Hashtable<>(); // Contiene la tabla de substitutos de fonts (String <--> String) private static String configurationFile = null; @@ -129,87 +110,28 @@ public class PDFReportItext implements IReportHandler private Document document; private PdfWriter writer; private Paragraph chunk; - private int currLine; - private int lastLine = 0; private static String predefinedSearchPath = ""; // Contiene los predefinedSearchPaths - private float leftMargin; - private float topMargin; - private float bottomMargin; //If Margin Bottom is not specified 6 lines are assumed (nlines =6). private PdfTemplate template; private BaseFont templateFont; - private int templateFontSize; - private boolean backFill = true; - private Color templateColorFill; - private int pages=0; - private boolean templateCreated = false; - public static float DASHES_UNITS_ON = 10; - public static float DASHES_UNITS_OFF = 10; - public static float DOTS_UNITS_OFF = 3; - public static float DOTS_UNITS_ON = 1; public boolean lineCapProjectingSquare = true; public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; public int runDirection = PdfWriter.RUN_DIRECTION_LTR; public int justifiedType; - - private HttpContext httpContext = null; - float[] STYLE_SOLID = new float[]{1,0};//0 - float[] STYLE_NONE = null;//1 - float[] STYLE_DOTTED, //2 - STYLE_DASHED, //3 - STYLE_LONG_DASHED, //4 - STYLE_LONG_DOT_DASHED; //5 - int STYLE_NONE_CONST=1; - - private enum VerticalAlign{ - TOP(0), - MIDDLE(1), - BOTTOM(2); - private int intValue; - VerticalAlign(int val) - { - this.intValue=val; - } - public int value(){ - return intValue; - } - } - /** Setea el OutputStream a utilizar * @param outputStream Stream a utilizar */ public void setOutputStream(OutputStream outputStream) { - this.outputStream = outputStream; + super.setOutputStream(outputStream); } /** Busca la ubicación del Acrobat. Si no la encuentra tira una excepción */ - private static String getAcrobatLocation() throws Exception + protected static String getAcrobatLocation() throws Exception { - ParseINI props; - try - { - props = new ParseINI(Const.INI_FILE); - if(new File(Const.INI_FILE).length() == 0) - new File(Const.INI_FILE).delete(); - } - catch(IOException e) - { - props = new ParseINI(); - } - - // Primero debo obtener la ubicación + ejecutable del Acrobat - String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property - if(acrobatLocation == null) - { - if(NativeFunctions.isUnix()) - { // Si estoy en Unix no puedo ir a buscar el registry ;) - throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); - } - } - return acrobatLocation; + return GXReportPainter.getAcrobatLocation(); } /** Manda a imprimir el reporte a la impresora @@ -221,31 +143,7 @@ private static String getAcrobatLocation() throws Exception */ public static void printReport(String pdfFilename, boolean silent) throws Exception { - if(NativeFunctions.isWindows()) - { // En Windows obtenemos el full path - // En Linux esto no anda bien - pdfFilename = "\"" + new File(pdfFilename).getAbsolutePath() + "\""; - } - - String [] cmd = {}; - String acrobatLocation = null; - try - { - // Primero debo obtener la ubicación + ejecutable del Acrobat - acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) - { - throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); - } - - //Se genera el PostScript - nativeCode.executeModal(acrobatLocation + " -toPostScript " + pdfFilename, false); - - //Se manda a imprimir a la impresora default - int pos = pdfFilename.lastIndexOf("."); - pdfFilename = pdfFilename.substring(0, pos) + ".ps"; - cmd = new String[] { "lp", pdfFilename}; - Runtime.getRuntime().exec(cmd); + GXReportPainter.printReport(pdfFilename,silent); } /** Muestra el reporte en pantalla @@ -255,202 +153,30 @@ public static void printReport(String pdfFilename, boolean silent) throws Except */ public static void showReport(String filename, boolean modal) throws Exception { - if(NativeFunctions.isWindows()) - { // En Windows obtenemos el full path - // En Linux esto no anda bien - filename = "\"" + new File(filename).getAbsolutePath() + "\""; - } - String acrobatLocation; - try - { - // Primero debo obtener la ubicación + ejecutable del Acrobat - acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) - { - throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); - } - - if(modal) - { - nativeCode.executeModal(acrobatLocation + " " + filename, true); - } - else - { - Runtime.getRuntime().exec(new String[] { acrobatLocation, filename}); - } + GXReportPainter.showReport(filename,modal); } - private static char alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; public PDFReportItext(ModelContext context) { + super(context); document = null; pageSize = null; - stringTotalPages = new Vector(); - documentImages = new ConcurrentHashMap(); - httpContext = (HttpContext) context.getHttpContext(); - - if(defaultRelativePrepend == null) - { - defaultRelativePrepend = httpContext.getDefaultPath(); - if(defaultRelativePrepend == null || defaultRelativePrepend.trim().equals("")) - defaultRelativePrepend = ""; - else - defaultRelativePrepend = defaultRelativePrepend.replace(alternateSeparator, File.separatorChar) + File.separatorChar; - defaultRelativePrependINI = defaultRelativePrepend; - if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) - { - configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; // Esto es para que en aplicaciones web el PDFReport.INI no quede visible en el server - configurationTemplateFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_TEMPLATE_FILE; - } - else - { - configurationFile = defaultRelativePrepend + Const.INI_FILE; - configurationTemplateFile = defaultRelativePrepend + Const.INI_TEMPLATE_FILE; - } - webAppDir = defaultRelativePrepend; - - if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) - { - // @cambio: 23/07/03 - // Para los reportes en el web, debemos tener en cuenta la preference 'Static Content Base URL' del modelo - // Pero SOLO la tenemos en cuenta si es un directorio relativo - // O sea, si la preference dice algo tipo /pepe, entonces vamos a buscar las - // imagenes relativas a %WebApp%/pepe, pero si la preference dice algo tipo - // 'http://otroServer/xxxyyy' entonces ahi no le damos bola a la preference! - // Además, para mantener compatibilidad con las aplicaciones hasta ahora, si la imagen - // no se encuentra all\uFFFDElo que hacemos es ir a buscarla a %WebApp% - - // @cambio: 12/09/17 - // Esto tambien se tiene que hacer para los reportes web que se llaman con submit - // (ese es el caso en el cual el getDefaultPath no es Empty) - - String staticContentBase = httpContext.getStaticContentBase(); - if(staticContentBase != null) - { - staticContentBase = staticContentBase.trim(); - if(staticContentBase.indexOf(':') == -1) - { // Si la staticContentBase es una ruta relativa - staticContentBase = staticContentBase.replace(alternateSeparator, File.separatorChar); - if(staticContentBase.startsWith(File.separator)) - { - staticContentBase = staticContentBase.substring(1); - } - if(!staticContentBase.equals("")) - { - defaultRelativePrepend += staticContentBase; - if(!defaultRelativePrepend.endsWith(File.separator)) - { - defaultRelativePrepend += File.separator; - } - } - } - } - } - } - if (firstTime) - { - loadProps(); - firstTime = false; - } + documentImages = new ConcurrentHashMap<>(); } private static boolean firstTime = true; - private void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) + protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) - { - iniFile = defaultRelativePrependINI + Const.WEB_INF + File.separatorChar + iniFile; - } - else - { - iniFile = defaultRelativePrependINI + iniFile; - } - - try - { - this.form = form; - printerSettings = new ParseINI(iniFile); - } - catch(IOException e){ printerSettings = new ParseINI(); } - - mode = (mode==2)?3:0; - - printerSettings.setupProperty(form, Const.PRINTER, printer); - printerSettings.setupProperty(form, Const.MODE, mode + ""); - printerSettings.setupProperty(form, Const.ORIENTATION, orientation+ ""); - printerSettings.setupProperty(form, Const.PAPERSIZE, pageSize+ ""); - printerSettings.setupProperty(form, Const.PAPERLENGTH, pageLength+ ""); - printerSettings.setupProperty(form, Const.PAPERWIDTH, pageWidth+ ""); - printerSettings.setupProperty(form, Const.SCALE, scale+ ""); - printerSettings.setupProperty(form, Const.COPIES, copies+ ""); - printerSettings.setupProperty(form, Const.DEFAULTSOURCE, defSrc+ ""); - printerSettings.setupProperty(form, Const.PRINTQUALITY, quality+ ""); - printerSettings.setupProperty(form, Const.COLOR, color+ ""); - printerSettings.setupProperty(form, Const.DUPLEX, duplex+ ""); + super.loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); } - private void loadProps() + protected void loadProps() { - try{ - props = new ParseINI(configurationFile, configurationTemplateFile); - }catch(IOException e){ props = new ParseINI(); } - - props.setupGeneralProperty(Const.PDF_REPORT_INI_VERSION_ENTRY, Const.PDF_REPORT_INI_VERSION); - props.setupGeneralProperty(Const.EMBEED_SECTION, Const.EMBEED_DEFAULT); - props.setupGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, Const.EMBEED_DEFAULT); - props.setupGeneralProperty(Const.SEARCH_FONTS_ALWAYS, "false"); - props.setupGeneralProperty(Const.SEARCH_FONTS_ONCE, "true"); - props.setupGeneralProperty(Const.SERVER_PRINTING, "false"); - props.setupGeneralProperty(Const.ADJUST_TO_PAPER, "true"); - props.setupGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE, Const.DEFAULT_LINE_CAP_PROJECTING_SQUARE); - props.setupGeneralProperty(Const.BARCODE128_AS_IMAGE, Const.DEFAULT_BARCODE128_AS_IMAGE); - props.setupGeneralProperty("DEBUG", "false"); - props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); - props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); - props.setupGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER); - props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); - props.setupGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "."); - props.setupGeneralProperty(Const.LEADING, "2"); - props.setupGeneralProperty(Const.RUN_DIRECTION, Const.RUN_DIRECTION_LTR); - props.setupGeneralProperty(Const.JUSTIFIED_TYPE_ALL, "false"); - - props.setupGeneralProperty(Const.STYLE_DOTTED, Const.DEFAULT_STYLE_DOTTED); - props.setupGeneralProperty(Const.STYLE_DASHED, Const.DEFAULT_STYLE_DASHED); - props.setupGeneralProperty(Const.STYLE_LONG_DASHED, Const.DEFAULT_STYLE_LONG_DASHED); - props.setupGeneralProperty(Const.STYLE_LONG_DOT_DASHED, Const.DEFAULT_STYLE_LONG_DOT_DASHED); - - loadSubstituteTable(); // Cargo la tabla de substitutos de fonts - - if(props.getBooleanGeneralProperty("DEBUG", false)) - { - DEBUG = true; - DEBUG_STREAM = System.out; - } - else - { - DEBUG = false; - DEBUG_STREAM = new PrintStream(new com.genexus.util.NullOutputStream()); - } - - Utilities.addPredefinedSearchPaths(new String[]{System.getProperty("java.awt.fonts", "c:\\windows\\fonts"), - System.getProperty("com.ms.windir", "c:\\windows") + "\\fonts"}); + super.loadProps(); } - public static final void addPredefinedSearchPaths(String [] predefinedPaths) - { - String predefinedPath = ""; - for(int i = 0; i < predefinedPaths.length; i++) - predefinedPath += predefinedPaths[i] + ";"; - predefinedSearchPath = predefinedPath + predefinedSearchPath; // SearchPath= los viejos más los nuevos - } - - public static final String getPredefinedSearchPaths() - { - return predefinedSearchPath; - } - - private void init() + protected void init() { Document.compress = true; try { @@ -471,40 +197,14 @@ public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) { } - private float[] parsePattern(String patternStr) + protected float[] parsePattern(String patternStr) { - if (patternStr!=null) - { - StringTokenizer st = new StringTokenizer(patternStr.trim(), ";"); - int length = st.countTokens(); - if (length>0) - { - int i = 0; - float[] pattern = new float[length]; - while(st.hasMoreTokens()) - { - pattern[i] = Float.parseFloat(st.nextToken()); - i++; - } - return pattern; - } - } - return null; + return super.parsePattern(patternStr); } - private float [] getDashedPattern(int style) + protected float [] getDashedPattern(int style) { - switch(style) - { - case 0: return STYLE_SOLID; - case 1: return STYLE_NONE; - case 2: return STYLE_DOTTED; - case 3: return STYLE_DASHED; - case 4: return STYLE_LONG_DASHED; - case 5: return STYLE_LONG_DOT_DASHED; - default: - return STYLE_SOLID; - } + return super.getDashedPattern(style); } /** @@ -812,7 +512,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) { - GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); + GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); } public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) @@ -955,21 +655,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom public String getSubstitute(String fontName) { - Vector fontSubstitutesProcessed = new Vector<>(); - String newFontName = fontName; - while( fontSubstitutes.containsKey(newFontName)) - { - if (!fontSubstitutesProcessed.contains(newFontName)) - { - fontSubstitutesProcessed.addElement(newFontName); - newFontName = fontSubstitutes.get(newFontName); - } - else - { - return fontSubstitutes.get(newFontName); - } - } - return newFontName; + return super.getSubstitute(fontName); } public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) @@ -1105,44 +791,18 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } } - private String getFontLocation(String fontName) + protected String getFontLocation(String fontName) { - String fontPath = props.getProperty(Const.MS_FONT_LOCATION, fontName, ""); - if (fontPath.equals("")) - { - fontPath = props.getProperty(Const.SUN_FONT_LOCATION, fontName, ""); - } - return fontPath; + return super.getFontLocation(fontName); } @SuppressWarnings("unchecked") - private Hashtable getFontLocations() + protected Hashtable getFontLocations() { - Hashtable msLocations = props.getSection(Const.MS_FONT_LOCATION); - Hashtable sunLocations = props.getSection(Const.SUN_FONT_LOCATION); - Hashtable locations = new Hashtable(); - if (msLocations != null) - { - for (Enumeration e = msLocations.keys(); e.hasMoreElements() ;) - { - Object key = e.nextElement(); - locations.put(key, msLocations.get(key)); - } - } - if (sunLocations != null) - { - for (Enumeration e = sunLocations.keys(); e.hasMoreElements() ;) - { - Object key = e.nextElement(); - locations.put(key, sunLocations.get(key)); - } - } - return locations; + return super.getFontLocations(); } - private boolean isEmbeddedFont(String realFontName) { - boolean generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); - boolean generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); - return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, realFontName, generalEmbeedNotSpecified); + protected boolean isEmbeddedFont(String realFontName) { + return super.isEmbeddedFont(realFontName); } public void setAsianFont(String fontName, String style) @@ -1567,8 +1227,8 @@ else if (valign == VerticalAlign.BOTTOM.value()) } } } - boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ - return bottomAux > drawingPageHeight; + boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ + return super.pageHeightExceeded(bottomAux,drawingPageHeight); } ColumnText SimulateDrawColumnText(PdfContentByte cb, Rectangle rect, Paragraph p, float leading, int runDirection, int alignment) throws DocumentException { @@ -1617,9 +1277,7 @@ private int columnAlignment(int alignment) else return alignment; } - public void GxClearAttris() - { - } + public void GxClearAttris() {} public static final double PAGE_SCALE_Y = 20; // Indica la escala de la página public static final double PAGE_SCALE_X = 20; // Indica la escala de la página @@ -1756,47 +1414,42 @@ else if (length == 15840 && width == 12240) public int getPageLines() { - if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); - return pageLines; - } - public int getLineHeight() - { - if(DEBUG)DEBUG_STREAM.println("getLineHeight: --> " + this.lineHeight); - return this.lineHeight; - } - public void setPageLines(int P_lines) - { - if(DEBUG)DEBUG_STREAM.println("setPageLines: " + P_lines); - pageLines = P_lines; - } - public void setLineHeight(int lineHeight) - { - - if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); - this.lineHeight = lineHeight; + return super.getPageLines(); } + public int getLineHeight() + { + return super.getLineHeight(); + } + public void setPageLines(int P_lines) + { + super.setPageLines(P_lines); + } + public void setLineHeight(int lineHeight) + { + super.setLineHeight(lineHeight); + } int M_top ; int M_bot ; public int getM_top() { - return M_top; + return super.getM_top(); } public int getM_bot() { - return M_bot; + return super.getM_bot(); } public void setM_top(int M_top) { - this.M_top = M_top; + super.setM_top(M_top); } public void setM_bot(int M_bot) { - this.M_bot = M_bot; + super.setM_bot(M_bot); } public void GxEndPage() @@ -1970,80 +1623,46 @@ public void GxSetDocFormat(String format) public void GxSetDocName(String docName) { - this.docName = docName.trim(); - if(this.docName.indexOf('.') < 0) - this.docName += ".pdf"; - if(!new File(docName).isAbsolute()) - { // Si el nombre del documento es relativo, veo si hay que agregarle el outputDir - String outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").replace(alternateSeparator, File.separatorChar).trim(); - if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) - { - if(!outputDir.endsWith(File.separator)) - { - outputDir += File.separator; - } - new File(outputDir).mkdirs(); - this.docName = outputDir + this.docName; - } - else - { - if (ModelContext.getModelContext() != null) - { - HttpContext webContext = (HttpContext) ModelContext.getModelContext().getHttpContext(); - if ((webContext != null) && (webContext instanceof HttpContextWeb)) - { - outputDir = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + File.separator; - this.docName = outputDir + this.docName; - } - } - } - } - if(this.docName.indexOf('.') < 0) - this.docName += ".pdf"; - if(DEBUG)DEBUG_STREAM.println("GxSetDocName: '" + this.docName + "'"); + super.GxSetDocName(docName); } public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { - //DEBUG.println("Processing..."); - return true; + return super.GxPrTextInit(ouput, nxPage, nyPage, psIniFile, psForm, sPrinter, nMode, nPaperLength, nPaperWidth, nGridX, nGridY, nPageLines); } public boolean GxPrnCfg( String ini ) { - //DEBUG.println("Processing..."); - return true; + return super.GxPrnCfg(ini); } public boolean GxIsAlive() { - return false; + return super.GxIsAlive(); } public boolean GxIsAliveDoc() { - return true; + return super.GxIsAliveDoc(); } - - private int page; public int getPage() { - return page; + return super.getPage(); } public void setPage(int page) { - this.page = page; + super.setPage(page); } public boolean getModal() { - return modal; + return super.getModal(); } public void setModal(boolean modal) { - this.modal = modal; + super.setModal(modal); } public void cleanup() {} @@ -2055,31 +1674,9 @@ public void setMetrics(String fontName, boolean bold, boolean italic, int ascent /** Carga la tabla de substitutos */ - private void loadSubstituteTable() + protected void loadSubstituteTable() { - // Primero leemos la tabla de substitutos del Registry - Hashtable> tempInverseMappings = new Hashtable<>(); - - // Seteo algunos Mappings que Acrobat toma como Type1 - for(int i = 0; i < Const.FONT_SUBSTITUTES_TTF_TYPE1.length; i++) - fontSubstitutes.put(Const.FONT_SUBSTITUTES_TTF_TYPE1[i][0], Const.FONT_SUBSTITUTES_TTF_TYPE1[i][1]); - - // Ahora inserto los mappings extra del PDFReport.INI (si es que hay) - // Los font substitutes del PDFReport.INI se encuentran bajo la seccion - // indicada por Const.FONT_SUBSTITUTES_SECTION y son pares oldFont -> newFont - Hashtable otherMappings = props.getSection(Const.FONT_SUBSTITUTES_SECTION); - if(otherMappings != null) - for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) - { - String fontName = (String)enumera.nextElement(); - fontSubstitutes.put(fontName, (String)otherMappings.get(fontName)); - if(tempInverseMappings.containsKey(fontName)) // Con esto solucionamos el tema de la recursión de Fonts -> Fonts - { // x ej: Si tenú} Font1-> Font2, y ahora tengo Font2->Font3, pongo cambio el 1º por Font1->Font3 - String fontSubstitute = (String)otherMappings.get(fontName); - for(Enumeration enum2 = tempInverseMappings.get(fontName).elements(); enum2.hasMoreElements();) - fontSubstitutes.put(enum2.nextElement(), fontSubstitute); - } - } + super.loadSubstituteTable(); } @@ -2096,23 +1693,20 @@ public void showInformation() } public static final double SCALE_FACTOR = 72; - private double PPP = 96; - private double convertScale(int value) + + protected double convertScale(int value) { - double result = value * SCALE_FACTOR / PPP; - return result; + return super.convertScale(value); } - private double convertScale(double value) + protected double convertScale(double value) { - double result = value * SCALE_FACTOR / PPP; - return result; + return super.convertScale(value); } - private float reconvertScale(float value) + protected float reconvertScale(float value) { - float result = value / (float)(SCALE_FACTOR / PPP); - return result; + return super.reconvertScale(value); } class FontProps @@ -2128,25 +1722,10 @@ class FontProps * @param t string to replace f * @return string with f replaced by t */ - private static String replace(String s,String f,String t) { - StringBuffer b = new StringBuffer(); - int p = 0, c=0; - - while(c>-1) { - if((c = s.indexOf(f,p)) > -1) { - b.append(s.substring(p,c)); - b.append(t); - p=c+1; - } + protected static String replace(String s,String f,String t) { + return GXReportPainter.replace(s,f,t); } - // include any remaining text - if(p fontSubstitutes = new Hashtable<>(); private static String configurationFile = null; @@ -62,94 +45,27 @@ public class PDFReportpdfbox implements IReportHandler{ private PDDocument document; private PDDocumentCatalog writer; private static String predefinedSearchPath = ""; - private float leftMargin; - private float topMargin; - private float bottomMargin; private PDPageContentStream template; private PDFormXObject formXObjecttemplate; private PDType0Font templateFont; - private int templateFontSize; - private boolean backFill = true; - private Color templateColorFill; - private int pages=0; - private boolean templateCreated = false; public boolean lineCapProjectingSquare = true; public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; public int runDirection = 0; - private HttpContext httpContext = null; - float[] STYLE_SOLID = new float[]{1,0};//0 - float[] STYLE_NONE = null; - float[] STYLE_DOTTED, - STYLE_DASHED, - STYLE_LONG_DASHED, - STYLE_LONG_DOT_DASHED; - int STYLE_NONE_CONST=1; - - private enum VerticalAlign{ - TOP(0), - MIDDLE(1), - BOTTOM(2); - private int intValue; - VerticalAlign(int val) - { - this.intValue=val; - } - public int value(){ - return intValue; - } - } public void setOutputStream(OutputStream outputStream) { - this.outputStream = outputStream; + super.setOutputStream(outputStream); } - private static String getAcrobatLocation() throws Exception + protected static String getAcrobatLocation() throws Exception { - ParseINI props; - try - { - props = new ParseINI(Const.INI_FILE); - if(new File(Const.INI_FILE).length() == 0) - new File(Const.INI_FILE).delete(); - } - catch(IOException e) - { - props = new ParseINI(); - } - String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property - if(acrobatLocation == null) - { - if(NativeFunctions.isUnix()) - { - throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); - } - } - return acrobatLocation; + return GXReportPainter.getAcrobatLocation(); } public static void printReport(String pdfFilename, boolean silent) throws Exception { - if(NativeFunctions.isWindows()) - { - pdfFilename = "\"" + new File(pdfFilename).getAbsolutePath() + "\""; - } - - String [] cmd = {}; - String acrobatLocation = null; - try - { - acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) - { - throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); - } - nativeCode.executeModal(acrobatLocation + " -toPostScript " + pdfFilename, false); - int pos = pdfFilename.lastIndexOf("."); - pdfFilename = pdfFilename.substring(0, pos) + ".ps"; - cmd = new String[] { "lp", pdfFilename}; - Runtime.getRuntime().exec(cmd); + GXReportPainter.printReport(pdfFilename,silent); } /** Muestra el reporte en pantalla @@ -159,187 +75,30 @@ public static void printReport(String pdfFilename, boolean silent) throws Except */ public static void showReport(String filename, boolean modal) throws Exception { - if(NativeFunctions.isWindows()) - { - filename = "\"" + new File(filename).getAbsolutePath() + "\""; - } - String acrobatLocation; - try - { - acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) - { - throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); - } - if(modal) - { - nativeCode.executeModal(acrobatLocation + " " + filename, true); - } - else - { - Runtime.getRuntime().exec(new String[] { acrobatLocation, filename}); - } + GXReportPainter.showReport(filename,modal); } - private static char alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; - public PDFReportpdfbox(ModelContext context) { + super(context); document = null; pageSize = null; - stringTotalPages = new Vector(); documentImages = new ConcurrentHashMap<>(); - httpContext = (HttpContext) context.getHttpContext(); - - if(defaultRelativePrepend == null) - { - defaultRelativePrepend = httpContext.getDefaultPath(); - if(defaultRelativePrepend == null || defaultRelativePrepend.trim().equals("")) - defaultRelativePrepend = ""; - else - defaultRelativePrepend = defaultRelativePrepend.replace(alternateSeparator, File.separatorChar) + File.separatorChar; - defaultRelativePrependINI = defaultRelativePrepend; - if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) - { - configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; - configurationTemplateFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_TEMPLATE_FILE; - } - else - { - configurationFile = defaultRelativePrepend + Const.INI_FILE; - configurationTemplateFile = defaultRelativePrepend + Const.INI_TEMPLATE_FILE; - } - webAppDir = defaultRelativePrepend; - - if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) - { - String staticContentBase = httpContext.getStaticContentBase(); - if(staticContentBase != null) - { - staticContentBase = staticContentBase.trim(); - if(staticContentBase.indexOf(':') == -1) - { - staticContentBase = staticContentBase.replace(alternateSeparator, File.separatorChar); - if(staticContentBase.startsWith(File.separator)) - { - staticContentBase = staticContentBase.substring(1); - } - if(!staticContentBase.equals("")) - { - defaultRelativePrepend += staticContentBase; - if(!defaultRelativePrepend.endsWith(File.separator)) - { - defaultRelativePrepend += File.separator; - } - } - } - } - } - } - if (firstTime) - { - loadProps(); - firstTime = false; - } } private static boolean firstTime = true; - private void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) + protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) - { - iniFile = defaultRelativePrependINI + Const.WEB_INF + File.separatorChar + iniFile; - } - else - { - iniFile = defaultRelativePrependINI + iniFile; - } - - try - { - this.form = form; - printerSettings = new ParseINI(iniFile); - } - catch(IOException e){ printerSettings = new ParseINI(); } - - mode = (mode==2)?3:0; - - printerSettings.setupProperty(form, Const.PRINTER, printer); - printerSettings.setupProperty(form, Const.MODE, mode + ""); - printerSettings.setupProperty(form, Const.ORIENTATION, orientation+ ""); - printerSettings.setupProperty(form, Const.PAPERSIZE, pageSize+ ""); - printerSettings.setupProperty(form, Const.PAPERLENGTH, pageLength+ ""); - printerSettings.setupProperty(form, Const.PAPERWIDTH, pageWidth+ ""); - printerSettings.setupProperty(form, Const.SCALE, scale+ ""); - printerSettings.setupProperty(form, Const.COPIES, copies+ ""); - printerSettings.setupProperty(form, Const.DEFAULTSOURCE, defSrc+ ""); - printerSettings.setupProperty(form, Const.PRINTQUALITY, quality+ ""); - printerSettings.setupProperty(form, Const.COLOR, color+ ""); - printerSettings.setupProperty(form, Const.DUPLEX, duplex+ ""); + super.loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); } - private void loadProps() + protected void loadProps() { - try{ - props = new ParseINI(configurationFile, configurationTemplateFile); - }catch(IOException e){ props = new ParseINI(); } - - props.setupGeneralProperty(Const.PDF_REPORT_INI_VERSION_ENTRY, Const.PDF_REPORT_INI_VERSION); - props.setupGeneralProperty(Const.EMBEED_SECTION, Const.EMBEED_DEFAULT); - props.setupGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, Const.EMBEED_DEFAULT); - props.setupGeneralProperty(Const.SEARCH_FONTS_ALWAYS, "false"); - props.setupGeneralProperty(Const.SEARCH_FONTS_ONCE, "true"); - props.setupGeneralProperty(Const.SERVER_PRINTING, "false"); - props.setupGeneralProperty(Const.ADJUST_TO_PAPER, "true"); - props.setupGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE, Const.DEFAULT_LINE_CAP_PROJECTING_SQUARE); - props.setupGeneralProperty(Const.BARCODE128_AS_IMAGE, Const.DEFAULT_BARCODE128_AS_IMAGE); - props.setupGeneralProperty("DEBUG", "false"); - props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); - props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); - props.setupGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER); - props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); - props.setupGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "."); - props.setupGeneralProperty(Const.LEADING, "2"); - props.setupGeneralProperty(Const.RUN_DIRECTION, Const.RUN_DIRECTION_LTR); - props.setupGeneralProperty(Const.JUSTIFIED_TYPE_ALL, "false"); - - props.setupGeneralProperty(Const.STYLE_DOTTED, Const.DEFAULT_STYLE_DOTTED); - props.setupGeneralProperty(Const.STYLE_DASHED, Const.DEFAULT_STYLE_DASHED); - props.setupGeneralProperty(Const.STYLE_LONG_DASHED, Const.DEFAULT_STYLE_LONG_DASHED); - props.setupGeneralProperty(Const.STYLE_LONG_DOT_DASHED, Const.DEFAULT_STYLE_LONG_DOT_DASHED); - - loadSubstituteTable(); - - if(props.getBooleanGeneralProperty("DEBUG", false)) - { - DEBUG = true; - DEBUG_STREAM = System.out; - } - else - { - DEBUG = false; - DEBUG_STREAM = new PrintStream(new com.genexus.util.NullOutputStream()); - } - - Utilities.addPredefinedSearchPaths(new String[]{System.getProperty("java.awt.fonts", "c:\\windows\\fonts"), - System.getProperty("com.ms.windir", "c:\\windows") + "\\fonts"}); - } - - public static final void addPredefinedSearchPaths(String [] predefinedPaths) - { - String predefinedPath = ""; - for(int i = 0; i < predefinedPaths.length; i++) - predefinedPath += predefinedPaths[i] + ";"; - predefinedSearchPath = predefinedPath + predefinedSearchPath; + super.loadProps(); } - public static final String getPredefinedSearchPaths() - { - return predefinedSearchPath; - } - - private void init() + protected void init() { try { document = new PDDocument(); @@ -353,40 +112,14 @@ public void GxRVSetLanguage(String lang) {} public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) {} - private float[] parsePattern(String patternStr) + protected float[] parsePattern(String patternStr) { - if (patternStr!=null) - { - StringTokenizer st = new StringTokenizer(patternStr.trim(), ";"); - int length = st.countTokens(); - if (length>0) - { - int i = 0; - float[] pattern = new float[length]; - while(st.hasMoreTokens()) - { - pattern[i] = Float.parseFloat(st.nextToken()); - i++; - } - return pattern; - } - } - return null; + return super.parsePattern(patternStr); } - private float [] getDashedPattern(int style) + protected float [] getDashedPattern(int style) { - switch(style) - { - case 0: return STYLE_SOLID; - case 1: return STYLE_NONE; - case 2: return STYLE_DOTTED; - case 3: return STYLE_DASHED; - case 4: return STYLE_LONG_DASHED; - case 5: return STYLE_LONG_DOT_DASHED; - default: - return STYLE_SOLID; - } + return super.getDashedPattern(style); } /** @@ -802,21 +535,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom public String getSubstitute(String fontName) { - Vector fontSubstitutesProcessed = new Vector<>(); - String newFontName = fontName; - while( fontSubstitutes.containsKey(newFontName)) - { - if (!fontSubstitutesProcessed.contains(newFontName)) - { - fontSubstitutesProcessed.addElement(newFontName); - newFontName = fontSubstitutes.get(newFontName); - } - else - { - return fontSubstitutes.get(newFontName); - } - } - return newFontName; + return super.getSubstitute(fontName); } public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) @@ -1012,44 +731,18 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } } - private String getFontLocation(String fontName) + protected String getFontLocation(String fontName) { - String fontPath = props.getProperty(Const.MS_FONT_LOCATION, fontName, ""); - if (fontPath.equals("")) - { - fontPath = props.getProperty(Const.SUN_FONT_LOCATION, fontName, ""); - } - return fontPath; + return super.getFontLocation(fontName); } @SuppressWarnings("unchecked") - private Hashtable getFontLocations() + protected Hashtable getFontLocations() { - Hashtable msLocations = props.getSection(Const.MS_FONT_LOCATION); - Hashtable sunLocations = props.getSection(Const.SUN_FONT_LOCATION); - Hashtable locations = new Hashtable(); - if (msLocations != null) - { - for (Enumeration e = msLocations.keys(); e.hasMoreElements() ;) - { - Object key = e.nextElement(); - locations.put(key, msLocations.get(key)); - } - } - if (sunLocations != null) - { - for (Enumeration e = sunLocations.keys(); e.hasMoreElements() ;) - { - Object key = e.nextElement(); - locations.put(key, sunLocations.get(key)); - } - } - return locations; + return super.getFontLocations(); } - private boolean isEmbeddedFont(String realFontName) { - boolean generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); - boolean generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); - return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, realFontName, generalEmbeedNotSpecified); + protected boolean isEmbeddedFont(String realFontName) { + return super.isEmbeddedFont(realFontName); } public void setAsianFont(String fontName, String style) @@ -1441,7 +1134,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ - return bottomAux > drawingPageHeight; + return super.pageHeightExceeded(bottomAux,drawingPageHeight); } public void GxClearAttris() {} @@ -1554,23 +1247,19 @@ else if (length == 15840 && width == 12240) public int getPageLines() { - if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); - return pageLines; + return super.getPageLines(); } public int getLineHeight() { - if(DEBUG)DEBUG_STREAM.println("getLineHeight: --> " + this.lineHeight); - return this.lineHeight; + return super.getLineHeight(); } public void setPageLines(int P_lines) { - if(DEBUG)DEBUG_STREAM.println("setPageLines: " + P_lines); - pageLines = P_lines; + super.setPageLines(P_lines); } public void setLineHeight(int lineHeight) { - if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); - this.lineHeight = lineHeight; + super.setLineHeight(lineHeight); } int M_top ; @@ -1578,22 +1267,22 @@ public void setLineHeight(int lineHeight) public int getM_top() { - return M_top; + return super.getM_top(); } public int getM_bot() { - return M_bot; + return super.getM_bot(); } public void setM_top(int M_top) { - this.M_top = M_top; + super.setM_top(M_top); } public void setM_bot(int M_bot) { - this.M_bot = M_bot; + super.setM_bot(M_bot); } public void GxEndPage() {} @@ -1757,77 +1446,47 @@ public void GxSetDocFormat(String format) {} public void GxSetDocName(String docName) { - this.docName = docName.trim(); - if(this.docName.indexOf('.') < 0) - this.docName += ".pdf"; - if(!new File(docName).isAbsolute()) - { - String outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").replace(alternateSeparator, File.separatorChar).trim(); - if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) - { - if(!outputDir.endsWith(File.separator)) - { - outputDir += File.separator; - } - new File(outputDir).mkdirs(); - this.docName = outputDir + this.docName; - } - else - { - if (ModelContext.getModelContext() != null) - { - HttpContext webContext = (HttpContext) ModelContext.getModelContext().getHttpContext(); - if ((webContext != null) && (webContext instanceof HttpContextWeb)) - { - outputDir = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + File.separator; - this.docName = outputDir + this.docName; - } - } - } - } - if(this.docName.indexOf('.') < 0) - this.docName += ".pdf"; - if(DEBUG)DEBUG_STREAM.println("GxSetDocName: '" + this.docName + "'"); + super.GxSetDocName(docName); } public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { - return true; + return super.GxPrTextInit(ouput, nxPage, nyPage, psIniFile, psForm, sPrinter, nMode, nPaperLength, nPaperWidth, nGridX, nGridY, nPageLines); } public boolean GxPrnCfg( String ini ) { - return true; + return super.GxPrnCfg(ini); } public boolean GxIsAlive() { - return false; + return super.GxIsAlive(); } public boolean GxIsAliveDoc() { - return true; + return super.GxIsAliveDoc(); } private int page; public int getPage() { - return page; + return super.getPage(); } public void setPage(int page) { - this.page = page; + super.setPage(page); } public boolean getModal() { - return modal; + return super.getModal(); } public void setModal(boolean modal) { - this.modal = modal; + super.setModal(modal); } public void cleanup() {} @@ -1836,26 +1495,9 @@ public void setMetrics(String fontName, boolean bold, boolean italic, int ascent /** Carga la tabla de substitutos */ - private void loadSubstituteTable() + protected void loadSubstituteTable() { - Hashtable> tempInverseMappings = new Hashtable<>(); - - for(int i = 0; i < Const.FONT_SUBSTITUTES_TTF_TYPE1.length; i++) - fontSubstitutes.put(Const.FONT_SUBSTITUTES_TTF_TYPE1[i][0], Const.FONT_SUBSTITUTES_TTF_TYPE1[i][1]); - - Hashtable otherMappings = props.getSection(Const.FONT_SUBSTITUTES_SECTION); - if(otherMappings != null) - for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) - { - String fontName = (String)enumera.nextElement(); - fontSubstitutes.put(fontName, (String)otherMappings.get(fontName)); - if(tempInverseMappings.containsKey(fontName)) - { - String fontSubstitute = (String)otherMappings.get(fontName); - for(Enumeration enum2 = tempInverseMappings.get(fontName).elements(); enum2.hasMoreElements();) - fontSubstitutes.put(enum2.nextElement(), fontSubstitute); - } - } + super.loadSubstituteTable(); } /** Estos métodos no hacen nada en este contexto @@ -1868,23 +1510,20 @@ private void loadSubstituteTable() public void showInformation() {} public static final double SCALE_FACTOR = 72; - private double PPP = 96; - private double convertScale(int value) + + protected double convertScale(int value) { - double result = value * SCALE_FACTOR / PPP; - return result; + return super.convertScale(value); } - private double convertScale(double value) + protected double convertScale(double value) { - double result = value * SCALE_FACTOR / PPP; - return result; + return super.convertScale(value); } - private float reconvertScale(float value) + protected float reconvertScale(float value) { - float result = value / (float)(SCALE_FACTOR / PPP); - return result; + return super.reconvertScale(value); } /** @@ -1894,22 +1533,8 @@ private float reconvertScale(float value) * @param t string to replace f * @return string with f replaced by t */ - private static String replace(String s,String f,String t) { - StringBuffer b = new StringBuffer(); - int p = 0, c=0; - - while(c>-1) { - if((c = s.indexOf(f,p)) > -1) { - b.append(s.substring(p,c)); - b.append(t); - p=c+1; - } - } - - if(p Date: Fri, 24 Mar 2023 11:51:36 -0300 Subject: [PATCH 09/32] Parent n child tweaks and document shows on screen --- .../com/genexus/reports/GXReportPainter.java | 63 +-- .../com/genexus/reports/PDFReportItext.java | 11 - .../com/genexus/reports/PDFReportpdfbox.java | 446 +++++++++--------- 3 files changed, 251 insertions(+), 269 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/GXReportPainter.java b/java/src/main/java/com/genexus/reports/GXReportPainter.java index a5e395996..472c97ce2 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPainter.java +++ b/java/src/main/java/com/genexus/reports/GXReportPainter.java @@ -10,46 +10,41 @@ import java.awt.*; import java.io.*; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; public abstract class GXReportPainter implements IReportHandler{ protected int lineHeight, pageLines; - protected int pageOrientation; // Indica la orientacion de las páginas - + protected int pageOrientation; protected boolean fontUnderline; protected boolean fontStrikethru; protected int fontSize; protected boolean fontBold = false; protected boolean fontItalic = false; protected Color backColor, foreColor; - public static PrintStream DEBUG_STREAM; - protected OutputStream outputStream = null; // Contiene el OutputStream de salida del reporte - //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página - protected static ParseINI props; + public static PrintStream DEBUG_STREAM = System.out; + protected OutputStream outputStream = null; + protected static ParseINI props = new ParseINI(); protected ParseINI printerSettings; protected String form; - protected Vector stringTotalPages; // Contiene la lista de locations del parámetros {{Pages}} - protected boolean isPageDirty; // Indica si la pagina NO se debe 'dispose()'ar pues se le va a agregar cosas al terminar el PDF - protected int outputType = -1; // Indica el tipo de Output que se desea para el documento - protected int printerOutputMode = -1; // Indica si se debe mostrar el cuadro de Impresion para la salida por impresora - protected boolean modal = false; // Indica si el diálogo debe ser modal o no modal en - protected String docName = "PDFReport.pdf"; // Nombre del documento a generar (se cambia con GxSetDocName) - private static INativeFunctions nativeCode = NativeFunctions.getInstance(); - private static Hashtable fontSubstitutes = new Hashtable<>(); // Contiene la tabla de substitutos de fonts (String <--> String) - private static String configurationFile = null; - private static String configurationTemplateFile = null; - private static String defaultRelativePrepend = null; // En aplicaciones web, contiene la ruta al root de la aplicación para ser agregado al inicio de las imagenes con path relativo - private static String defaultRelativePrependINI = null; - private static String webAppDir = null; - //private boolean containsSpecialMetrics = false; - //private Hashtable fontMetricsProps = new Hashtable(); + protected Vector stringTotalPages; + protected boolean isPageDirty; + protected int outputType = -1; + protected int printerOutputMode = -1; + protected boolean modal = false; + protected String docName = "PDFReport.pdf"; + protected static INativeFunctions nativeCode = NativeFunctions.getInstance(); + protected static Hashtable fontSubstitutes = new Hashtable<>(); + protected static String configurationFile = null; + protected static String configurationTemplateFile = null; + protected static String defaultRelativePrepend = null; + protected static String defaultRelativePrependINI = null; + protected static String webAppDir = null; public static boolean DEBUG = false; protected int currLine; protected int lastLine = 0; - private static String predefinedSearchPath = ""; // Contiene los predefinedSearchPaths + private static String predefinedSearchPath = ""; protected float leftMargin; protected float topMargin; - protected float bottomMargin; //If Margin Bottom is not specified 6 lines are assumed (nlines =6). + protected float bottomMargin; protected int templateFontSize; protected boolean backFill = true; protected Color templateColorFill; @@ -63,12 +58,12 @@ public abstract class GXReportPainter implements IReportHandler{ public boolean barcode128AsImage = true; public int justifiedType; protected HttpContext httpContext = null; - float[] STYLE_SOLID = new float[]{1,0};//0 - float[] STYLE_NONE = null;//1 - float[] STYLE_DOTTED, //2 - STYLE_DASHED, //3 - STYLE_LONG_DASHED, //4 - STYLE_LONG_DOT_DASHED; //5 + float[] STYLE_SOLID = new float[]{1,0}; + float[] STYLE_NONE = null; + float[] STYLE_DOTTED, + STYLE_DASHED, + STYLE_LONG_DASHED, + STYLE_LONG_DOT_DASHED; int STYLE_NONE_CONST=1; protected enum VerticalAlign{ @@ -84,13 +79,7 @@ public int value(){ return intValue; } } - protected static char alternateSeparator; - - static { - props = new ParseINI(); - alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; - DEBUG_STREAM = System.out; - } + protected static char alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; /** Setea el OutputStream a utilizar * @param outputStream Stream a utilizar diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index 66fe3d5db..4aa5a2ef8 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -50,15 +50,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.io.PrintStream; import java.io.StringReader; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import com.genexus.CommonUtil; import com.genexus.ModelContext; -import com.genexus.internet.HttpContext; -import com.genexus.platform.INativeFunctions; import com.genexus.platform.NativeFunctions; import com.genexus.util.TemporaryFiles; import com.genexus.webpanels.HttpContextWeb; @@ -87,7 +84,6 @@ import com.genexus.reports.fonts.PDFFont; import com.genexus.reports.fonts.PDFFontDescriptor; import com.genexus.reports.fonts.Type1FontMetrics; -import com.genexus.reports.fonts.Utilities; public class PDFReportItext extends GXReportPainter { @@ -97,13 +93,6 @@ public class PDFReportItext extends GXReportPainter private BaseFont baseFont; private Barcode barcode = null; //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página - private static INativeFunctions nativeCode = NativeFunctions.getInstance(); - private static Hashtable fontSubstitutes = new Hashtable<>(); // Contiene la tabla de substitutos de fonts (String <--> String) - private static String configurationFile = null; - private static String configurationTemplateFile = null; - private static String defaultRelativePrepend = null; // En aplicaciones web, contiene la ruta al root de la aplicación para ser agregado al inicio de las imagenes con path relativo - private static String defaultRelativePrependINI = null; - private static String webAppDir = null; //private boolean containsSpecialMetrics = false; //private Hashtable fontMetricsProps = new Hashtable(); public static boolean DEBUG = false; diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 12f16c31e..4dd0cafed 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -8,15 +8,12 @@ import com.genexus.CommonUtil; import com.genexus.ModelContext; -import com.genexus.internet.HttpContext; -import com.genexus.platform.INativeFunctions; import com.genexus.platform.NativeFunctions; import com.genexus.util.TemporaryFiles; import com.genexus.webpanels.HttpContextWeb; import com.genexus.reports.fonts.PDFFont; import com.genexus.reports.fonts.PDFFontDescriptor; import com.genexus.reports.fonts.Type1FontMetrics; -import com.genexus.reports.fonts.Utilities; import org.apache.pdfbox.cos.*; import org.apache.pdfbox.pdmodel.*; @@ -34,13 +31,6 @@ public class PDFReportpdfbox extends GXReportPainter{ private PDType1Font font; private PDType0Font baseFont; //private BarcodeUtil barcode = null; por ahora no soportamos barcode - private static INativeFunctions nativeCode = NativeFunctions.getInstance(); - private static Hashtable fontSubstitutes = new Hashtable<>(); - private static String configurationFile = null; - private static String configurationTemplateFile = null; - private static String defaultRelativePrepend = null; - private static String defaultRelativePrependINI = null; - private static String webAppDir = null; public static boolean DEBUG = false; private PDDocument document; private PDDocumentCatalog writer; @@ -81,16 +71,24 @@ public static void showReport(String filename, boolean modal) throws Exception public PDFReportpdfbox(ModelContext context) { super(context); - document = null; - pageSize = null; - documentImages = new ConcurrentHashMap<>(); + try { + document = null; + pageSize = null; + documentImages = new ConcurrentHashMap<>(); + } catch (Exception e){ + e.printStackTrace(System.err); + } } private static boolean firstTime = true; protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - super.loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + try { + super.loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + } catch (Exception e){ + e.printStackTrace(System.err); + } } protected void loadProps() @@ -312,7 +310,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ float penAux = (float)convertScale(pen); float rightAux = (float)convertScale(right); @@ -409,7 +407,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ float widthAux = (float)convertScale(width); float rightAux = (float)convertScale(right); @@ -456,7 +454,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ PDImageXObject image; try { @@ -832,7 +830,7 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ boolean printRectangle = false; if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) printRectangle = true; @@ -906,14 +904,13 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); contentStream.setNonStrokingColor(backColor); contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); contentStream.fill(); - contentStream.close(); try { - document.getPage(page - 1).setMediaBox(rectangle); + document.getPage(page).setMediaBox(rectangle); contentStream.close(); } catch(Exception e) @@ -952,14 +949,13 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); contentStream.setNonStrokingColor(foreColor); // set background color to yellow contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); - contentStream.close(); try { - document.getPage(page - 1).setMediaBox(underline); + document.getPage(page).setMediaBox(underline); contentStream.close(); } catch(Exception e) @@ -995,14 +991,13 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); contentStream.setNonStrokingColor(foreColor); contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); - contentStream.close(); try { - document.getPage(page - 1).setMediaBox(underline); + document.getPage(page).setMediaBox(underline); contentStream.close(); } catch(Exception e) @@ -1022,7 +1017,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) templateCreated = true; } PDFormXObject form = new PDFormXObject(document); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); contentStream.drawForm(form); contentStream.close(); @@ -1060,8 +1055,8 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); try{ - document.getPage(page - 1).getAnnotations().add(annotation); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1)); + document.getPage(page).getAnnotations().add(annotation); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); contentStream.beginText(); contentStream.showText(annotation.getContents()); contentStream.endText(); @@ -1086,7 +1081,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } - try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1))){ + try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page))){ switch(alignment) { @@ -1095,8 +1090,8 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; contentStream.setHorizontalScaling(1f); contentStream.setFont(baseFont, fontSize); + contentStream.moveTo(x, y); contentStream.beginText(); - contentStream.newLineAtOffset(x, y); contentStream.showText(sTxt); contentStream.endText(); contentStream.close(); @@ -1106,8 +1101,8 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; contentStream.setHorizontalScaling(1f); contentStream.setFont(baseFont, fontSize); + contentStream.moveTo(x, y); contentStream.beginText(); - contentStream.newLineAtOffset(x, y); contentStream.showText(sTxt); contentStream.endText(); contentStream.close(); @@ -1118,10 +1113,11 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; contentStream.setHorizontalScaling(1f); contentStream.setFont(baseFont, fontSize); + contentStream.moveTo(x, y); contentStream.beginText(); - contentStream.newLineAtOffset(x, y); contentStream.showText(sTxt); contentStream.endText(); + contentStream.close(); break; } } catch (Exception e) { @@ -1146,77 +1142,82 @@ public void GxClearAttris() {} private static double TO_CM_SCALE =28.6; public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - PPP = gxYPage[0]; - loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + try { + PPP = gxYPage[0]; + loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - if(outputStream != null) - { - if (output.equalsIgnoreCase("PRN")) - outputType = Const.OUTPUT_STREAM_PRINTER; - else - outputType = Const.OUTPUT_STREAM; - } - else - { - if(output.equalsIgnoreCase("SCR")) - outputType = Const.OUTPUT_SCREEN; - else if(output.equalsIgnoreCase("PRN")) - outputType = Const.OUTPUT_PRINTER; - else outputType = Const.OUTPUT_FILE; - - if(outputType == Const.OUTPUT_FILE) - TemporaryFiles.getInstance().removeFileFromList(docName); + if(outputStream != null) + { + if (output.equalsIgnoreCase("PRN")) + outputType = Const.OUTPUT_STREAM_PRINTER; + else + outputType = Const.OUTPUT_STREAM; + } else { - String tempPrefix = docName; - String tempExtension = "pdf"; - int tempIndex = docName.lastIndexOf('.'); - if(tempIndex != -1) + if(output.equalsIgnoreCase("SCR")) + outputType = Const.OUTPUT_SCREEN; + else if(output.equalsIgnoreCase("PRN")) + outputType = Const.OUTPUT_PRINTER; + else outputType = Const.OUTPUT_FILE; + + if(outputType == Const.OUTPUT_FILE) + TemporaryFiles.getInstance().removeFileFromList(docName); + else { - tempPrefix = docName.substring(0, tempIndex); - tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); + String tempPrefix = docName; + String tempExtension = "pdf"; + int tempIndex = docName.lastIndexOf('.'); + if(tempIndex != -1) + { + tempPrefix = docName.substring(0, tempIndex); + tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); + } + docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); + } + try + { + setOutputStream(new FileOutputStream(docName)); + }catch(IOException accessError) + { + accessError.printStackTrace(System.err); + outputStream = new com.genexus.util.NullOutputStream(); + outputType = Const.OUTPUT_FILE; } - docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); - } - try - { - setOutputStream(new FileOutputStream(docName)); - }catch(IOException accessError) - { - accessError.printStackTrace(System.err); - outputStream = new com.genexus.util.NullOutputStream(); - outputType = Const.OUTPUT_FILE; } - } - printerOutputMode = mode; - - boolean ret; - ret = props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); - ret = props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); - ret = props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); - leftMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.LEFT_MARGIN)).doubleValue()); - topMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.TOP_MARGIN)).doubleValue()); - bottomMargin = (float) (Double.valueOf(props.getGeneralProperty(Const.BOTTOM_MARGIN)).doubleValue()); - - lineCapProjectingSquare = props.getGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE).equals("true"); - barcode128AsImage = props.getGeneralProperty(Const.BARCODE128_AS_IMAGE).equals("true"); - STYLE_DOTTED = parsePattern(props.getGeneralProperty(Const.STYLE_DOTTED)); - STYLE_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_DASHED)); - STYLE_LONG_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DASHED)); - STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); - - runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); - - this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); - gxXPage[0] = (int)this.pageSize.getUpperRightX (); - if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) - gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); - else - gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); + printerOutputMode = mode; + + boolean ret; + ret = props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); + ret = props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); + ret = props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); + leftMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.LEFT_MARGIN)).doubleValue()); + topMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.TOP_MARGIN)).doubleValue()); + bottomMargin = (float) (Double.valueOf(props.getGeneralProperty(Const.BOTTOM_MARGIN)).doubleValue()); + + lineCapProjectingSquare = props.getGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE).equals("true"); + barcode128AsImage = props.getGeneralProperty(Const.BARCODE128_AS_IMAGE).equals("true"); + STYLE_DOTTED = parsePattern(props.getGeneralProperty(Const.STYLE_DOTTED)); + STYLE_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_DASHED)); + STYLE_LONG_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DASHED)); + STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); + + runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); + + this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); + gxXPage[0] = (int)this.pageSize.getUpperRightX (); + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); + else + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); - init(); + init(); - return true; + return true; + } catch (Exception e) { + e.printStackTrace(System.err); + return false; + } } private PDRectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) @@ -1289,149 +1290,152 @@ public void GxEndPage() {} public void GxEndDocument() { - if(document.getNumberOfPages() == 0) - { - document.addPage(new PDPage(this.pageSize)); - pages++; - } - if (template != null) - { - try{ - template.beginText(); - template.setFont(baseFont, fontSize); - template.setTextMatrix(new Matrix()); - template.setNonStrokingColor(templateColorFill); - template.showText(String.valueOf(pages)); - template.endText(); - template.close(); - for (PDPage page : document.getPages()){ - try (PDPageContentStream templatePainter = new PDPageContentStream(document, page)) { - templatePainter.drawForm(formXObjecttemplate); - } - - } - template.close(); - } catch (IOException e){ System.err.println(e.getMessage()); } - } - int copies = 1; - try - { - copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); - if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); - - writer = document.getDocumentCatalog(); - - COSDictionary dict = new COSDictionary(); - if (writer.getViewerPreferences() != null && writer.getViewerPreferences().getCOSObject() != null) - dict = writer.getViewerPreferences().getCOSObject(); - PDViewerPreferences viewerPreferences = new PDViewerPreferences(dict); - viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); - dict.setInt("NumCopies", copies); - writer.setViewerPreferences(viewerPreferences); - - int duplex= Integer.parseInt(printerSettings.getProperty(form, Const.DUPLEX)); - COSName duplexValue; - switch (duplex){ - case 1: duplexValue = COSName.HELV; break; - case 2: duplexValue = COSName.DUPLEX; break; - case 3: duplexValue = COSName.DUPLEX;break; - case 4: duplexValue = COSName.DUPLEX;break; - default: duplexValue = COSName.NONE; - } - if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue); - writer = document.getDocumentCatalog(); - dict = writer.getViewerPreferences().getCOSObject(); - if (dict == null) {dict = new COSDictionary();} - viewerPreferences = new PDViewerPreferences(dict); - viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); - dict.setName(COSName.DUPLEX, duplexValue.toString()); - writer.setViewerPreferences(viewerPreferences); - } - catch(Exception ex) - { - ex.printStackTrace(System.err); - } - - String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); - boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); - if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) - { - PDDocumentCatalog catalog = document.getDocumentCatalog(); - StringBuffer jsActions = new StringBuffer(); - jsActions.append("var pp = this.getPrintParams();\n"); - String printerAux=printerSettings.getProperty(form, Const.PRINTER); - String printer = replace(printerAux, "\\", "\\\\"); - - if (printer!=null && !printer.equals("")) + try { + if(document.getNumberOfPages() == 0) { - jsActions.append("pp.printerName = \"" + printer + "\";\n"); + document.addPage(new PDPage(this.pageSize)); + pages++; } + if (template != null) + { + try{ + template.beginText(); + template.setFont(baseFont, fontSize); + template.setTextMatrix(new Matrix()); + template.setNonStrokingColor(templateColorFill); + template.showText(String.valueOf(pages)); + template.endText(); + template.close(); + for (PDPage page : document.getPages()){ + try (PDPageContentStream templatePainter = new PDPageContentStream(document, page)) { + templatePainter.drawForm(formXObjecttemplate); + } - if (fit) + } + template.close(); + } catch (IOException e){ System.err.println(e.getMessage()); } + } + int copies = 1; + try { - jsActions.append("pp.pageHandling = pp.constants.handling.fit;\n"); + copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); + if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); + + writer = document.getDocumentCatalog(); + + COSDictionary dict = new COSDictionary(); + if (writer.getViewerPreferences() != null && writer.getViewerPreferences().getCOSObject() != null) + dict = writer.getViewerPreferences().getCOSObject(); + PDViewerPreferences viewerPreferences = new PDViewerPreferences(dict); + viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); + dict.setInt("NumCopies", copies); + writer.setViewerPreferences(viewerPreferences); + + int duplex= Integer.parseInt(printerSettings.getProperty(form, Const.DUPLEX)); + COSName duplexValue; + switch (duplex){ + case 1: duplexValue = COSName.HELV; break; + case 2: duplexValue = COSName.DUPLEX; break; + case 3: duplexValue = COSName.DUPLEX;break; + case 4: duplexValue = COSName.DUPLEX;break; + default: duplexValue = COSName.NONE; + } + if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue); + writer = document.getDocumentCatalog(); + dict = writer.getViewerPreferences().getCOSObject(); + if (dict == null) {dict = new COSDictionary();} + viewerPreferences = new PDViewerPreferences(dict); + viewerPreferences.setPrintScaling(PDViewerPreferences.PRINT_SCALING.None); + dict.setName(COSName.DUPLEX, duplexValue.toString()); + writer.setViewerPreferences(viewerPreferences); } - else + catch(Exception ex) { - jsActions.append("pp.pageHandling = pp.constants.handling.none;\n"); + ex.printStackTrace(System.err); } - if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")) + String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); + boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); + if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { - jsActions.append("pp.interactive = pp.constants.interactionLevel.automatic;\n"); - for(int i = 0; i < copies; i++) + PDDocumentCatalog catalog = document.getDocumentCatalog(); + StringBuffer jsActions = new StringBuffer(); + jsActions.append("var pp = this.getPrintParams();\n"); + String printerAux=printerSettings.getProperty(form, Const.PRINTER); + String printer = replace(printerAux, "\\", "\\\\"); + + if (printer!=null && !printer.equals("")) + { + jsActions.append("pp.printerName = \"" + printer + "\";\n"); + } + + if (fit) + { + jsActions.append("pp.pageHandling = pp.constants.handling.fit;\n"); + } + else + { + jsActions.append("pp.pageHandling = pp.constants.handling.none;\n"); + } + + if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")) + { + jsActions.append("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + for(int i = 0; i < copies; i++) + { + jsActions.append("this.print(pp);\n"); + } + } + else { + jsActions.append("pp.interactive = pp.constants.interactionLevel.full;\n"); jsActions.append("this.print(pp);\n"); } + PDActionJavaScript openActions = new PDActionJavaScript(jsActions.toString()); + catalog.setOpenAction(openActions); } - else - { - jsActions.append("pp.interactive = pp.constants.interactionLevel.full;\n"); - jsActions.append("this.print(pp);\n"); + try { + document.save(outputStream); + document.close(); + } catch (IOException e) { + System.err.println(e.getMessage()); } - PDActionJavaScript openActions = new PDActionJavaScript(jsActions.toString()); - catalog.setOpenAction(openActions); - } - try { - String pdfFilename = new File(docName).getAbsolutePath(); - document.save(pdfFilename); - document.close(); - } catch (IOException e) { - System.err.println(e.getMessage()); - } - if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); + if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); - try{ props.save(); } catch(IOException e) { ; } + try{ props.save(); } catch(IOException e) { ; } - switch(outputType) - { - case Const.OUTPUT_SCREEN: - try{ outputStream.close(); } catch(IOException e) { } - try{ showReport(docName, modal); } - catch(Exception e) { - e.printStackTrace(); - } - break; - case Const.OUTPUT_PRINTER: - try{ outputStream.close(); } catch(IOException e) { } - try{ - if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) - { - printReport(docName, this.printerOutputMode == 1); + switch(outputType) + { + case Const.OUTPUT_SCREEN: + try{ outputStream.close(); } catch(IOException e) { } + try{ showReport(docName, modal); } + catch(Exception e) { + e.printStackTrace(); } - } catch(Exception e){ - e.printStackTrace(); - } - break; - case Const.OUTPUT_FILE: - try{ outputStream.close(); } catch(IOException e) { ; } - break; - case Const.OUTPUT_STREAM: - case Const.OUTPUT_STREAM_PRINTER: - default: break; + break; + case Const.OUTPUT_PRINTER: + try{ outputStream.close(); } catch(IOException e) { } + try{ + if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) + { + printReport(docName, this.printerOutputMode == 1); + } + } catch(Exception e){ + e.printStackTrace(); + } + break; + case Const.OUTPUT_FILE: + try{ outputStream.close(); } catch(IOException e) { ; } + break; + case Const.OUTPUT_STREAM: + case Const.OUTPUT_STREAM_PRINTER: + default: break; + } + outputStream = null; + } catch (Exception e){ + e.printStackTrace(System.err); } - outputStream = null; } public void GxEndPrinter() {} From 864e006b32a62ec6edb7c60152c58f5626274771 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Mon, 27 Mar 2023 13:32:05 -0300 Subject: [PATCH 10/32] text, lines and rectangles appear on report --- .../com/genexus/reports/PDFReportpdfbox.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 4dd0cafed..d44f6e28d 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -1081,14 +1081,13 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } - try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page))){ + try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND, false, false)){ switch(alignment) { case 1: // Center Alignment float x = ((leftAux + rightAux) / 2) + leftMargin; float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.setHorizontalScaling(1f); contentStream.setFont(baseFont, fontSize); contentStream.moveTo(x, y); contentStream.beginText(); @@ -1099,7 +1098,6 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) case 2: // Right Alignment x = rightAux + leftMargin; y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.setHorizontalScaling(1f); contentStream.setFont(baseFont, fontSize); contentStream.moveTo(x, y); contentStream.beginText(); @@ -1109,16 +1107,16 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) break; case 0: // Left Alignment case 3: // Justified, only one text line - x = (leftAux + rightAux) / 2 + leftMargin; - y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.setHorizontalScaling(1f); - contentStream.setFont(baseFont, fontSize); - contentStream.moveTo(x, y); - contentStream.beginText(); - contentStream.showText(sTxt); - contentStream.endText(); - contentStream.close(); - break; + x = (leftAux + rightAux) / 2 + leftMargin; + y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; + contentStream.beginText(); + contentStream.setFont(baseFont, fontSize); + contentStream.newLineAtOffset(x, y); + contentStream.showText(sTxt); + contentStream.endText(); + contentStream.close(); + break; + } } catch (Exception e) { System.err.println(e.getMessage()); From ce2af28f559b3a87951c955273bfa95415c1ab57 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 29 Mar 2023 13:44:21 -0300 Subject: [PATCH 11/32] Support for img and many controls at the same time --- .../com/genexus/reports/PDFReportItext.java | 1 - .../com/genexus/reports/PDFReportpdfbox.java | 180 ++++++------------ 2 files changed, 59 insertions(+), 122 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index 4aa5a2ef8..f13080c30 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -95,7 +95,6 @@ public class PDFReportItext extends GXReportPainter //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página //private boolean containsSpecialMetrics = false; //private Hashtable fontMetricsProps = new Hashtable(); - public static boolean DEBUG = false; private Document document; private PdfWriter writer; private Paragraph chunk; diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index d44f6e28d..a351788c4 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -31,7 +31,6 @@ public class PDFReportpdfbox extends GXReportPainter{ private PDType1Font font; private PDType0Font baseFont; //private BarcodeUtil barcode = null; por ahora no soportamos barcode - public static boolean DEBUG = false; private PDDocument document; private PDDocumentCatalog writer; private static String predefinedSearchPath = ""; @@ -58,11 +57,6 @@ public static void printReport(String pdfFilename, boolean silent) throws Except GXReportPainter.printReport(pdfFilename,silent); } - /** Muestra el reporte en pantalla - * @param filename nombre del PDF a mostrar - * @param modal indica si el PDF se va a mostrar en diálogo modal - * @exception Exception no se puede encontrar el Acrobat - */ public static void showReport(String filename, boolean modal) throws Exception { GXReportPainter.showReport(filename,modal); @@ -120,9 +114,6 @@ protected float[] parsePattern(String patternStr) return super.getDashedPattern(style); } - /** - * @param hideCorners indica si se deben ocultar los triangulos de las esquinas cuando el lado que los une esta oculto. - */ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) @@ -310,7 +301,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ float penAux = (float)convertScale(pen); float rightAux = (float)convertScale(right); @@ -396,7 +387,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo if(DEBUG)DEBUG_STREAM.println("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); } catch (Exception e) { - + System.err.println(e.getMessage()); } } @@ -407,7 +398,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ float widthAux = (float)convertScale(width); float rightAux = (float)convertScale(right); @@ -443,7 +434,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int cb.restoreGraphicsState(); } catch (Exception e){ - + System.err.println(e.getMessage()); } } @@ -454,7 +445,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ PDImageXObject image; try { @@ -522,7 +513,6 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom cb.drawImage(image, x, y, rightAux - leftAux, bottomAux - topAux); else cb.drawImage(image, x, y, (rightAux - leftAux) * aspectRatio, (bottomAux - topAux) * aspectRatio); - cb.close(); } } catch(Exception e) @@ -785,24 +775,24 @@ public void setAsianFont(String fontName, String style) else { if (fontName.equals("Japanese")){ - fontDict.setName(COSName.BASE_FONT, "HeiseiMin-W3"); + fontDict.setName(COSName.BASE_FONT, "HeiseiMin-W3" + style); differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H")); } if (fontName.equals("Japanese2")){ - fontDict.setName(COSName.BASE_FONT, "HeiseiKakuGo-W5"); - differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H")); + fontDict.setName(COSName.BASE_FONT, "HeiseiKakuGo-W5" + style); + differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H" + style)); } if (fontName.equals("SimplifiedChinese")){ fontDict.setName(COSName.BASE_FONT, "STSong-Light"); - differencesArray.add(COSName.getPDFName("UniGB-UCS2-H")); + differencesArray.add(COSName.getPDFName("UniGB-UCS2-H" + style)); } if (fontName.equals("TraditionalChinese")){ fontDict.setName(COSName.BASE_FONT, "MHei-Medium"); - differencesArray.add(COSName.getPDFName("UniGB-UCS2-H")); + differencesArray.add(COSName.getPDFName("UniGB-UCS2-H" + style)); } if (fontName.equals("Korean")) { fontDict.setName(COSName.BASE_FONT, "HYSMyeongJo-Medium"); - differencesArray.add(COSName.getPDFName("UniKS-UCS2-H")); + differencesArray.add(COSName.getPDFName("UniKS-UCS2-H" + style)); } fontDict.setItem(COSName.ENCODING, encodingDict); fontDict.setItem(COSName.DESC, null); @@ -830,7 +820,7 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page))){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ boolean printRectangle = false; if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) printRectangle = true; @@ -850,7 +840,7 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in cb.setFont(font,fontSize); cb.setNonStrokingColor(foreColor); int arabicOptions = 0; - float captionHeight = font.getFontDescriptor().getCapHeight(); + float captionHeight = baseFont.getFontMatrix().transformPoint(0, font.getFontDescriptor().getCapHeight()).y * fontSize; float rectangleWidth = font.getStringWidth(sTxt); float lineHeight = font.getFontDescriptor().getFontBoundingBox().getUpperRightY() - font.getFontDescriptor().getFontBoundingBox().getLowerLeftX(); float textBlockHeight = (float)convertScale(bottom-top); @@ -904,19 +894,11 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); contentStream.setNonStrokingColor(backColor); contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); contentStream.fill(); - try - { - document.getPage(page).setMediaBox(rectangle); - contentStream.close(); - } - catch(Exception e) - { - System.err.println(e.getMessage()); - } + contentStream.close(); } float underlineSeparation = lineHeight / 5; @@ -949,19 +931,11 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); contentStream.setNonStrokingColor(foreColor); // set background color to yellow contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); - try - { - document.getPage(page).setMediaBox(underline); - contentStream.close(); - } - catch(Exception e) - { - System.err.println(e.getMessage()); - } + contentStream.close(); } if (fontStrikethru) @@ -991,19 +965,11 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); contentStream.setNonStrokingColor(foreColor); contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); - try - { - document.getPage(page).setMediaBox(underline); - contentStream.close(); - } - catch(Exception e) - { - System.err.println(e.getMessage()); - } + contentStream.close(); } if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) @@ -1017,7 +983,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) templateCreated = true; } PDFormXObject form = new PDFormXObject(document); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); contentStream.drawForm(form); contentStream.close(); @@ -1054,18 +1020,12 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) annotation.setContents(sTxt); annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); - try{ - document.getPage(page).getAnnotations().add(annotation); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page)); - contentStream.beginText(); - contentStream.showText(annotation.getContents()); - contentStream.endText(); - contentStream.close(); - } - catch (Exception e) - { - e.printStackTrace(System.err); - } + document.getPage(page).getAnnotations().add(annotation); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); + contentStream.beginText(); + contentStream.showText(annotation.getContents()); + contentStream.endText(); + contentStream.close(); } else { @@ -1080,46 +1040,18 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) TxtWidth = baseFont.getStringWidth(newsTxt) / 1000 * fontSize; } } - - try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND, false, false)){ - - switch(alignment) - { - case 1: // Center Alignment - float x = ((leftAux + rightAux) / 2) + leftMargin; - float y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.setFont(baseFont, fontSize); - contentStream.moveTo(x, y); - contentStream.beginText(); - contentStream.showText(sTxt); - contentStream.endText(); - contentStream.close(); - break; - case 2: // Right Alignment - x = rightAux + leftMargin; - y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.setFont(baseFont, fontSize); - contentStream.moveTo(x, y); - contentStream.beginText(); - contentStream.showText(sTxt); - contentStream.endText(); - contentStream.close(); - break; - case 0: // Left Alignment - case 3: // Justified, only one text line - x = (leftAux + rightAux) / 2 + leftMargin; - y = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight; - contentStream.beginText(); - contentStream.setFont(baseFont, fontSize); - contentStream.newLineAtOffset(x, y); - contentStream.showText(sTxt); - contentStream.endText(); - contentStream.close(); - break; - - } - } catch (Exception e) { - System.err.println(e.getMessage()); + switch(alignment) + { + case 1: // Center Alignment + showTextAligned(font, sTxt, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); + break; + case 2: // Right Alignment + showTextAligned(font, sTxt, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + showTextAligned(font, sTxt, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); + break; } } } @@ -1127,6 +1059,23 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) System.err.println(e.getMessage()); } } + + private void showTextAligned(PDType0Font font, String text, float x, float y){ + try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page), PDPageContentStream.AppendMode.APPEND, false, false)){ + contentStream.saveGraphicsState(); + contentStream.setFont(font, fontSize); + contentStream.setLeading(2); + contentStream.beginText(); + contentStream.moveTextPositionByAmount(x, y); + for (String line : text.split("\n")) { + contentStream.newLine(); + contentStream.showText(line); + } + contentStream.endText(); + contentStream.restoreGraphicsState(); + } catch (Exception e) { System.err.println(e.getMessage()); } + } + boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ return super.pageHeightExceeded(bottomAux,drawingPageHeight); } @@ -1305,7 +1254,7 @@ public void GxEndDocument() template.endText(); template.close(); for (PDPage page : document.getPages()){ - try (PDPageContentStream templatePainter = new PDPageContentStream(document, page)) { + try (PDPageContentStream templatePainter = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,false)) { templatePainter.drawForm(formXObjecttemplate); } @@ -1334,8 +1283,8 @@ public void GxEndDocument() switch (duplex){ case 1: duplexValue = COSName.HELV; break; case 2: duplexValue = COSName.DUPLEX; break; - case 3: duplexValue = COSName.DUPLEX;break; - case 4: duplexValue = COSName.DUPLEX;break; + case 3: duplexValue = COSName.DUPLEX; break; + case 4: duplexValue = COSName.DUPLEX; break; default: duplexValue = COSName.NONE; } if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue); @@ -1439,7 +1388,7 @@ public void GxEndDocument() public void GxEndPrinter() {} public void GxStartPage() { - document.addPage(new PDPage()); + document.addPage(new PDPage(this.pageSize)); pages++; } @@ -1495,15 +1444,11 @@ public void cleanup() {} public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) {} - /** Carga la tabla de substitutos - */ protected void loadSubstituteTable() { super.loadSubstituteTable(); } - /** Estos métodos no hacen nada en este contexto - */ public void GxPrintMax() { ; } public void GxPrintNormal() { ; } public void GxPrintOnTop() { ; } @@ -1528,13 +1473,6 @@ protected float reconvertScale(float value) return super.reconvertScale(value); } - /** - * Helper method for toString() - * @param s source string - * @param f string to remove - * @param t string to replace f - * @return string with f replaced by t - */ protected static String replace(String s,String f,String t) { return GXReportPainter.replace(s,f,t); } From ec81e280330b6839e600de532bcc3268445ee115 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 29 Mar 2023 19:32:54 -0300 Subject: [PATCH 12/32] More code cleanup --- .../com/genexus/reports/GXReportPainter.java | 84 ++-- .../com/genexus/reports/PDFReportItext.java | 401 +----------------- .../com/genexus/reports/PDFReportpdfbox.java | 240 +---------- 3 files changed, 65 insertions(+), 660 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/GXReportPainter.java b/java/src/main/java/com/genexus/reports/GXReportPainter.java index 472c97ce2..22fbae2fd 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPainter.java +++ b/java/src/main/java/com/genexus/reports/GXReportPainter.java @@ -1,5 +1,52 @@ package com.genexus.reports; +/** + * Formato del archivo PDFReport.INI + * --------------------------------- + * + * GeneralProperties: + * - Embeed Fonts -> booleano que indica si embeber los fonts o no (ver Seccion 'Embeed Fonts') + * - SearchNewFonts -> booleano que indica si se deben buscar los fonts si no estan en el INI al embeberlos + * - SearchNewFontsOnce -> booleano que indica buscar por única vez los fonts si no se encuentran + * - Version -> Indica la version del PDFReport (formato a.b.c.d) + * - FontsLocation -> Indica la ubicación de los fonts + * - LeftMargin -> Indica el margen izquierdo asociado al documento (en centúŠetros) + * - TopMargin -> Indica el margen arriba asociado al documento (en centúŠetros) + * - DEBUG -> Indica que se quiere mostrar DEBUG por la stdout + * + * Seccion 'Embeed Fonts': + * - Para cada nombre de font se le asocia un booleano que indica si embeber el font o no (para granularidad más fina de la GeneralProperty) + * Para embeber un font, debe estar en 'true' la generalProperty y la property de esta seccion + * Para setear que fonts embeber, se puede ejecutar el 'com.genexus.reports.PDFReportConfig' + * + * Seccion 'Fonts Location (MS)' y 'Fonts Location (Sun)' + * - Se almacenan los mappings 'FontName= ubiacion del .ttf asociado'. Estos mappings son distintos para MS y Sun + * Estos mappings son creados automaticamente + * + * Seccion 'Fonts Substitutions' + * - Se almacenan pares 'Font= Font' que mapean un font en otro. + * Por ejemplo, se puede poner 'Impact= Courier', para mapear un TrueTypeFont en otro + * También se puede mapear un font en un Type1, por ej: 'Impact= Helvetica' + * Estos mappings los puede realizar el usuario + * + * Seccion 'Font Metrics' + * - Se almacenan pares 'Font= metricas' que indican las metricas de un font + * Esto es definido por el usuario, es decir estas métricas hacen un override de las + * metricas que se utilizarú}n en otro caso + * Las metricas se definen mediante rules separadas por ';': + * FontName= rule1;rule2;...;ruleN + * donde cada rule puede ser de este estilo: + * - monospaced(XXX), que indica que se utilizan las mismas metricas para todos los caracteres + * - range(NN,XX0,XX1,XX2,XX3,XX4....,XXN, en el que se enumeran las metricas para cada + * caracter comenzando desde el caracter NN. En este caso si se indican unas pocas metricas, solo + * se hace el override de la interseccion. + * - move(HH,VV), que indica que los textos con dicho font se deben mover HH y VV pixels + * horizantal y verticalmente + * Nota: no se puede especificar si el font es bold y/o italic, es decir que estas metricas + * van a aplicar para todas las combinaciones de bold/italic para dicho font + * + */ + import com.genexus.ModelContext; import com.genexus.internet.HttpContext; import com.genexus.platform.INativeFunctions; @@ -58,6 +105,7 @@ public abstract class GXReportPainter implements IReportHandler{ public boolean barcode128AsImage = true; public int justifiedType; protected HttpContext httpContext = null; + protected static boolean firstTime = true; float[] STYLE_SOLID = new float[]{1,0}; float[] STYLE_NONE = null; float[] STYLE_DOTTED, @@ -84,7 +132,7 @@ public int value(){ /** Setea el OutputStream a utilizar * @param outputStream Stream a utilizar */ - protected void setOutputStream(OutputStream outputStream) + public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; } @@ -104,7 +152,6 @@ protected static String getAcrobatLocation() throws Exception { props = new ParseINI(); } - // Primero debo obtener la ubicación + ejecutable del Acrobat String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property if(acrobatLocation == null) @@ -186,8 +233,6 @@ public static void showReport(String filename, boolean modal) throws Exception } public GXReportPainter(ModelContext context) { - //document = null; - //pageSize = null; stringTotalPages = new Vector(); httpContext = (HttpContext) context.getHttpContext(); @@ -256,8 +301,6 @@ public GXReportPainter(ModelContext context) } } - private static boolean firstTime = true; - protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) @@ -354,7 +397,6 @@ public static final String getPredefinedSearchPaths() protected abstract void init(); - public void GxRVSetLanguage(String lang) {} public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) {} @@ -538,8 +580,8 @@ public void setLineHeight(int lineHeight) this.lineHeight = lineHeight; } - int M_top ; - int M_bot ; + protected int M_top ; + protected int M_bot ; public int getM_top() { @@ -568,14 +610,8 @@ public void setM_bot(int M_bot) public void GxEndPrinter() {} public abstract void GxStartPage(); - public void GxStartDoc() - { - //DEBUG.println("Processing..."); - } - public void GxSetDocFormat(String format) - { - //DEBUG.println("Processing..."); - } + public void GxStartDoc() {} + public void GxSetDocFormat(String format) {} public void GxSetDocName(String docName) { @@ -614,13 +650,11 @@ public void GxSetDocName(String docName) public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { - //DEBUG.println("Processing..."); return true; } public boolean GxPrnCfg( String ini ) { - //DEBUG.println("Processing..."); return true; } @@ -657,9 +691,7 @@ public void setModal(boolean modal) public void cleanup() {} - public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) - { - } + public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) {} /** Carga la tabla de substitutos @@ -695,14 +727,14 @@ protected void loadSubstituteTable() /** Estos métodos no hacen nada en este contexto */ public void GxPrintMax() { ; } + public void GxPrintNormal() { ; } + public void GxPrintOnTop() { ; } - public void GxPrnCmd(String cmd) { ; } + public void GxPrnCmd(String cmd) { ; } - public void showInformation() - { - } + public void showInformation() {} public static final double SCALE_FACTOR = 72; protected double PPP = 96; diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index f13080c30..5d5572e3b 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -1,51 +1,6 @@ package com.genexus.reports; + import java.awt.Color; -/** - * Formato del archivo PDFReport.INI - * --------------------------------- - * - * GeneralProperties: - * - Embeed Fonts -> booleano que indica si embeber los fonts o no (ver Seccion 'Embeed Fonts') - * - SearchNewFonts -> booleano que indica si se deben buscar los fonts si no estan en el INI al embeberlos - * - SearchNewFontsOnce -> booleano que indica buscar por única vez los fonts si no se encuentran - * - Version -> Indica la version del PDFReport (formato a.b.c.d) - * - FontsLocation -> Indica la ubicación de los fonts - * - LeftMargin -> Indica el margen izquierdo asociado al documento (en centúŠetros) - * - TopMargin -> Indica el margen arriba asociado al documento (en centúŠetros) - * - DEBUG -> Indica que se quiere mostrar DEBUG por la stdout - * - * Seccion 'Embeed Fonts': - * - Para cada nombre de font se le asocia un booleano que indica si embeber el font o no (para granularidad más fina de la GeneralProperty) - * Para embeber un font, debe estar en 'true' la generalProperty y la property de esta seccion - * Para setear que fonts embeber, se puede ejecutar el 'com.genexus.reports.PDFReportConfig' - * - * Seccion 'Fonts Location (MS)' y 'Fonts Location (Sun)' - * - Se almacenan los mappings 'FontName= ubiacion del .ttf asociado'. Estos mappings son distintos para MS y Sun - * Estos mappings son creados automaticamente - * - * Seccion 'Fonts Substitutions' - * - Se almacenan pares 'Font= Font' que mapean un font en otro. - * Por ejemplo, se puede poner 'Impact= Courier', para mapear un TrueTypeFont en otro - * También se puede mapear un font en un Type1, por ej: 'Impact= Helvetica' - * Estos mappings los puede realizar el usuario - * - * Seccion 'Font Metrics' - * - Se almacenan pares 'Font= metricas' que indican las metricas de un font - * Esto es definido por el usuario, es decir estas métricas hacen un override de las - * metricas que se utilizarú}n en otro caso - * Las metricas se definen mediante rules separadas por ';': - * FontName= rule1;rule2;...;ruleN - * donde cada rule puede ser de este estilo: - * - monospaced(XXX), que indica que se utilizan las mismas metricas para todos los caracteres - * - range(NN,XX0,XX1,XX2,XX3,XX4....,XXN, en el que se enumeran las metricas para cada - * caracter comenzando desde el caracter NN. En este caso si se indican unas pocas metricas, solo - * se hace el override de la interseccion. - * - move(HH,VV), que indica que los textos con dicho font se deben mover HH y VV pixels - * horizantal y verticalmente - * Nota: no se puede especificar si el font es bold y/o italic, es decir que estas metricas - * van a aplicar para todas las combinaciones de bold/italic para dicho font - * - */ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -87,62 +42,19 @@ public class PDFReportItext extends GXReportPainter { - private com.lowagie.text.Rectangle pageSize; // Contiene las dimensiones de la página private Font font; private BaseFont baseFont; private Barcode barcode = null; - //private Point pageMargin = new Point(0,0); // Contiene el margen [left, top] de cada página - //private boolean containsSpecialMetrics = false; - //private Hashtable fontMetricsProps = new Hashtable(); private Document document; private PdfWriter writer; private Paragraph chunk; - private static String predefinedSearchPath = ""; // Contiene los predefinedSearchPaths private PdfTemplate template; private BaseFont templateFont; public boolean lineCapProjectingSquare = true; public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; public int runDirection = PdfWriter.RUN_DIRECTION_LTR; - public int justifiedType; - - /** Setea el OutputStream a utilizar - * @param outputStream Stream a utilizar - */ - public void setOutputStream(OutputStream outputStream) - { - super.setOutputStream(outputStream); - } - - /** Busca la ubicación del Acrobat. Si no la encuentra tira una excepción - */ - protected static String getAcrobatLocation() throws Exception - { - return GXReportPainter.getAcrobatLocation(); - } - - /** Manda a imprimir el reporte a la impresora - * Si en las properties del PDFReport esta definida una GeneralProperty 'Acrobat Location' se - * utiliza esta property para obtener la ubicación + ejecutable del Acrobat, sino se busca en el Registry - * @param pdfFilename Nombre del reporte a imprimir (con extensión) - * @param silent Booleano que indica si se va a imprimir sin diálogo - * @exception Exception si no se puede realizar la operación - */ - public static void printReport(String pdfFilename, boolean silent) throws Exception - { - GXReportPainter.printReport(pdfFilename,silent); - } - - /** Muestra el reporte en pantalla - * @param filename nombre del PDF a mostrar - * @param modal indica si el PDF se va a mostrar en diálogo modal - * @exception Exception no se puede encontrar el Acrobat - */ - public static void showReport(String filename, boolean modal) throws Exception - { - GXReportPainter.showReport(filename,modal); - } public PDFReportItext(ModelContext context) { @@ -151,18 +63,6 @@ public PDFReportItext(ModelContext context) pageSize = null; documentImages = new ConcurrentHashMap<>(); } - - private static boolean firstTime = true; - - protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) - { - super.loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - } - - protected void loadProps() - { - super.loadProps(); - } protected void init() { @@ -175,25 +75,6 @@ protected void init() } document.open(); } - - - public void GxRVSetLanguage(String lang) - { - } - - public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) - { - } - - protected float[] parsePattern(String patternStr) - { - return super.parsePattern(patternStr); - } - - protected float [] getDashedPattern(int style) - { - return super.getDashedPattern(style); - } /** * @param hideCorners indica si se deben ocultar los triangulos de las esquinas cuando el lado que los une esta oculto. @@ -394,15 +275,7 @@ private void roundRectangle(PdfContentByte cb, float x, float y, float w, float } } - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) - { - GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, 0, 0); - } - - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int style, int cornerRadius) - { - GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, style, style, style, style, cornerRadius, cornerRadius, cornerRadius, cornerRadius); - } + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { @@ -497,11 +370,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo if(DEBUG)DEBUG_STREAM.println("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); } - - public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) - { - GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); - } public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { @@ -541,11 +409,6 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int cb.restoreState(); } - - public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom) - { - GxDrawBitMap(bitmap, left, top, right, bottom, 0); - } public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { @@ -640,11 +503,6 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom System.err.println(e.getMessage()); } } - - public String getSubstitute(String fontName) - { - return super.getSubstitute(fontName); - } public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) { @@ -779,20 +637,6 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } } - protected String getFontLocation(String fontName) - { - return super.getFontLocation(fontName); - } - @SuppressWarnings("unchecked") - protected Hashtable getFontLocations() - { - return super.getFontLocations(); - } - - protected boolean isEmbeddedFont(String realFontName) { - return super.isEmbeddedFont(realFontName); - } - public void setAsianFont(String fontName, String style) { try @@ -831,21 +675,6 @@ public void setAsianFont(String fontName, String style) System.err.println(ioe.getMessage()); } } - /** - * @deprecated - */ - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align) - { - GxDrawText(sTxt, left, top, right, bottom, align, 0); - } - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat) - { - GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, 0); - } - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border) - { - GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, border, 0); - } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { boolean printRectangle = false; @@ -935,7 +764,6 @@ else if (valign == VerticalAlign.BOTTOM.value()) Col.setAlignment(colAlignment); ColumnText simulationCol = new ColumnText(null); float drawingPageHeight = (float)this.pageSize.getTop() - topMargin - bottomMargin; - //Col.setSimpleColumn(llx, lly, urx, ury); Col.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); simulationCol.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); @@ -1265,7 +1093,6 @@ private int columnAlignment(int alignment) else return alignment; } - public void GxClearAttris() {} public static final double PAGE_SCALE_Y = 20; // Indica la escala de la página public static final double PAGE_SCALE_X = 20; // Indica la escala de la página @@ -1351,26 +1178,10 @@ else if(output.equalsIgnoreCase("PRN")) else gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); // Cuanto menor sea GX_PAGE_SCALE_Y, GeneXus imprime mayor parte de cada hoja - - //Ahora chequeamos que el margen asociado en el PDFReport.INI sea correcto, y si es inválido, asociamos el que sea por defecto - //if(leftMargin > this.pageSize.width || topMargin > this.pageSize.height) - //{ // Si el margen asociado es mayor que el tamaño de la página, entonces asociamos los márgenes por default - - //float leftMargin = (float) (TO_CM_SCALE * Double.valueOf(Const.DEFAULT_LEFT_MARGIN).doubleValue()); - //float topMargin = (float) (TO_CM_SCALE * Double.valueOf(Const.DEFAULT_TOP_MARGIN).doubleValue()); - - //float rightMargin = 0; - //float bottomMargin = 0; - //System.err.println("Invalid page Margin... Resetting to defaults"); - //} - - document = new Document(this.pageSize,0,0,0,0); init(); - //if(DEBUG)DEBUG_STREAM.println("GxPrintInit ---> Size:" + this.pageSize + " Orientation: " + (pageOrientation == PDFPage.PORTRAIT ? "Portrait" : "Landscape")); - return true; } @@ -1400,56 +1211,6 @@ else if (length == 15840 && width == 12240) return new com.lowagie.text.Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); } - public int getPageLines() - { - return super.getPageLines(); - } - public int getLineHeight() - { - return super.getLineHeight(); - } - public void setPageLines(int P_lines) - { - super.setPageLines(P_lines); - } - public void setLineHeight(int lineHeight) - { - super.setLineHeight(lineHeight); - } - - int M_top ; - int M_bot ; - - public int getM_top() - { - return super.getM_top(); - } - - public int getM_bot() - { - return super.getM_bot(); - } - - public void setM_top(int M_top) - { - super.setM_top(M_top); - } - - public void setM_bot(int M_bot) - { - super.setM_bot(M_bot); - } - - public void GxEndPage() - { - //if(DEBUG)DEBUG_STREAM.println("GxEndPage"); - - //if(document != null && !isPageDirty) - // document.dispose(); -// if(document == null) GxStartPage(); // Si la página esta vacú}, la agrego primero al PDF. Esto hace que haya una hoja vacú} al final, as\uFFFDEque lo saco -// document = null; // La nueva página est\uFFFDEvacú} - } - public void GxEndDocument() { if(document.getPageNumber() == 0) @@ -1542,9 +1303,6 @@ public void GxEndDocument() document.close(); if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); - //showInformation(); - //ParseINI props = pdf.getPDF().props; - //pdf.end(); try{ props.save(); } catch(IOException e) { ; } @@ -1583,167 +1341,18 @@ public void GxEndDocument() } outputStream = null; } - - public void GxEndPrinter() - { - //DEBUG.println("Processing..."); - } public void GxStartPage() { - //try - //{ - boolean ret = document.newPage(); - pages = pages +1; - //} - //catch(DocumentException de) { - // System.err.println(de.getMessage()); - //} + boolean ret = document.newPage(); + pages = pages +1; } - public void GxStartDoc() - { - //DEBUG.println("Processing..."); - } - public void GxSetDocFormat(String format) - { - //DEBUG.println("Processing..."); - } - - public void GxSetDocName(String docName) - { - super.GxSetDocName(docName); - } - - public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) - { - return super.GxPrTextInit(ouput, nxPage, nyPage, psIniFile, psForm, sPrinter, nMode, nPaperLength, nPaperWidth, nGridX, nGridY, nPageLines); - } - - public boolean GxPrnCfg( String ini ) - { - return super.GxPrnCfg(ini); - } - - public boolean GxIsAlive() - { - return super.GxIsAlive(); - } - - public boolean GxIsAliveDoc() - { - return super.GxIsAliveDoc(); - } - - public int getPage() - { - return super.getPage(); - } - - public void setPage(int page) - { - super.setPage(page); - } - - public boolean getModal() - { - return super.getModal(); - } - public void setModal(boolean modal) - { - super.setModal(modal); - } - - public void cleanup() {} - - public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) - { - } - - - /** Carga la tabla de substitutos - */ - protected void loadSubstituteTable() - { - super.loadSubstituteTable(); - } - - - /** Estos métodos no hacen nada en este contexto - */ - public void GxPrintMax() { ; } - public void GxPrintNormal() { ; } - public void GxPrintOnTop() { ; } - public void GxPrnCmd(String cmd) { ; } - - - public void showInformation() - { - } - - public static final double SCALE_FACTOR = 72; - - protected double convertScale(int value) - { - return super.convertScale(value); - } - - protected double convertScale(double value) - { - return super.convertScale(value); - } - - protected float reconvertScale(float value) - { - return super.reconvertScale(value); - } + public void GxEndPage() {} class FontProps { public int horizontal; public int vertical; } - - /** - * Helper method for toString() - * @param s source string - * @param f string to remove - * @param t string to replace f - * @return string with f replaced by t - */ - protected static String replace(String s,String f,String t) { - return GXReportPainter.replace(s,f,t); - } - - /** Contiene un state de una pagina (atributos, etc) + un String a ingresar - * La idea es que se pueda agregar Strings en cualquier página al final del proceso del PDF - *//* - class TextProperties - { - public final PDFGraphics document; - public final Font font; - public final Color foreColor; - public final Color backColor; - public final boolean fontUnderline; - public final boolean fontStrikeThru; - public final String text; - public final int left, top, right, bottom, align; - public TextProperties(PDFGraphics document, Font font, Color foreColor, Color backColor, - boolean fontUnderline, boolean fontStrikeThru, String text, int left, - int top, int right, int bottom, int align) - { - this.document = document; - this.font = font; - this.foreColor = foreColor; - this.backColor = backColor; - this.fontUnderline = fontUnderline; - this.fontStrikeThru = fontStrikeThru; - this.text = text; - this.left = left; - this.top = top; - this.right = right; - this.bottom = bottom; - this.align = align; - } - }*/ } diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index a351788c4..3e7e5e996 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -33,7 +33,6 @@ public class PDFReportpdfbox extends GXReportPainter{ //private BarcodeUtil barcode = null; por ahora no soportamos barcode private PDDocument document; private PDDocumentCatalog writer; - private static String predefinedSearchPath = ""; private PDPageContentStream template; private PDFormXObject formXObjecttemplate; private PDType0Font templateFont; @@ -41,26 +40,7 @@ public class PDFReportpdfbox extends GXReportPainter{ public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; public int runDirection = 0; - - public void setOutputStream(OutputStream outputStream) - { - super.setOutputStream(outputStream); - } - - protected static String getAcrobatLocation() throws Exception - { - return GXReportPainter.getAcrobatLocation(); - } - - public static void printReport(String pdfFilename, boolean silent) throws Exception - { - GXReportPainter.printReport(pdfFilename,silent); - } - - public static void showReport(String filename, boolean modal) throws Exception - { - GXReportPainter.showReport(filename,modal); - } + private int page; public PDFReportpdfbox(ModelContext context) { @@ -74,22 +54,6 @@ public PDFReportpdfbox(ModelContext context) } } - private static boolean firstTime = true; - - protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) - { - try { - super.loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - } catch (Exception e){ - e.printStackTrace(System.err); - } - } - - protected void loadProps() - { - super.loadProps(); - } - protected void init() { try { @@ -100,20 +64,6 @@ protected void init() } } - public void GxRVSetLanguage(String lang) {} - - public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) {} - - protected float[] parsePattern(String patternStr) - { - return super.parsePattern(patternStr); - } - - protected float [] getDashedPattern(int style) - { - return super.getDashedPattern(style); - } - private void drawRectangle(PDPageContentStream cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) @@ -288,16 +238,6 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f } } - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) - { - GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, 0, 0); - } - - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int style, int cornerRadius) - { - GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, style, style, style, style, cornerRadius, cornerRadius, cornerRadius, cornerRadius); - } - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { @@ -391,11 +331,6 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo } } - public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) - { - GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); - } - public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ @@ -438,11 +373,6 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int } } - public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom) - { - GxDrawBitMap(bitmap, left, top, right, bottom, 0); - } - public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ @@ -521,11 +451,6 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom } } - public String getSubstitute(String fontName) - { - return super.getSubstitute(fontName); - } - public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) { boolean isCJK = false; @@ -719,20 +644,6 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } } - protected String getFontLocation(String fontName) - { - return super.getFontLocation(fontName); - } - @SuppressWarnings("unchecked") - protected Hashtable getFontLocations() - { - return super.getFontLocations(); - } - - protected boolean isEmbeddedFont(String realFontName) { - return super.isEmbeddedFont(realFontName); - } - public void setAsianFont(String fontName, String style) { try @@ -803,21 +714,6 @@ public void setAsianFont(String fontName, String style) System.err.println(e.getMessage()); } } - /** - * @deprecated - */ - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align) - { - GxDrawText(sTxt, left, top, right, bottom, align, 0); - } - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat) - { - GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, 0); - } - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border) - { - GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, border, 0); - } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ @@ -1076,10 +972,6 @@ private void showTextAligned(PDType0Font font, String text, float x, float y){ } catch (Exception e) { System.err.println(e.getMessage()); } } - boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ - return super.pageHeightExceeded(bottomAux,drawingPageHeight); - } - public void GxClearAttris() {} public static final double PAGE_SCALE_Y = 20; @@ -1193,48 +1085,6 @@ else if (length == 15840 && width == 12240) return new PDRectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); } - public int getPageLines() - { - return super.getPageLines(); - } - public int getLineHeight() - { - return super.getLineHeight(); - } - public void setPageLines(int P_lines) - { - super.setPageLines(P_lines); - } - public void setLineHeight(int lineHeight) - { - super.setLineHeight(lineHeight); - } - - int M_top ; - int M_bot ; - - public int getM_top() - { - return super.getM_top(); - } - - public int getM_bot() - { - return super.getM_bot(); - } - - public void setM_top(int M_top) - { - super.setM_top(M_top); - } - - public void setM_bot(int M_bot) - { - super.setM_bot(M_bot); - } - - public void GxEndPage() {} - public void GxEndDocument() { try { @@ -1384,97 +1234,11 @@ public void GxEndDocument() e.printStackTrace(System.err); } } - - public void GxEndPrinter() {} public void GxStartPage() { document.addPage(new PDPage(this.pageSize)); pages++; } - public void GxStartDoc() {} - public void GxSetDocFormat(String format) {} - - public void GxSetDocName(String docName) - { - super.GxSetDocName(docName); - } - - public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) - { - return super.GxPrTextInit(ouput, nxPage, nyPage, psIniFile, psForm, sPrinter, nMode, nPaperLength, nPaperWidth, nGridX, nGridY, nPageLines); - } - - public boolean GxPrnCfg( String ini ) - { - return super.GxPrnCfg(ini); - } - - public boolean GxIsAlive() - { - return super.GxIsAlive(); - } - - public boolean GxIsAliveDoc() - { - return super.GxIsAliveDoc(); - } - - private int page; - public int getPage() - { - return super.getPage(); - } - - public void setPage(int page) - { - super.setPage(page); - } - - public boolean getModal() - { - return super.getModal(); - } - public void setModal(boolean modal) - { - super.setModal(modal); - } - - public void cleanup() {} - - public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) {} - - protected void loadSubstituteTable() - { - super.loadSubstituteTable(); - } - - public void GxPrintMax() { ; } - public void GxPrintNormal() { ; } - public void GxPrintOnTop() { ; } - public void GxPrnCmd(String cmd) { ; } - - public void showInformation() {} - - public static final double SCALE_FACTOR = 72; - - protected double convertScale(int value) - { - return super.convertScale(value); - } - - protected double convertScale(double value) - { - return super.convertScale(value); - } - - protected float reconvertScale(float value) - { - return super.reconvertScale(value); - } - - protected static String replace(String s,String f,String t) { - return GXReportPainter.replace(s,f,t); - } - + public void GxEndPage() {} } \ No newline at end of file From af3d99bc695a6f4f82b8ddc679d0830b3beee037 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Thu, 30 Mar 2023 13:56:37 -0300 Subject: [PATCH 13/32] Fix all use of PDRectangles --- .../com/genexus/reports/PDFReportItext.java | 5 +- .../com/genexus/reports/PDFReportpdfbox.java | 86 +++++++++++-------- 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index 5d5572e3b..fbf5eac9e 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -709,7 +709,6 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in bottom = top + (int)reconvertScale(lineHeight); else if (valign == VerticalAlign.BOTTOM.value()) top = bottom - (int)reconvertScale(lineHeight); - //if valign == middle, no se cambia ni top ni bottom } float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; @@ -942,7 +941,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, this.pageSize.getTop() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; - case 2: // Right Alignment + case 2: // Right Alignment underline = new com.lowagie.text.Rectangle( rightAux + leftMargin - rectangleWidth , this.pageSize.getTop() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, rightAux + leftMargin, @@ -952,7 +951,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) underline = new com.lowagie.text.Rectangle( leftAux + leftMargin , this.pageSize.getTop() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, leftAux + leftMargin + rectangleWidth, - this.pageSize.getTop() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + this.pageSize.getTop() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } underline.setBackgroundColor(foreColor); diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 3e7e5e996..b329fb056 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -737,8 +737,8 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in cb.setNonStrokingColor(foreColor); int arabicOptions = 0; float captionHeight = baseFont.getFontMatrix().transformPoint(0, font.getFontDescriptor().getCapHeight()).y * fontSize; - float rectangleWidth = font.getStringWidth(sTxt); - float lineHeight = font.getFontDescriptor().getFontBoundingBox().getUpperRightY() - font.getFontDescriptor().getFontBoundingBox().getLowerLeftX(); + float rectangleWidth = baseFont.getStringWidth(sTxt) / 1000 * fontSize; + float lineHeight = (baseFont.getFontDescriptor().getFontBoundingBox().getUpperRightY() - baseFont.getFontDescriptor().getFontBoundingBox().getLowerLeftY())/ 1000 * fontSize; float textBlockHeight = (float)convertScale(bottom-top); int linesCount = (int)(textBlockHeight/lineHeight); int bottomOri = bottom; @@ -777,17 +777,26 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) if(backFill) { - PDRectangle rectangle = new PDRectangle(0,0); + PDRectangle rectangle = new PDRectangle(); switch(alignment) { case 1: // Center Alignment - rectangle = new PDRectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); + rectangle.setLowerLeftX((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2); + rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin); + rectangle.setUpperRightX((leftAux + rightAux)/2 + leftMargin + rectangleWidth/2); + rectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; case 2: // Right Alignment - rectangle = new PDRectangle(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , rightAux + leftMargin, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); + rectangle.setLowerLeftX(rightAux + leftMargin - rectangleWidth); + rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin); + rectangle.setUpperRightX(rightAux + leftMargin); + rectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; case 0: // Left Alignment - rectangle = new PDRectangle(leftAux + leftMargin, (float)this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin , leftAux + leftMargin + rectangleWidth, (float)this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); + rectangle.setLowerLeftX(leftAux + leftMargin); + rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin); + rectangle.setUpperRightX(leftAux + leftMargin + rectangleWidth); + rectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; } PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); @@ -803,28 +812,27 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) if (fontUnderline) { - underline = new PDRectangle(0,0); + underline = new PDRectangle(); switch(alignment) { case 1: // Center Alignment - underline = new PDRectangle( - (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, - (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + underline.setLowerLeftX((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2); + underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation); + underline.setUpperRightX((leftAux + rightAux)/2 + leftMargin + rectangleWidth/2); + underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; case 2: // Right Alignment - underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, - rightAux + leftMargin, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + underline.setLowerLeftX(rightAux + leftMargin - rectangleWidth); + underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation); + underline.setUpperRightX(rightAux + leftMargin); + underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; case 0: // Left Alignment - underline = new PDRectangle( leftAux + leftMargin , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation, - leftAux + leftMargin + rectangleWidth, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); + underline.setLowerLeftX(leftAux + leftMargin); + underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation); + underline.setUpperRightX(leftAux + leftMargin + rectangleWidth); + underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; } PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); @@ -836,34 +844,33 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) if (fontStrikethru) { - underline = new PDRectangle(0,0); + underline = new PDRectangle(); float strikethruSeparation = lineHeight / 2; switch(alignment) { case 1: // Center Alignment - underline = new PDRectangle( - (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, - (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + underline.setLowerLeftX((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2); + underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation); + underline.setUpperRightX((leftAux + rightAux)/2 + leftMargin + rectangleWidth/2); + underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; case 2: // Right Alignment - underline = new PDRectangle( rightAux + leftMargin - rectangleWidth , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, - rightAux + leftMargin, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + underline.setLowerLeftX(rightAux + leftMargin - rectangleWidth); + underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation); + underline.setUpperRightX(rightAux + leftMargin); + underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; case 0: // Left Alignment - underline = new PDRectangle( leftAux + leftMargin , - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation, - leftAux + leftMargin + rectangleWidth, - this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); + underline.setLowerLeftX(leftAux + leftMargin); + underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation); + underline.setUpperRightX(leftAux + leftMargin + rectangleWidth); + underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); contentStream.setNonStrokingColor(foreColor); - contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); + contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY() - strikethruSeparation * 1/3, underline.getWidth(), underline.getHeight()); contentStream.fill(); contentStream.close(); } @@ -914,8 +921,13 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } annotation.setDefaultAppearance("/" + font.getName() + " " + fontSize + " Tf " + leading + " TL 0 g " + alignmentString + " <>BDC q BT /F1 " + fontSize + " Tf " + leading + " TL Tj ET Q EMC"); annotation.setContents(sTxt); - annotation.setRectangle(new PDRectangle(leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin, - rightAux + leftMargin, this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin)); + + PDRectangle annotationRectangle = new PDRectangle(); + annotationRectangle.setLowerLeftX(leftAux + leftMargin); + annotationRectangle.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin); + annotationRectangle.setUpperRightX(rightAux + leftMargin); + annotationRectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin); + annotation.setRectangle(annotationRectangle); document.getPage(page).getAnnotations().add(annotation); PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); contentStream.beginText(); From 0510343d7dff6f435baa77050c0b5052d3538d0e Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Mon, 3 Apr 2023 13:43:53 -0300 Subject: [PATCH 14/32] bold and italic text support --- .../com/genexus/reports/PDFReportpdfbox.java | 78 +++++++++++++++---- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index b329fb056..5a41b3618 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -1,9 +1,9 @@ package com.genexus.reports; import java.awt.Color; +import java.awt.geom.AffineTransform; import java.io.*; import java.net.URL; -import java.util.*; import java.util.concurrent.ConcurrentHashMap; import com.genexus.CommonUtil; @@ -21,6 +21,7 @@ import org.apache.pdfbox.pdmodel.font.*; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText; import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences; @@ -615,6 +616,7 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo COSDictionary dict = new COSDictionary(); dict.setItem(COSName.TYPE, COSName.FONT); dict.setItem(COSName.SUBTYPE, COSName.TYPE0); + dict.setItem(COSName.FONT, COSName.HELV); dict.setItem(COSName.BASE_FONT, COSName.HELV); dict.setItem(COSName.ENCODING, COSName.WIN_ANSI_ENCODING); dict.setItem(COSName.DESCENDANT_FONTS, new COSArray()); @@ -631,10 +633,27 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } else { - baseFont = PDType0Font.load(document,new File(fontPath + style)); - COSDictionary dict = baseFont.getCOSObject(); - dict.setItem(COSName.ENCODING, COSName.IDENTITY_H); - dict.setItem(COSName.FONT_FILE2, COSNull.NULL); + PDType0Font auxFont = PDType0Font.load(document,new File(fontPath)); + COSDictionary dict = new COSDictionary(auxFont.getCOSObject()); + baseFont = new PDType0Font(dict); + switch (style) + { + case ",Bold": + baseFont.getCOSObject().setInt(COSName.FONT_WEIGHT, 700); + break; + case ",Italic": + baseFont.getFontMatrix().setValue(0,1,0.2f); + baseFont.getFontDescriptor().setItalic(true); + break; + case ",BoldItalic": + baseFont.getCOSObject().setInt(COSName.FONT_WEIGHT, 700); + baseFont.getFontMatrix().setValue(0, 1, 0.2f); + baseFont.getFontDescriptor().setItalic(true); + break; + default: break; + } + baseFont.getCOSObject().setItem(COSName.ENCODING, COSName.IDENTITY_H); + baseFont.getCOSObject().setItem(COSName.FONT_FILE2, COSNull.NULL); } } } @@ -930,9 +949,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) annotation.setRectangle(annotationRectangle); document.getPage(page).getAnnotations().add(annotation); PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); - contentStream.beginText(); - contentStream.showText(annotation.getContents()); - contentStream.endText(); + resolveTextStyling(contentStream,annotation.getContents(),leftAux + leftMargin,this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin); contentStream.close(); } else @@ -968,18 +985,49 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) } } + private void resolveTextStyling(PDPageContentStream contentStream, String text, float x, float y){ + try { + if (this.fontBold && this.fontItalic){ + contentStream.setRenderingMode(RenderingMode.FILL_STROKE); + Matrix tiltMatrix = new Matrix(); + tiltMatrix.setValue(1, 0, 0.5f); + contentStream.setTextMatrix(tiltMatrix); + + contentStream.beginText(); + contentStream.moveTextPositionByAmount(-x + 104, y); + contentStream.showText(text); + contentStream.endText(); + } else if (this.fontBold && !this.fontItalic){ + contentStream.setRenderingMode(RenderingMode.FILL_STROKE); + + contentStream.beginText(); + contentStream.moveTextPositionByAmount(x, y); + contentStream.showText(text); + contentStream.endText(); + } else if (!this.fontBold && this.fontItalic){ + Matrix tiltMatrix = new Matrix(); + tiltMatrix.setValue(1, 0, 0.2f); + contentStream.transform(tiltMatrix); + + contentStream.beginText(); + contentStream.moveTextPositionByAmount(-x + 104, y); + contentStream.showText(text); + contentStream.endText(); + } else { + contentStream.beginText(); + contentStream.moveTextPositionByAmount(x, y); + contentStream.showText(text); + contentStream.endText(); + } + } catch (Exception e) {} + } + private void showTextAligned(PDType0Font font, String text, float x, float y){ try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page), PDPageContentStream.AppendMode.APPEND, false, false)){ contentStream.saveGraphicsState(); contentStream.setFont(font, fontSize); contentStream.setLeading(2); - contentStream.beginText(); - contentStream.moveTextPositionByAmount(x, y); - for (String line : text.split("\n")) { - contentStream.newLine(); - contentStream.showText(line); - } - contentStream.endText(); + resolveTextStyling(contentStream,text, x, y); contentStream.restoreGraphicsState(); } catch (Exception e) { System.err.println(e.getMessage()); } } From b32c7dc2dd652e217636422c4944303b224c133f Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Mon, 10 Apr 2023 12:05:58 -0300 Subject: [PATCH 15/32] Fix pagination and report library support --- .../com/genexus/reports/PDFReportpdfbox.java | 54 ++++++------- .../com/genexus/webpanels/GXWebReport.java | 80 ++++++++++++------- 2 files changed, 77 insertions(+), 57 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java index 5a41b3618..0b9d925e7 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java @@ -1,7 +1,6 @@ package com.genexus.reports; import java.awt.Color; -import java.awt.geom.AffineTransform; import java.io.*; import java.net.URL; import java.util.concurrent.ConcurrentHashMap; @@ -242,7 +241,7 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ float penAux = (float)convertScale(pen); float rightAux = (float)convertScale(right); @@ -334,7 +333,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ float widthAux = (float)convertScale(width); float rightAux = (float)convertScale(right); @@ -376,7 +375,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ PDImageXObject image; try { @@ -735,7 +734,7 @@ public void setAsianFont(String fontName, String style) } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { - try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false)){ + try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ boolean printRectangle = false; if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) printRectangle = true; @@ -818,7 +817,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) rectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin -bottomMargin); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false); contentStream.setNonStrokingColor(backColor); contentStream.addRect(rectangle.getLowerLeftX(), rectangle.getLowerLeftY(),rectangle.getWidth(), rectangle.getHeight()); contentStream.fill(); @@ -854,8 +853,8 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); - contentStream.setNonStrokingColor(foreColor); // set background color to yellow + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false); + contentStream.setNonStrokingColor(foreColor); contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY(),underline.getWidth(), underline.getHeight()); contentStream.fill(); contentStream.close(); @@ -887,7 +886,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) underline.setUpperRightY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineHeight + strikethruSeparation); break; } - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false); contentStream.setNonStrokingColor(foreColor); contentStream.addRect(underline.getLowerLeftX(), underline.getLowerLeftY() - strikethruSeparation * 1/3, underline.getWidth(), underline.getHeight()); contentStream.fill(); @@ -905,7 +904,7 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) templateCreated = true; } PDFormXObject form = new PDFormXObject(document); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false); contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); contentStream.drawForm(form); contentStream.close(); @@ -947,8 +946,8 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) annotationRectangle.setUpperRightX(rightAux + leftMargin); annotationRectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin); annotation.setRectangle(annotationRectangle); - document.getPage(page).getAnnotations().add(annotation); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page),PDPageContentStream.AppendMode.APPEND,false); + document.getPage(page - 1).getAnnotations().add(annotation); + PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false); resolveTextStyling(contentStream,annotation.getContents(),leftAux + leftMargin,this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin); contentStream.close(); } @@ -988,31 +987,31 @@ else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) private void resolveTextStyling(PDPageContentStream contentStream, String text, float x, float y){ try { if (this.fontBold && this.fontItalic){ - contentStream.setRenderingMode(RenderingMode.FILL_STROKE); - Matrix tiltMatrix = new Matrix(); - tiltMatrix.setValue(1, 0, 0.5f); - contentStream.setTextMatrix(tiltMatrix); - contentStream.beginText(); - contentStream.moveTextPositionByAmount(-x + 104, y); + contentStream.moveTextPositionByAmount(x, y); + //contentStream.setTextMatrix(1, 0, .2f, 1, 7, 5); + //contentStream.setTextMatrix(1, 0, .2f, 1, 0, 0); + contentStream.setTextMatrix(1, Math.tan(Math.toRadians(10)), 0, 1, 0, 0); + contentStream.appendRawCommands("2 Tr\n"); contentStream.showText(text); + contentStream.appendRawCommands("0 Tr\n"); contentStream.endText(); } else if (this.fontBold && !this.fontItalic){ - contentStream.setRenderingMode(RenderingMode.FILL_STROKE); - contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); + contentStream.appendRawCommands("2 Tr\n"); contentStream.showText(text); + contentStream.appendRawCommands("0 Tr\n"); contentStream.endText(); } else if (!this.fontBold && this.fontItalic){ - Matrix tiltMatrix = new Matrix(); - tiltMatrix.setValue(1, 0, 0.2f); - contentStream.transform(tiltMatrix); - contentStream.beginText(); - contentStream.moveTextPositionByAmount(-x + 104, y); + contentStream.moveTextPositionByAmount(x, y); + //contentStream.setTextMatrix(1, 0, .2f, 1, 7, 5); + //contentStream.setTextMatrix(1, 0, .2f, 1, 0, 0); + contentStream.setTextMatrix(1, Math.tan(Math.toRadians(10)), 0, 1, 0, 0); contentStream.showText(text); contentStream.endText(); + contentStream.restoreGraphicsState(); } else { contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); @@ -1023,7 +1022,7 @@ private void resolveTextStyling(PDPageContentStream contentStream, String text, } private void showTextAligned(PDType0Font font, String text, float x, float y){ - try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page), PDPageContentStream.AppendMode.APPEND, false, false)){ + try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1), PDPageContentStream.AppendMode.APPEND, false, false)){ contentStream.saveGraphicsState(); contentStream.setFont(font, fontSize); contentStream.setLeading(2); @@ -1297,7 +1296,8 @@ public void GxEndDocument() public void GxStartPage() { document.addPage(new PDPage(this.pageSize)); - pages++; + pages = pages + 1; + page = page + 1; } public void GxEndPage() {} diff --git a/java/src/main/java/com/genexus/webpanels/GXWebReport.java b/java/src/main/java/com/genexus/webpanels/GXWebReport.java index 1978f2b51..6d77bea37 100644 --- a/java/src/main/java/com/genexus/webpanels/GXWebReport.java +++ b/java/src/main/java/com/genexus/webpanels/GXWebReport.java @@ -4,9 +4,8 @@ import com.genexus.ProcessInterruptedException; import com.genexus.db.UserInformation; import com.genexus.internet.HttpContext; -import com.genexus.reports.GXReportMetadata; -import com.genexus.reports.IReportHandler; -import com.genexus.reports.PDFReportItext; +import com.genexus.reports.*; +import com.genexus.util.IniFile; public abstract class GXWebReport extends GXWebProcedure { @@ -23,7 +22,7 @@ public abstract class GXWebReport extends GXWebProcedure protected int gxXPage; protected int gxYPage; protected int Gx_page; - protected String Gx_out = ""; // Esto est� asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask. + protected String Gx_out = ""; // Esto esto asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask. protected String filename; protected String filetype; @@ -34,24 +33,32 @@ public GXWebReport(HttpContext httpContext) protected void initState(ModelContext context, UserInformation ui) { - super.initState(context, ui); - - httpContext.setBuffered(true); - httpContext.setBinary(true); - - reportHandler = new PDFReportItext(context); - - initValues(); + try { + String filePath = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + "\\WEB-INF\\classes\\com\\" + com.genexus.ModelContext.getModelContext().getHttpContext().getTheme().toLowerCase() + "\\client.cfg"; + IniFile iniFile = new IniFile(filePath); + String implementation = iniFile.getProperty("Client", "PDF_RPT_LIBRARY", ""); + super.initState(context, ui); + httpContext.setBuffered(true); + httpContext.setBinary(true); + if (implementation.equals("ITEXT")) + reportHandler = new PDFReportItext(context); + else if (implementation.equals("PDFBOX")) + reportHandler = new PDFReportpdfbox(context); + initValues(); + } catch (Exception e){ + e.printStackTrace(System.err); + } } protected void preExecute() { - httpContext.setContentType("application/pdf"); - httpContext.setStream(); - - // Tiene que ir despues del setStream porque sino el getOutputStream apunta - // a otro lado. - ((PDFReportItext) reportHandler).setOutputStream(httpContext.getOutputStream()); + try { + httpContext.setContentType("application/pdf"); + httpContext.setStream(); + ((GXReportPainter) reportHandler).setOutputStream(httpContext.getOutputStream()); + } catch (Exception e){ + e.printStackTrace(System.err); + } } protected void setOutputFileName(String outputFileName){ @@ -103,23 +110,32 @@ protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, Strin protected boolean initPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - int x[] = {gxXPage}; - int y[] = {gxYPage}; - setResponseOuputFileName(); + try { + int x[] = {gxXPage}; + int y[] = {gxYPage}; + setResponseOuputFileName(); - getPrinter().GxRVSetLanguage(localUtil._language); - boolean ret = getPrinter().GxPrintInit(output, x, y, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + getPrinter().GxRVSetLanguage(localUtil._language); + boolean ret = getPrinter().GxPrintInit(output, x, y, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - this.gxXPage = x[0]; - this.gxYPage = y[0]; + this.gxXPage = x[0]; + this.gxYPage = y[0]; - return ret; + return ret; + } catch (Exception e){ + e.printStackTrace(System.err); + return false; + } } private void setResponseOuputFileName(){ - String outputFileName = filename!=null ? filename : getClass().getSimpleName(); - String outputFileType = filetype!=null ? "." + filetype.toLowerCase(): ".pdf"; - httpContext.getResponse().addHeader("content-disposition", "inline; filename=" + outputFileName + outputFileType); + try { + String outputFileName = filename!=null ? filename : getClass().getSimpleName(); + String outputFileType = filetype!=null ? "." + filetype.toLowerCase(): ".pdf"; + httpContext.getResponse().addHeader("content-disposition", "inline; filename=" + outputFileName + outputFileType); + } catch (Exception e) { + e.printStackTrace(System.err); + } } protected void endPrinter() @@ -181,6 +197,10 @@ protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, protected void cleanup( ) { - super.cleanup(); + try { + super.cleanup(); + } catch (Exception e) { + e.printStackTrace(System.err); + } } } From 1f99b11800fb33e8932814c65fd4e93fe6930731 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Tue, 11 Apr 2023 11:00:10 -0300 Subject: [PATCH 16/32] Minor casing, naming and catching fixes --- .../java/com/genexus/ClientPreferences.java | 4 ++ .../common/interfaces/IClientPreferences.java | 2 + .../java/com/genexus/ClientPreferences.java | 4 ++ ...rtPainter.java => GXReportPDFCommons.java} | 4 +- .../com/genexus/reports/PDFReportItext.java | 3 +- ...Reportpdfbox.java => PDFReportPDFBox.java} | 9 ++- .../com/genexus/webpanels/GXWebReport.java | 72 +++++++------------ 7 files changed, 41 insertions(+), 57 deletions(-) rename java/src/main/java/com/genexus/reports/{GXReportPainter.java => GXReportPDFCommons.java} (99%) rename java/src/main/java/com/genexus/reports/{PDFReportpdfbox.java => PDFReportPDFBox.java} (99%) diff --git a/android/src/main/java/com/genexus/ClientPreferences.java b/android/src/main/java/com/genexus/ClientPreferences.java index 5d6f7f6dc..23a1ab5fb 100644 --- a/android/src/main/java/com/genexus/ClientPreferences.java +++ b/android/src/main/java/com/genexus/ClientPreferences.java @@ -529,4 +529,8 @@ public boolean getJDBC_LOGEnabled() { return iniFile.getProperty(name, "JDBCLogEnabled", "0").equals("1"); } + public String getPDF_RPT_LIBRARY(){ + return iniFile.getProperty(defaultSection, "PDF_RPT_LIBRARY", "ITEXT"); + } + } diff --git a/common/src/main/java/com/genexus/common/interfaces/IClientPreferences.java b/common/src/main/java/com/genexus/common/interfaces/IClientPreferences.java index b8b05394b..8556582dc 100644 --- a/common/src/main/java/com/genexus/common/interfaces/IClientPreferences.java +++ b/common/src/main/java/com/genexus/common/interfaces/IClientPreferences.java @@ -53,4 +53,6 @@ public interface IClientPreferences { String getPRINT_LAYOUT_METADATA_DIR(); boolean getEXPOSE_METADATA(); + + String getPDF_RPT_LIBRARY(); } diff --git a/java/src/main/java/com/genexus/ClientPreferences.java b/java/src/main/java/com/genexus/ClientPreferences.java index 064b9f3fa..1db5b764e 100644 --- a/java/src/main/java/com/genexus/ClientPreferences.java +++ b/java/src/main/java/com/genexus/ClientPreferences.java @@ -534,4 +534,8 @@ public int getHttpBufferSize() } return HTTP_BUFFER_SIZE; } + + public String getPDF_RPT_LIBRARY(){ + return iniFile.getProperty(defaultSection, "PDF_RPT_LIBRARY", "ITEXT"); + } } diff --git a/java/src/main/java/com/genexus/reports/GXReportPainter.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java similarity index 99% rename from java/src/main/java/com/genexus/reports/GXReportPainter.java rename to java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 22fbae2fd..831d9658f 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPainter.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -58,7 +58,7 @@ import java.io.*; import java.util.*; -public abstract class GXReportPainter implements IReportHandler{ +public abstract class GXReportPDFCommons implements IReportHandler{ protected int lineHeight, pageLines; protected int pageOrientation; protected boolean fontUnderline; @@ -231,7 +231,7 @@ public static void showReport(String filename, boolean modal) throws Exception Runtime.getRuntime().exec(new String[] { acrobatLocation, filename}); } } - public GXReportPainter(ModelContext context) + public GXReportPDFCommons(ModelContext context) { stringTotalPages = new Vector(); httpContext = (HttpContext) context.getHttpContext(); diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index fbf5eac9e..d2fdb499c 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -4,7 +4,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.io.StringReader; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -40,7 +39,7 @@ import com.genexus.reports.fonts.PDFFontDescriptor; import com.genexus.reports.fonts.Type1FontMetrics; -public class PDFReportItext extends GXReportPainter +public class PDFReportItext extends GXReportPDFCommons { private com.lowagie.text.Rectangle pageSize; // Contiene las dimensiones de la página private Font font; diff --git a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java similarity index 99% rename from java/src/main/java/com/genexus/reports/PDFReportpdfbox.java rename to java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 0b9d925e7..56014cd46 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportpdfbox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -20,13 +20,12 @@ import org.apache.pdfbox.pdmodel.font.*; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; -import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText; import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences; import org.apache.pdfbox.util.Matrix; -public class PDFReportpdfbox extends GXReportPainter{ +public class PDFReportPDFBox extends GXReportPDFCommons{ private PDRectangle pageSize; private PDType1Font font; private PDType0Font baseFont; @@ -42,7 +41,7 @@ public class PDFReportpdfbox extends GXReportPainter{ public int runDirection = 0; private int page; - public PDFReportpdfbox(ModelContext context) + public PDFReportPDFBox(ModelContext context) { super(context); try { @@ -764,9 +763,9 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) { - if (valign == PDFReportpdfbox.VerticalAlign.TOP.value()) + if (valign == PDFReportPDFBox.VerticalAlign.TOP.value()) bottom = top + (int)reconvertScale(lineHeight); - else if (valign == PDFReportpdfbox.VerticalAlign.BOTTOM.value()) + else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) top = bottom - (int)reconvertScale(lineHeight); } diff --git a/java/src/main/java/com/genexus/webpanels/GXWebReport.java b/java/src/main/java/com/genexus/webpanels/GXWebReport.java index 6d77bea37..0785e9714 100644 --- a/java/src/main/java/com/genexus/webpanels/GXWebReport.java +++ b/java/src/main/java/com/genexus/webpanels/GXWebReport.java @@ -5,7 +5,6 @@ import com.genexus.db.UserInformation; import com.genexus.internet.HttpContext; import com.genexus.reports.*; -import com.genexus.util.IniFile; public abstract class GXWebReport extends GXWebProcedure { @@ -33,32 +32,22 @@ public GXWebReport(HttpContext httpContext) protected void initState(ModelContext context, UserInformation ui) { - try { - String filePath = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + "\\WEB-INF\\classes\\com\\" + com.genexus.ModelContext.getModelContext().getHttpContext().getTheme().toLowerCase() + "\\client.cfg"; - IniFile iniFile = new IniFile(filePath); - String implementation = iniFile.getProperty("Client", "PDF_RPT_LIBRARY", ""); - super.initState(context, ui); - httpContext.setBuffered(true); - httpContext.setBinary(true); - if (implementation.equals("ITEXT")) - reportHandler = new PDFReportItext(context); - else if (implementation.equals("PDFBOX")) - reportHandler = new PDFReportpdfbox(context); - initValues(); - } catch (Exception e){ - e.printStackTrace(System.err); - } + String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); + super.initState(context, ui); + httpContext.setBuffered(true); + httpContext.setBinary(true); + if (implementation.equals("PDFBOX")) + reportHandler = new PDFReportPDFBox(context); + else + reportHandler = new PDFReportItext(context); + initValues(); } protected void preExecute() { - try { - httpContext.setContentType("application/pdf"); - httpContext.setStream(); - ((GXReportPainter) reportHandler).setOutputStream(httpContext.getOutputStream()); - } catch (Exception e){ - e.printStackTrace(System.err); - } + httpContext.setContentType("application/pdf"); + httpContext.setStream(); + ((GXReportPDFCommons) reportHandler).setOutputStream(httpContext.getOutputStream()); } protected void setOutputFileName(String outputFileName){ @@ -110,32 +99,23 @@ protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, Strin protected boolean initPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - try { - int x[] = {gxXPage}; - int y[] = {gxYPage}; - setResponseOuputFileName(); + int x[] = {gxXPage}; + int y[] = {gxYPage}; + setResponseOuputFileName(); - getPrinter().GxRVSetLanguage(localUtil._language); - boolean ret = getPrinter().GxPrintInit(output, x, y, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + getPrinter().GxRVSetLanguage(localUtil._language); + boolean ret = getPrinter().GxPrintInit(output, x, y, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - this.gxXPage = x[0]; - this.gxYPage = y[0]; + this.gxXPage = x[0]; + this.gxYPage = y[0]; - return ret; - } catch (Exception e){ - e.printStackTrace(System.err); - return false; - } + return ret; } private void setResponseOuputFileName(){ - try { - String outputFileName = filename!=null ? filename : getClass().getSimpleName(); - String outputFileType = filetype!=null ? "." + filetype.toLowerCase(): ".pdf"; - httpContext.getResponse().addHeader("content-disposition", "inline; filename=" + outputFileName + outputFileType); - } catch (Exception e) { - e.printStackTrace(System.err); - } + String outputFileName = filename!=null ? filename : getClass().getSimpleName(); + String outputFileType = filetype!=null ? "." + filetype.toLowerCase(): ".pdf"; + httpContext.getResponse().addHeader("content-disposition", "inline; filename=" + outputFileName + outputFileType); } protected void endPrinter() @@ -197,10 +177,6 @@ protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, protected void cleanup( ) { - try { - super.cleanup(); - } catch (Exception e) { - e.printStackTrace(System.err); - } + super.cleanup(); } } From d70721288dd45b98fca901084adf6b80d322f171 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Thu, 20 Apr 2023 12:34:42 -0300 Subject: [PATCH 17/32] code styling, text positioning, text wrapping and text coloring fixes --- .../genexus/reports/GXReportPDFCommons.java | 234 +++----- .../com/genexus/reports/PDFReportItext.java | 456 +++++---------- .../com/genexus/reports/PDFReportPDFBox.java | 540 +++++++----------- 3 files changed, 445 insertions(+), 785 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 831d9658f..05bb606d2 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -119,8 +119,7 @@ protected enum VerticalAlign{ MIDDLE(1), BOTTOM(2); private int intValue; - VerticalAlign(int val) - { + VerticalAlign(int val) { this.intValue=val; } public int value(){ @@ -132,32 +131,27 @@ public int value(){ /** Setea el OutputStream a utilizar * @param outputStream Stream a utilizar */ - public void setOutputStream(OutputStream outputStream) - { + public void setOutputStream(OutputStream outputStream) { this.outputStream = outputStream; } /** Busca la ubicación del Acrobat. Si no la encuentra tira una excepción */ - protected static String getAcrobatLocation() throws Exception - { + protected static String getAcrobatLocation() throws Exception { ParseINI props; - try - { + try { props = new ParseINI(Const.INI_FILE); if(new File(Const.INI_FILE).length() == 0) new File(Const.INI_FILE).delete(); } - catch(IOException e) - { + catch(IOException e) { props = new ParseINI(); } // Primero debo obtener la ubicación + ejecutable del Acrobat String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property if(acrobatLocation == null) { - if(NativeFunctions.isUnix()) - { // Si estoy en Unix no puedo ir a buscar el registry ;) + if(NativeFunctions.isUnix()) { // Si estoy en Unix no puedo ir a buscar el registry ;) throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); } } @@ -171,22 +165,18 @@ protected static String getAcrobatLocation() throws Exception * @param silent Booleano que indica si se va a imprimir sin diálogo * @exception Exception si no se puede realizar la operación */ - public static void printReport(String pdfFilename, boolean silent) throws Exception - { - if(NativeFunctions.isWindows()) - { // En Windows obtenemos el full path + public static void printReport(String pdfFilename, boolean silent) throws Exception { + if(NativeFunctions.isWindows()) { // En Windows obtenemos el full path // En Linux esto no anda bien pdfFilename = "\"" + new File(pdfFilename).getAbsolutePath() + "\""; } String [] cmd = {}; String acrobatLocation = null; - try - { + try { // Primero debo obtener la ubicación + ejecutable del Acrobat acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) - { + }catch(Exception acrobatNotFound) { throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); } @@ -205,59 +195,48 @@ public static void printReport(String pdfFilename, boolean silent) throws Except * @param modal indica si el PDF se va a mostrar en diálogo modal * @exception Exception no se puede encontrar el Acrobat */ - public static void showReport(String filename, boolean modal) throws Exception - { - if(NativeFunctions.isWindows()) - { // En Windows obtenemos el full path + public static void showReport(String filename, boolean modal) throws Exception { + if(NativeFunctions.isWindows()) { // En Windows obtenemos el full path // En Linux esto no anda bien filename = "\"" + new File(filename).getAbsolutePath() + "\""; } String acrobatLocation; - try - { + try { // Primero debo obtener la ubicación + ejecutable del Acrobat acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) - { + }catch(Exception acrobatNotFound) { throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); } - if(modal) - { + if(modal) { nativeCode.executeModal(acrobatLocation + " " + filename, true); } - else - { + else { Runtime.getRuntime().exec(new String[] { acrobatLocation, filename}); } } - public GXReportPDFCommons(ModelContext context) - { + public GXReportPDFCommons(ModelContext context) { stringTotalPages = new Vector(); httpContext = (HttpContext) context.getHttpContext(); - if(defaultRelativePrepend == null) - { + if(defaultRelativePrepend == null) { defaultRelativePrepend = httpContext.getDefaultPath(); if(defaultRelativePrepend == null || defaultRelativePrepend.trim().equals("")) defaultRelativePrepend = ""; else defaultRelativePrepend = defaultRelativePrepend.replace(alternateSeparator, File.separatorChar) + File.separatorChar; defaultRelativePrependINI = defaultRelativePrepend; - if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) - { + if(new File(defaultRelativePrepend + Const.WEB_INF).isDirectory()) { configurationFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_FILE; // Esto es para que en aplicaciones web el PDFReport.INI no quede visible en el server configurationTemplateFile = defaultRelativePrepend + Const.WEB_INF + File.separatorChar + Const.INI_TEMPLATE_FILE; } - else - { + else { configurationFile = defaultRelativePrepend + Const.INI_FILE; configurationTemplateFile = defaultRelativePrepend + Const.INI_TEMPLATE_FILE; } webAppDir = defaultRelativePrepend; - if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) - { + if(httpContext instanceof HttpContextWeb || !httpContext.getDefaultPath().isEmpty()) { // @cambio: 23/07/03 // Para los reportes en el web, debemos tener en cuenta la preference 'Static Content Base URL' del modelo // Pero SOLO la tenemos en cuenta si es un directorio relativo @@ -272,21 +251,16 @@ public GXReportPDFCommons(ModelContext context) // (ese es el caso en el cual el getDefaultPath no es Empty) String staticContentBase = httpContext.getStaticContentBase(); - if(staticContentBase != null) - { + if(staticContentBase != null) { staticContentBase = staticContentBase.trim(); - if(staticContentBase.indexOf(':') == -1) - { // Si la staticContentBase es una ruta relativa + if(staticContentBase.indexOf(':') == -1) { // Si la staticContentBase es una ruta relativa staticContentBase = staticContentBase.replace(alternateSeparator, File.separatorChar); - if(staticContentBase.startsWith(File.separator)) - { + if(staticContentBase.startsWith(File.separator)) { staticContentBase = staticContentBase.substring(1); } - if(!staticContentBase.equals("")) - { + if(!staticContentBase.equals("")) { defaultRelativePrepend += staticContentBase; - if(!defaultRelativePrepend.endsWith(File.separator)) - { + if(!defaultRelativePrepend.endsWith(File.separator)) { defaultRelativePrepend += File.separator; } } @@ -294,8 +268,7 @@ public GXReportPDFCommons(ModelContext context) } } } - if (firstTime) - { + if (firstTime) { loadProps(); firstTime = false; } @@ -303,17 +276,14 @@ public GXReportPDFCommons(ModelContext context) protected void loadPrinterSettingsProps(String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) - { + if(new File(defaultRelativePrependINI + Const.WEB_INF).isDirectory()) { iniFile = defaultRelativePrependINI + Const.WEB_INF + File.separatorChar + iniFile; } - else - { + else { iniFile = defaultRelativePrependINI + iniFile; } - try - { + try { this.form = form; printerSettings = new ParseINI(iniFile); } @@ -335,8 +305,7 @@ protected void loadPrinterSettingsProps(String iniFile, String form, String prin printerSettings.setupProperty(form, Const.DUPLEX, duplex+ ""); } - protected void loadProps() - { + protected void loadProps() { try{ props = new ParseINI(configurationFile, configurationTemplateFile); }catch(IOException e){ props = new ParseINI(); } @@ -367,13 +336,11 @@ protected void loadProps() loadSubstituteTable(); // Cargo la tabla de substitutos de fonts - if(props.getBooleanGeneralProperty("DEBUG", false)) - { + if(props.getBooleanGeneralProperty("DEBUG", false)) { DEBUG = true; DEBUG_STREAM = System.out; } - else - { + else { DEBUG = false; DEBUG_STREAM = new PrintStream(new com.genexus.util.NullOutputStream()); } @@ -382,8 +349,7 @@ protected void loadProps() System.getProperty("com.ms.windir", "c:\\windows") + "\\fonts"}); } - public static final void addPredefinedSearchPaths(String [] predefinedPaths) - { + public static final void addPredefinedSearchPaths(String [] predefinedPaths) { String predefinedPath = ""; for(int i = 0; i < predefinedPaths.length; i++) predefinedPath += predefinedPaths[i] + ";"; @@ -401,18 +367,14 @@ public void GxRVSetLanguage(String lang) {} public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) {} - protected float[] parsePattern(String patternStr) - { - if (patternStr!=null) - { + protected float[] parsePattern(String patternStr) { + if (patternStr!=null) { StringTokenizer st = new StringTokenizer(patternStr.trim(), ";"); int length = st.countTokens(); - if (length>0) - { + if (length>0) { int i = 0; float[] pattern = new float[length]; - while(st.hasMoreTokens()) - { + while(st.hasMoreTokens()) { pattern[i] = Float.parseFloat(st.nextToken()); i++; } @@ -422,10 +384,8 @@ protected float[] parsePattern(String patternStr) return null; } - protected float [] getDashedPattern(int style) - { - switch(style) - { + protected float [] getDashedPattern(int style) { + switch(style) { case 0: return STYLE_SOLID; case 1: return STYLE_NONE; case 2: return STYLE_DOTTED; @@ -437,45 +397,37 @@ protected float[] parsePattern(String patternStr) } } - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) - { + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) { GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, 0, 0); } - public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int style, int cornerRadius) - { + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int style, int cornerRadius) { GxDrawRect(left, top, right, bottom, pen, foreRed, foreGreen, foreBlue, backMode, backRed, backGreen, backBlue, style, style, style, style, cornerRadius, cornerRadius, cornerRadius, cornerRadius); } public abstract void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR); - public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) - { + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue) { GxDrawLine(left, top, right, bottom, width, foreRed, foreGreen, foreBlue, 0); } public abstract void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style); - public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom) - { + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom) { GxDrawBitMap(bitmap, left, top, right, bottom, 0); } public abstract void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio); - public String getSubstitute(String fontName) - { + public String getSubstitute(String fontName) { Vector fontSubstitutesProcessed = new Vector<>(); String newFontName = fontName; - while( fontSubstitutes.containsKey(newFontName)) - { - if (!fontSubstitutesProcessed.contains(newFontName)) - { + while( fontSubstitutes.containsKey(newFontName)) { + if (!fontSubstitutesProcessed.contains(newFontName)) { fontSubstitutesProcessed.addElement(newFontName); newFontName = fontSubstitutes.get(newFontName); } - else - { + else { return fontSubstitutes.get(newFontName); } } @@ -484,33 +436,26 @@ public String getSubstitute(String fontName) public abstract void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue); - protected String getFontLocation(String fontName) - { + protected String getFontLocation(String fontName) { String fontPath = props.getProperty(Const.MS_FONT_LOCATION, fontName, ""); - if (fontPath.equals("")) - { + if (fontPath.equals("")) { fontPath = props.getProperty(Const.SUN_FONT_LOCATION, fontName, ""); } return fontPath; } @SuppressWarnings("unchecked") - protected Hashtable getFontLocations() - { + protected Hashtable getFontLocations() { Hashtable msLocations = props.getSection(Const.MS_FONT_LOCATION); Hashtable sunLocations = props.getSection(Const.SUN_FONT_LOCATION); Hashtable locations = new Hashtable(); - if (msLocations != null) - { - for (Enumeration e = msLocations.keys(); e.hasMoreElements() ;) - { + if (msLocations != null) { + for (Enumeration e = msLocations.keys(); e.hasMoreElements() ;) { Object key = e.nextElement(); locations.put(key, msLocations.get(key)); } } - if (sunLocations != null) - { - for (Enumeration e = sunLocations.keys(); e.hasMoreElements() ;) - { + if (sunLocations != null) { + for (Enumeration e = sunLocations.keys(); e.hasMoreElements() ;) { Object key = e.nextElement(); locations.put(key, sunLocations.get(key)); } @@ -529,16 +474,13 @@ protected boolean isEmbeddedFont(String realFontName) { /** * @deprecated */ - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align) - { + public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align) { GxDrawText(sTxt, left, top, right, bottom, align, 0); } - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat) - { + public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat) { GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, 0); } - public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border) - { + public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border) { GxDrawText(sTxt, left, top, right, bottom, align, htmlformat, border, 0); } public abstract void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign); @@ -555,26 +497,22 @@ public void GxClearAttris() {} //Por ejemplo: si en genexus se tiene un reporte con Paper Height de 1169 (A4) centésimos de pulgada (1/100 inch), //en el parámetro pageLength llega 16834 que esta en Twips (16834 = 1169*14.4). 1 twip = 1/1440 inch. //Con el valor anterior 15.45 estaba quedando un margen bottom fijo que no se podia eliminar (incluso seteando mb 0). - private static double TO_CM_SCALE =28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) + protected static double TO_CM_SCALE = 28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) public abstract boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex); - public int getPageLines() - { + public int getPageLines() { if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); return pageLines; } - public int getLineHeight() - { + public int getLineHeight() { if(DEBUG)DEBUG_STREAM.println("getLineHeight: --> " + this.lineHeight); return this.lineHeight; } - public void setPageLines(int P_lines) - { + public void setPageLines(int P_lines) { if(DEBUG)DEBUG_STREAM.println("setPageLines: " + P_lines); pageLines = P_lines; } - public void setLineHeight(int lineHeight) - { + public void setLineHeight(int lineHeight) { if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); this.lineHeight = lineHeight; @@ -613,30 +551,23 @@ public void GxEndPrinter() {} public void GxStartDoc() {} public void GxSetDocFormat(String format) {} - public void GxSetDocName(String docName) - { + public void GxSetDocName(String docName) { this.docName = docName.trim(); if(this.docName.indexOf('.') < 0) this.docName += ".pdf"; - if(!new File(docName).isAbsolute()) - { // Si el nombre del documento es relativo, veo si hay que agregarle el outputDir + if(!new File(docName).isAbsolute()) { // Si el nombre del documento es relativo, veo si hay que agregarle el outputDir String outputDir = props.getGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "").replace(alternateSeparator, File.separatorChar).trim(); - if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) - { - if(!outputDir.endsWith(File.separator)) - { + if(!outputDir.equalsIgnoreCase("") && !outputDir.equalsIgnoreCase(".")) { + if(!outputDir.endsWith(File.separator)) { outputDir += File.separator; } new File(outputDir).mkdirs(); this.docName = outputDir + this.docName; } - else - { - if (ModelContext.getModelContext() != null) - { + else { + if (ModelContext.getModelContext() != null) { HttpContext webContext = (HttpContext) ModelContext.getModelContext().getHttpContext(); - if ((webContext != null) && (webContext instanceof HttpContextWeb)) - { + if ((webContext != null) && (webContext instanceof HttpContextWeb)) { outputDir = com.genexus.ModelContext.getModelContext().getHttpContext().getDefaultPath() + File.separator; this.docName = outputDir + this.docName; } @@ -648,8 +579,7 @@ public void GxSetDocName(String docName) if(DEBUG)DEBUG_STREAM.println("GxSetDocName: '" + this.docName + "'"); } - public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) - { + public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { return true; } @@ -668,7 +598,6 @@ public boolean GxIsAliveDoc() return true; } - protected int page; public int getPage() { @@ -696,8 +625,7 @@ public void setMetrics(String fontName, boolean bold, boolean italic, int ascent /** Carga la tabla de substitutos */ - protected void loadSubstituteTable() - { + protected void loadSubstituteTable() { // Primero leemos la tabla de substitutos del Registry Hashtable> tempInverseMappings = new Hashtable<>(); @@ -710,12 +638,10 @@ protected void loadSubstituteTable() // indicada por Const.FONT_SUBSTITUTES_SECTION y son pares oldFont -> newFont Hashtable otherMappings = props.getSection(Const.FONT_SUBSTITUTES_SECTION); if(otherMappings != null) - for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) - { + for(Enumeration enumera = otherMappings.keys(); enumera.hasMoreElements();) { String fontName = (String)enumera.nextElement(); fontSubstitutes.put(fontName, (String)otherMappings.get(fontName)); - if(tempInverseMappings.containsKey(fontName)) // Con esto solucionamos el tema de la recursión de Fonts -> Fonts - { // x ej: Si tenú} Font1-> Font2, y ahora tengo Font2->Font3, pongo cambio el 1º por Font1->Font3 + if(tempInverseMappings.containsKey(fontName)) { // Con esto solucionamos el tema de la recursión de Fonts -> Fonts, x ej: Si tenú} Font1-> Font2, y ahora tengo Font2->Font3, pongo cambio el 1º por Font1->Font3 String fontSubstitute = (String)otherMappings.get(fontName); for(Enumeration enum2 = tempInverseMappings.get(fontName).elements(); enum2.hasMoreElements();) fontSubstitutes.put(enum2.nextElement(), fontSubstitute); @@ -738,26 +664,22 @@ public void showInformation() {} public static final double SCALE_FACTOR = 72; protected double PPP = 96; - protected double convertScale(int value) - { + protected double convertScale(int value) { double result = value * SCALE_FACTOR / PPP; return result; } - protected double convertScale(double value) - { + protected double convertScale(double value) { double result = value * SCALE_FACTOR / PPP; return result; } - protected float reconvertScale(float value) - { + protected float reconvertScale(float value) { float result = value / (float)(SCALE_FACTOR / PPP); return result; } - class FontProps - { + class FontProps { public int horizontal; public int vertical; } diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index d2fdb499c..4e349ea6e 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -80,8 +80,7 @@ protected void init() */ private void drawRectangle(PdfContentByte cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, - float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) - { + float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) { float[] dashPatternTop = getDashedPattern(styleTop); @@ -90,137 +89,109 @@ private void drawRectangle(PdfContentByte cb, float x, float y, float w, float h float[] dashPatternRight = getDashedPattern(styleRight); //-------------------bottom line--------------------- - if (styleBottom!=STYLE_NONE_CONST) - { + if (styleBottom!=STYLE_NONE_CONST) { cb.setLineDash(dashPatternBottom, 0); } float b = 0.4477f; - if (radioBL>0) - { + if (radioBL>0) { cb.moveTo(x + radioBL, y); } - else - { - if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) - { + else { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) { cb.moveTo(x + penAux, y); } - else - { + else { cb.moveTo(x, y); } } //-------------------bottom right corner--------------------- - if (styleBottom!=STYLE_NONE_CONST)//si es null es Style None y no traza la linea - { - if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) - { + if (styleBottom!=STYLE_NONE_CONST){ //si es null es Style None y no traza la linea + + if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) { cb.lineTo(x + w - penAux, y); } - else - { + else { cb.lineTo(x + w - radioBR, y); } - if (radioBR>0 && styleRight!=STYLE_NONE_CONST) - { + if (radioBR>0 && styleRight!=STYLE_NONE_CONST) { cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); } } //-------------------right line--------------------- - if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) - { + if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) { cb.stroke(); cb.setLineDash(dashPatternRight, 0); - if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) - { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) { cb.moveTo(x + w, y + penAux); } - else - { + else { cb.moveTo(x + w, y + radioBR); } } //-------------------top right corner--------------------- - if (styleRight!=STYLE_NONE_CONST) - { - if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) - { + if (styleRight!=STYLE_NONE_CONST) { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) { cb.lineTo (x + w, y + h - penAux); } - else - { + else { cb.lineTo (x + w, y + h - radioTR); } - if (radioTR>0 && styleTop!=STYLE_NONE_CONST) - { + if (radioTR>0 && styleTop!=STYLE_NONE_CONST) { cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); } } //-------------------top line--------------------- - if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) - { + if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) { cb.stroke(); cb.setLineDash(dashPatternTop, 0); - if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) - { + if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) { cb.moveTo(x + w - penAux, y + h); } - else - { + else { cb.moveTo(x + w - radioTR, y + h); } } //-------------------top left corner--------------------- - if (styleTop!=STYLE_NONE_CONST) - { - if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) - { + if (styleTop!=STYLE_NONE_CONST) { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) { cb.lineTo(x + penAux, y + h); } - else - { + else { cb.lineTo(x + radioTL, y + h); } - if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) - { + if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) { cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); } } //-------------------left line--------------------- - if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) - { + if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) { cb.stroke(); cb.setLineDash(dashPatternLeft, 0); - if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) - { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) { cb.moveTo(x, y + h - penAux); } - else - { + else { cb.moveTo(x, y + h - radioTL); } } //-------------------bottom left corner--------------------- - if (styleLeft!=STYLE_NONE_CONST) - { - if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) - { + if (styleLeft!=STYLE_NONE_CONST) { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) { cb.lineTo(x, y + penAux); } - else - { + else { cb.lineTo(x, y + radioBL); } if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) @@ -232,52 +203,44 @@ private void drawRectangle(PdfContentByte cb, float x, float y, float w, float h } private void roundRectangle(PdfContentByte cb, float x, float y, float w, float h, - float radioTL, float radioTR, float radioBL, float radioBR) - { + float radioTL, float radioTR, float radioBL, float radioBR) { //-------------------bottom line--------------------- float b = 0.4477f; - if (radioBL>0) - { + if (radioBL>0) { cb.moveTo(x + radioBL, y); } - else - { + else { cb.moveTo(x, y); } //-------------------bottom right corner--------------------- cb.lineTo(x + w - radioBR, y); - if (radioBR>0) - { + if (radioBR>0) { cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); } cb.lineTo (x + w, y + h - radioTR); - if (radioTR>0) - { + if (radioTR>0) { cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); } cb.lineTo(x + radioTL, y + h); - if (radioTL>0) - { + if (radioTL>0) { cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); } cb.lineTo(x, y + radioBL); - if (radioBL>0) - { + if (radioBL>0) { cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); } } public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, - int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) - { + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { PdfContentByte cb = writer.getDirectContent(); @@ -298,8 +261,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cb.setLineWidth(penAux); cb.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE); - if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) - { + if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) { //Tengo que hacer eso para que el borde quede del mismo color que el fill si se indica que no se quiere borde, //porque no funciona el setLineWidth if (pen > 0) @@ -309,24 +271,20 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cb.rectangle(x1, y1, x2 - x1, y2 - y1); - if (backMode!=0) - { + if (backMode!=0) { cb.setColorFill(new Color(backRed, backGreen, backBlue)); cb.fillStroke(); } cb.closePathStroke(); } - else - { + else { float w = x2 - x1; float h = y2 - y1; - if (w < 0) - { + if (w < 0) { x1 += w; w = -w; } - if (h < 0) - { + if (h < 0) { y1 += h; h = -h; } @@ -343,8 +301,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cRadioBL = Math.max(0, Math.min(cRadioBL, max/2)); cRadioBR = Math.max(0, Math.min(cRadioBR, max/2)); - if (backMode!=0) - { + if (backMode!=0) { //Interior del rectangulo cb.setRGBColorStroke(backRed, backGreen, backBlue); cb.setLineWidth(0); @@ -355,8 +312,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cb.fillStroke(); cb.setLineWidth(penAux); } - if (pen > 0) - { + if (pen > 0) { //Bordes del rectangulo cb.setRGBColorStroke(foreRed, foreGreen, foreBlue); drawRectangle(cb, x1, y1, w, h, @@ -370,8 +326,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo if(DEBUG)DEBUG_STREAM.println("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); } - public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) - { + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { PdfContentByte cb = writer.getDirectContent(); float widthAux = (float)convertScale(width); @@ -393,12 +348,10 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int cb.setRGBColorStroke(foreRed, foreGreen, foreBlue); cb.setLineWidth(widthAux); - if (lineCapProjectingSquare) - { + if (lineCapProjectingSquare) { cb.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE); //Hace que lineas de width 10 por ejemplo que forman una esquina no quedan igual que en disenio porque "rellena" la esquina. } - if (style!=0) - { + if (style!=0) { float[] dashPattern = getDashedPattern(style); cb.setLineDash(dashPattern, 0); } @@ -409,63 +362,50 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int cb.restoreState(); } - public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) - { - try - { + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { + try { //java.awt.Image image; com.lowagie.text.Image image; com.lowagie.text.Image imageRef; - try - { - if (documentImages != null && documentImages.containsKey(bitmap)) - { + try { + if (documentImages != null && documentImages.containsKey(bitmap)) { image = documentImages.get(bitmap); } - else - { + else { - if (!NativeFunctions.isWindows() && new File(bitmap).isAbsolute() && bitmap.startsWith(httpContext.getStaticContentBase())) - { + if (!NativeFunctions.isWindows() && new File(bitmap).isAbsolute() && bitmap.startsWith(httpContext.getStaticContentBase())) { bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); } - if (!new File(bitmap).isAbsolute() && !bitmap.toLowerCase().startsWith("http:") && !bitmap.toLowerCase().startsWith("https:")) - { - if (bitmap.startsWith(httpContext.getStaticContentBase())) - { + if (!new File(bitmap).isAbsolute() && !bitmap.toLowerCase().startsWith("http:") && !bitmap.toLowerCase().startsWith("https:")) { + if (bitmap.startsWith(httpContext.getStaticContentBase())) { bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); } // Si la ruta a la imagen NO es absoluta, en aplicaciones Web le agregamos al comienzo la ruta al root de la aplicación // más la staticContentBaseURL si ésta es relativa. image = com.lowagie.text.Image.getInstance(defaultRelativePrepend + bitmap); //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(defaultRelativePrepend + bitmap); - if(image == null) - { // Si all\uFFFDEno se encuentra la imagen, entonces la buscamos bajo el webAppDir (para mantener compatibilidad) + if(image == null) { // Si all\uFFFDEno se encuentra la imagen, entonces la buscamos bajo el webAppDir (para mantener compatibilidad) bitmap = webAppDir + bitmap; image = com.lowagie.text.Image.getInstance(bitmap); //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); } - else - { + else { bitmap = defaultRelativePrepend + bitmap; } } - else - { + else { image = com.lowagie.text.Image.getInstance(bitmap); //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); } } } - catch(java.lang.IllegalArgumentException ex)//Puede ser una url absoluta - { + catch(java.lang.IllegalArgumentException ex) {//Puede ser una url absoluta java.net.URL url= new java.net.URL(bitmap); image = com.lowagie.text.Image.getInstance(url); } - if (documentImages == null) - { + if (documentImages == null) { documentImages = new ConcurrentHashMap(); } documentImages.putIfAbsent(bitmap, image); @@ -473,8 +413,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom if(DEBUG)DEBUG_STREAM.println("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); - if(image != null) - { // Si la imagen NO se encuentra, no hago nada + if(image != null) { // Si la imagen NO se encuentra, no hago nada float rightAux = (float)convertScale(right); float bottomAux = (float)convertScale(bottom); float leftAux = (float)convertScale(left); @@ -489,31 +428,25 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom cb.addImage(image); } } - catch(DocumentException de) - { + catch(DocumentException de) { System.err.println(de.getMessage()); } - catch(IOException ioe) - { + catch(IOException ioe) { System.err.println(ioe.getMessage()); } - catch(Exception e) - { + catch(Exception e) { System.err.println(e.getMessage()); } } - public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) - { + public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) { boolean isCJK = false; boolean embeedFont = isEmbeddedFont(fontName); String originalFontName = fontName; - if (!embeedFont) - { + if (!embeedFont) { fontName = getSubstitute(fontName); // Veo si hay substitutos solo si el font no va a ir embebido } - if(DEBUG) - { + if(DEBUG) { String fontSubstitute = ""; if (!originalFontName.equals(fontName)) { @@ -525,13 +458,11 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo DEBUG_STREAM.println("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); } - if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) - { + if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { barcode = new Barcode128(); barcode.setCodeType(Barcode128.CODE128); } - else - { + else { barcode = null; } this.fontUnderline = fontUnderline; @@ -544,19 +475,15 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo backFill = (backMode != 0); try { - if (PDFFont.isType1(fontName)) - { + if (PDFFont.isType1(fontName)) { //Me fijo si es un Asian font - for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) - { + for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) { if(Type1FontMetrics.CJKNames[i][0].equalsIgnoreCase(fontName) || - Type1FontMetrics.CJKNames[i][1].equalsIgnoreCase(fontName)) - { + Type1FontMetrics.CJKNames[i][1].equalsIgnoreCase(fontName)) { String style = ""; if (fontBold && fontItalic) style = "BoldItalic"; - else - { + else { if (fontItalic) style = "Italic"; if (fontBold) @@ -567,22 +494,18 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo break; } } - if (!isCJK) - { + if (!isCJK) { int style = 0; if (fontBold && fontItalic) style = style + 3; - else - { + else { if (fontItalic) style = style + 2; if (fontBold) style = style + 1; } - for(int i=0;i= 2 && !((align & 16) == 16) && htmlformat != 1) - { + if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) { if (valign == VerticalAlign.TOP.value()) bottom = top + (int)reconvertScale(lineHeight); else if (valign == VerticalAlign.BOTTOM.value()) @@ -726,20 +635,16 @@ else if (valign == VerticalAlign.BOTTOM.value()) int alignment = align & 3; boolean autoResize = (align & 256) == 256; - if (htmlformat == 1) - { + if (htmlformat == 1) { StyleSheet styles = new StyleSheet(); Hashtable locations = getFontLocations(); - for (Enumeration e = locations.keys(); e.hasMoreElements() ;) - { + for (Enumeration e = locations.keys(); e.hasMoreElements() ;) { String fontName = (String)e.nextElement(); String fontPath = (String)locations.get(fontName); - if (fontPath.equals("")) - { + if (fontPath.equals("")) { fontPath = PDFFontDescriptor.getTrueTypeFontLocation(fontName, props); } - if (!fontPath.equals("")) - { + if (!fontPath.equals("")) { FontFactory.register(fontPath, fontName); styles.loadTagStyle("body", "face", fontName); @@ -765,18 +670,14 @@ else if (valign == VerticalAlign.BOTTOM.value()) Col.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); simulationCol.setSimpleColumn(leftAux + leftMargin,drawingPageHeight - bottomAux,rightAux + leftMargin,drawingPageHeight - topAux); - try - { + try { ArrayList objects = HTMLWorker.parseToList(new StringReader(sTxt), styles); - for (int k = 0; k < objects.size(); ++k) - { - if (pageHeightExceeded(bottomAux, drawingPageHeight)) - { + for (int k = 0; k < objects.size(); ++k) { + if (pageHeightExceeded(bottomAux, drawingPageHeight)) { simulationCol.addElement((Element)objects.get(k)); simulationCol.go(true); - if (simulationCol.getYLine() < bottomMargin) - { + if (simulationCol.getYLine() < bottomMargin) { GxEndPage(); GxStartPage(); simulationCol = new ColumnText(null); @@ -802,17 +703,14 @@ else if (valign == VerticalAlign.BOTTOM.value()) } } else - if (barcode!=null) - { + if (barcode!=null) { if(DEBUG)DEBUG_STREAM.println("Barcode: --> " + barcode.getClass().getName()); - try - { + try { barcode.setCode(sTxt); barcode.setTextAlignment(alignment); com.lowagie.text.Rectangle rectangle = new com.lowagie.text.Rectangle(0, 0); //El rectangulo tiene tamaño ok. - switch (alignment) - { + switch (alignment) { case 1: // Center Alignment rectangle = new com.lowagie.text.Rectangle((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, (float)this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin, @@ -847,21 +745,17 @@ else if (valign == VerticalAlign.BOTTOM.value()) imageCode.scaleToFit(rectangle.getWidth(), rectangle.getHeight()); document.add(imageCode); } - catch (Exception ex) - { + catch (Exception ex) { if(DEBUG)DEBUG_STREAM.println("Error generating Barcode: --> " + barcode.getClass().getName() + ex.getMessage()); if(DEBUG)ex.printStackTrace (); } } - else - { + else { - if(backFill) - { + if(backFill) { com.lowagie.text.Rectangle rectangle = new com.lowagie.text.Rectangle(0,0); //Si el texto tiene background lo dibujo de esta forma - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment rectangle = new com.lowagie.text.Rectangle((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, (float)this.pageSize.getTop() - bottomAux - topMargin -bottomMargin , (leftAux + rightAux)/2 + leftMargin + rectangleWidth/2, (float)this.pageSize.getTop() - topAux - topMargin -bottomMargin); break; @@ -873,12 +767,10 @@ else if (valign == VerticalAlign.BOTTOM.value()) break; } rectangle.setBackgroundColor(backColor); - try - { + try { document.add(rectangle); } - catch(DocumentException de) - { + catch(DocumentException de) { System.err.println(de.getMessage()); } } @@ -888,12 +780,10 @@ else if (valign == VerticalAlign.BOTTOM.value()) com.lowagie.text.Rectangle underline; //Si el texto esta subrayado - if (fontUnderline) - { + if (fontUnderline) { underline = new com.lowagie.text.Rectangle(0,0); - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment underline = new com.lowagie.text.Rectangle( (leftAux + rightAux)/2 + leftMargin - rectangleWidth/2, @@ -915,19 +805,16 @@ else if (valign == VerticalAlign.BOTTOM.value()) break; } underline.setBackgroundColor(foreColor); - try - { + try { document.add(underline); } - catch(DocumentException de) - { + catch(DocumentException de) { System.err.println(de.getMessage()); } } //Si el texto esta tachado - if (fontStrikethru) - { + if (fontStrikethru) { underline = new com.lowagie.text.Rectangle(0,0); float strikethruSeparation = lineHeight / 2; @@ -964,10 +851,8 @@ else if (valign == VerticalAlign.BOTTOM.value()) } } - if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) - {// Si el texto es la cantidad de páginas del documento - if (!templateCreated) - { + if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) {// Si el texto es la cantidad de páginas del documento + if (!templateCreated) { template = cb.createTemplate(right - left, bottom - top); templateCreated = true; } @@ -984,8 +869,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) boolean wrap = ((align & 16) == 16); //Justified - if (wrap || justified) - { + if (wrap || justified) { //Bottom y top son los absolutos, sin considerar la altura real a la que se escriben las letras. bottomAux = (float)convertScale(bottomOri); topAux = (float)convertScale(topOri); @@ -1007,17 +891,14 @@ else if (valign == VerticalAlign.BOTTOM.value()) ex.printStackTrace(System.err); } } - else //no wrap - { + else{ //no wrap startHeight=0; - if (!autoResize) - { + if (!autoResize) { //Va quitando el ultimo char del texto hasta que llega a un string cuyo ancho se pasa solo por un caracter //del ancho del textblock ("se pasa solo por un caracter": esto es porque en el caso general es ese el texto que //mas se parece a lo que se disenia en genexus). String newsTxt = sTxt; - while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) - { + while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) { sTxt = newsTxt; newsTxt = newsTxt.substring(0, newsTxt.length()-1); TxtWidth = baseFont.getWidthPoint(newsTxt, fontSize); @@ -1025,8 +906,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) } Phrase phrase = new Phrase(sTxt, font); - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment ColumnText.showTextAligned(cb, cb.ALIGN_CENTER, phrase, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin + startHeight, 0, runDirection, arabicOptions); break; @@ -1055,8 +935,7 @@ ColumnText SimulateDrawColumnText(PdfContentByte cb, Rectangle rect, Paragraph p Col.go(true); return Col; } - void DrawColumnText(PdfContentByte cb, float llx, float lly, float urx, float ury, Paragraph p, float leading, int runDirection, int valign, int alignment) throws DocumentException - { + void DrawColumnText(PdfContentByte cb, float llx, float lly, float urx, float ury, Paragraph p, float leading, int runDirection, int valign, int alignment) throws DocumentException { Rectangle rect = new Rectangle(llx, lly, urx, ury); ColumnText ct = SimulateDrawColumnText(cb, rect, p, leading, runDirection, alignment);//add the column in simulation mode float y = ct.getYLine(); @@ -1084,36 +963,24 @@ else if (valign == VerticalAlign.TOP.value()) Col.addText(p); Col.go(); } - private int columnAlignment(int alignment) - { + private int columnAlignment(int alignment) { if (alignment == Element.ALIGN_JUSTIFIED) return justifiedType; else return alignment; } - public static final double PAGE_SCALE_Y = 20; // Indica la escala de la página - public static final double PAGE_SCALE_X = 20; // Indica la escala de la página - public static final double GX_PAGE_SCALE_Y_OLD = 15.45; - public static final double GX_PAGE_SCALE_Y = 14.4; // Indica la escala de la página, GeneXus lleva otra escala para el tamaño de la hoja, (variando este parametro, se agranda o achica el tamaño imprimible por GeneXus) - //Por ejemplo: si en genexus se tiene un reporte con Paper Height de 1169 (A4) centésimos de pulgada (1/100 inch), - //en el parámetro pageLength llega 16834 que esta en Twips (16834 = 1169*14.4). 1 twip = 1/1440 inch. - //Con el valor anterior 15.45 estaba quedando un margen bottom fijo que no se podia eliminar (incluso seteando mb 0). - private static double TO_CM_SCALE =28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) - public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) - { + public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { PPP = gxYPage[0]; loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - if(outputStream != null) - { + if(outputStream != null) { if (output.equalsIgnoreCase("PRN")) outputType = Const.OUTPUT_STREAM_PRINTER; else outputType = Const.OUTPUT_STREAM; } - else - { + else { if(output.equalsIgnoreCase("SCR")) outputType = Const.OUTPUT_SCREEN; else if(output.equalsIgnoreCase("PRN")) @@ -1122,23 +989,19 @@ else if(output.equalsIgnoreCase("PRN")) if(outputType == Const.OUTPUT_FILE) TemporaryFiles.getInstance().removeFileFromList(docName); - else - { + else { String tempPrefix = docName; String tempExtension = "pdf"; int tempIndex = docName.lastIndexOf('.'); - if(tempIndex != -1) - { + if(tempIndex != -1) { tempPrefix = docName.substring(0, tempIndex); tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); } docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); } - try - { + try { setOutputStream(new FileOutputStream(docName)); - }catch(IOException accessError) - { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream + }catch(IOException accessError) { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream accessError.printStackTrace(System.err); outputStream = new com.genexus.util.NullOutputStream(); outputType = Const.OUTPUT_FILE; // Hago esto para no tener lios con el Acrobat @@ -1183,10 +1046,8 @@ else if(output.equalsIgnoreCase("PRN")) return true; } - private com.lowagie.text.Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) - { - if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) - { + private com.lowagie.text.Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { + if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) { if (length == 23818 && width == 16834) return PageSize.A3; else if (length == 16834 && width == 11909) @@ -1209,16 +1070,13 @@ else if (length == 15840 && width == 12240) return new com.lowagie.text.Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); } - public void GxEndDocument() - { - if(document.getPageNumber() == 0) - { // Si no hay ninguna página en el documento, agrego una vacia} + public void GxEndDocument() { + if(document.getPageNumber() == 0) { // Si no hay ninguna página en el documento, agrego una vacia} writer.setPageEmpty(false); } //Ahora proceso los comandos GeneXus {{Pages}} - if (template != null) - { + if (template != null) { template.beginText(); template.setFontAndSize(templateFont, templateFontSize); template.setTextMatrix(0,0); @@ -1227,8 +1085,7 @@ public void GxEndDocument() template.endText(); } int copies = 1; - try - { + try { copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); writer.addViewerPreference(PdfName.NUMCOPIES, new PdfNumber(copies)); @@ -1245,40 +1102,32 @@ public void GxEndDocument() if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue.toString()); writer.addViewerPreference(PdfName.DUPLEX, duplexValue); } - catch(Exception ex) - { + catch(Exception ex) { ex.printStackTrace(System.err); } String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); - if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) - { + if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { //writer.addJavaScript("if (this.external)\n");//Specifies whether the current document is being viewed in the Acrobat application or in an external window (such as a web browser). //writer.addJavaScript("app.alert('SI es externa' + this.external);"); - writer.addJavaScript("var pp = this.getPrintParams();\n"); - //writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); String printerAux=printerSettings.getProperty(form, Const.PRINTER); String printer = replace(printerAux, "\\", "\\\\"); - if (printer!=null && !printer.equals("")) - { + if (printer!=null && !printer.equals("")) { writer.addJavaScript("pp.printerName = \"" + printer + "\";\n"); } - if (fit) - { + if (fit) { writer.addJavaScript("pp.pageHandling = pp.constants.handling.fit;\n"); } - else - { + else { writer.addJavaScript("pp.pageHandling = pp.constants.handling.none;\n"); } - if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0"))//Show printer dialog Never - { + if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")){//Show printer dialog Never writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); //No print dialog is displayed. During printing a progress monitor and cancel //dialog is displayed and removed automatically when printing is complete. @@ -1287,8 +1136,7 @@ public void GxEndDocument() writer.addJavaScript("this.print(pp);\n"); } } - else //Show printer dialog is sent directly to printer | always - { + else{ //Show printer dialog is sent directly to printer | always writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.full;\n"); //Displays the print dialog allowing the user to change print settings and requiring //the user to press OK to continue. During printing a progress monitor and cancel @@ -1304,14 +1152,11 @@ public void GxEndDocument() try{ props.save(); } catch(IOException e) { ; } - // OK, ahora que ya terminamos el PDF, vemos si tenemos que mostrarlo en pantalla - switch(outputType) - { + switch(outputType) { case Const.OUTPUT_SCREEN: try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo - try{ showReport(docName, modal); } catch(Exception e) - { // Si no se puede mostrar el reporte + try{ showReport(docName, modal); } catch(Exception e) { // Si no se puede mostrar el reporte e.printStackTrace(); } // Comento la próxima lú‹ea, porque por manejo interno del Acrobat, si ya habú} una instancia del @@ -1322,8 +1167,7 @@ public void GxEndDocument() case Const.OUTPUT_PRINTER: try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo try{ - if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) - { + if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) { printReport(docName, this.printerOutputMode == 1); } } catch(Exception e){ // Si no se puede mostrar el reporte @@ -1339,16 +1183,14 @@ public void GxEndDocument() } outputStream = null; } - public void GxStartPage() - { + public void GxStartPage() { boolean ret = document.newPage(); pages = pages +1; } public void GxEndPage() {} - class FontProps - { + class FontProps { public int horizontal; public int vertical; } diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 56014cd46..ec9e68ea8 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -3,6 +3,8 @@ import java.awt.Color; import java.io.*; import java.net.URL; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import com.genexus.CommonUtil; @@ -21,7 +23,6 @@ import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; -import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationText; import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences; import org.apache.pdfbox.util.Matrix; @@ -41,20 +42,14 @@ public class PDFReportPDFBox extends GXReportPDFCommons{ public int runDirection = 0; private int page; - public PDFReportPDFBox(ModelContext context) - { + public PDFReportPDFBox(ModelContext context) { super(context); - try { - document = null; - pageSize = null; - documentImages = new ConcurrentHashMap<>(); - } catch (Exception e){ - e.printStackTrace(System.err); - } + document = null; + pageSize = null; + documentImages = new ConcurrentHashMap<>(); } - protected void init() - { + protected void init() { try { document = new PDDocument(); } @@ -65,131 +60,100 @@ protected void init() private void drawRectangle(PDPageContentStream cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, - float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) - { + float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) { float[] dashPatternTop = getDashedPattern(styleTop); float[] dashPatternBottom = getDashedPattern(styleBottom); float[] dashPatternLeft = getDashedPattern(styleLeft); float[] dashPatternRight = getDashedPattern(styleRight); try { - if (styleBottom!=STYLE_NONE_CONST) - { + if (styleBottom!=STYLE_NONE_CONST) { cb.setLineDashPattern(dashPatternBottom, 0); } float b = 0.4477f; - if (radioBL>0) - { + if (radioBL>0) { cb.moveTo(x + radioBL, y); } - else - { - if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) - { + else { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) { cb.moveTo(x + penAux, y); } - else - { + else { cb.moveTo(x, y); } } - if (styleBottom!=STYLE_NONE_CONST) - { - if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) - { + if (styleBottom!=STYLE_NONE_CONST) { + if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) { cb.lineTo(x + w - penAux, y); } - else - { + else { cb.lineTo(x + w - radioBR, y); } - if (radioBR>0 && styleRight!=STYLE_NONE_CONST) - { + if (radioBR>0 && styleRight!=STYLE_NONE_CONST) { cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); } } - if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) - { + if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) { cb.stroke(); cb.setLineDashPattern(dashPatternRight, 0); - if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) - { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) { cb.moveTo(x + w, y + penAux); } - else - { + else { cb.moveTo(x + w, y + radioBR); } } - if (styleRight!=STYLE_NONE_CONST) - { - if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) - { + if (styleRight!=STYLE_NONE_CONST) { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) { cb.lineTo (x + w, y + h - penAux); } - else - { + else { cb.lineTo (x + w, y + h - radioTR); } - if (radioTR>0 && styleTop!=STYLE_NONE_CONST) - { + if (radioTR>0 && styleTop!=STYLE_NONE_CONST) { cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); } } - if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) - { + if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) { cb.stroke(); cb.setLineDashPattern(dashPatternTop, 0); - if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) - { + if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) { cb.moveTo(x + w - penAux, y + h); } - else - { + else { cb.moveTo(x + w - radioTR, y + h); } } - if (styleTop!=STYLE_NONE_CONST) - { - if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) - { + if (styleTop!=STYLE_NONE_CONST) { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) { cb.lineTo(x + penAux, y + h); } - else - { + else { cb.lineTo(x + radioTL, y + h); } - if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) - { + if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) { cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); } } - if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) - { + if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) { cb.stroke(); cb.setLineDashPattern(dashPatternLeft, 0); - if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) - { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) { cb.moveTo(x, y + h - penAux); } - else - { + else { cb.moveTo(x, y + h - radioTL); } } - if (styleLeft!=STYLE_NONE_CONST) - { - if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) - { + if (styleLeft!=STYLE_NONE_CONST) { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) { cb.lineTo(x, y + penAux); } - else - { + else { cb.lineTo(x, y + radioBL); } - if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) - { + if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) { cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); } } @@ -200,36 +164,29 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl } private void roundRectangle(PDPageContentStream cb, float x, float y, float w, float h, - float radioTL, float radioTR, float radioBL, float radioBR) - { + float radioTL, float radioTR, float radioBL, float radioBR) { try { float b = 0.4477f; - if (radioBL>0) - { + if (radioBL>0) { cb.moveTo(x + radioBL, y); } - else - { + else { cb.moveTo(x, y); } cb.lineTo(x + w - radioBR, y); - if (radioBR>0) - { + if (radioBR>0) { cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); } cb.lineTo (x + w, y + h - radioTR); - if (radioTR>0) - { + if (radioTR>0) { cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); } cb.lineTo(x + radioTL, y + h); - if (radioTL>0) - { + if (radioTL>0) { cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); } cb.lineTo(x, y + radioBL); - if (radioBL>0) - { + if (radioBL>0) { cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); } } catch (IOException ioe) { @@ -238,8 +195,7 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f } public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, - int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) - { + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ float penAux = (float)convertScale(pen); @@ -259,8 +215,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cb.setLineWidth(penAux); cb.setLineCapStyle(2); - if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) - { + if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) { if (pen > 0) cb.setStrokingColor(foreRed, foreGreen, foreBlue); else @@ -268,25 +223,21 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cb.addRect(x1, y1, x2 - x1, y2 - y1); - if (backMode!=0) - { + if (backMode!=0) { cb.setNonStrokingColor(new Color(backRed, backGreen, backBlue)); cb.fillAndStroke(); } cb.closePath(); cb.stroke(); } - else - { + else { float w = x2 - x1; float h = y2 - y1; - if (w < 0) - { + if (w < 0) { x1 += w; w = -w; } - if (h < 0) - { + if (h < 0) { y1 += h; h = -h; } @@ -302,8 +253,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cRadioBL = Math.max(0, Math.min(cRadioBL, max/2)); cRadioBR = Math.max(0, Math.min(cRadioBR, max/2)); - if (backMode!=0) - { + if (backMode!=0) { cb.setStrokingColor(backRed, backGreen, backBlue); cb.setLineWidth(0); roundRectangle(cb, x1, y1, w, h, @@ -313,8 +263,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo cb.fillAndStroke(); cb.setLineWidth(penAux); } - if (pen > 0) - { + if (pen > 0) { cb.setStrokingColor(foreRed, foreGreen, foreBlue); drawRectangle(cb, x1, y1, w, h, styleTop, styleBottom, styleRight, styleLeft, @@ -330,8 +279,7 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo } } - public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) - { + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ float widthAux = (float)convertScale(width); @@ -353,12 +301,10 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int cb.setStrokingColor(foreRed, foreGreen, foreBlue); cb.setLineWidth(widthAux); - if (lineCapProjectingSquare) - { + if (lineCapProjectingSquare) { cb.setLineCapStyle(2); } - if (style!=0) - { + if (style!=0) { float[] dashPattern = getDashedPattern(style); cb.setLineDashPattern(dashPattern, 0); } @@ -372,55 +318,44 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int } } - public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) - { + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { try (PDPageContentStream cb = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false)){ PDImageXObject image; - try - { - if (documentImages != null && documentImages.containsKey(bitmap)) - { + try { + if (documentImages != null && documentImages.containsKey(bitmap)) { image = documentImages.get(bitmap); } - else - { + else { - if (!NativeFunctions.isWindows() && new File(bitmap).isAbsolute() && bitmap.startsWith(httpContext.getStaticContentBase())) - { + if (!NativeFunctions.isWindows() && new File(bitmap).isAbsolute() && bitmap.startsWith(httpContext.getStaticContentBase())) { bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); } - if (!new File(bitmap).isAbsolute() && !bitmap.toLowerCase().startsWith("http:") && !bitmap.toLowerCase().startsWith("https:")) - { + if (!new File(bitmap).isAbsolute() && !bitmap.toLowerCase().startsWith("http:") && !bitmap.toLowerCase().startsWith("https:")) { if (bitmap.startsWith(httpContext.getStaticContentBase())) { bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); } image = PDImageXObject.createFromFile(defaultRelativePrepend + bitmap,document); - if(image == null) - { + if(image == null) { bitmap = webAppDir + bitmap; image = PDImageXObject.createFromFile(bitmap,document); } - else - { + else { bitmap = defaultRelativePrepend + bitmap; } } - else - { + else { image = PDImageXObject.createFromFile(bitmap,document); } } } - catch(java.lang.IllegalArgumentException ex) - { + catch(java.lang.IllegalArgumentException ex) { URL url= new java.net.URL(bitmap); image = PDImageXObject.createFromFile(url.toString(),document); } - if (documentImages == null) - { + if (documentImages == null) { documentImages = new ConcurrentHashMap<>(); } documentImages.putIfAbsent(bitmap, image); @@ -428,8 +363,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom if(DEBUG)DEBUG_STREAM.println("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); - if(image != null) - { + if(image != null) { float rightAux = (float)convertScale(right); float bottomAux = (float)convertScale(bottom); float leftAux = (float)convertScale(left); @@ -444,26 +378,21 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom cb.drawImage(image, x, y, (rightAux - leftAux) * aspectRatio, (bottomAux - topAux) * aspectRatio); } } - catch(Exception e) - { + catch(Exception e) { System.err.println(e.getMessage()); } } - public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) - { + public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) { boolean isCJK = false; boolean embeedFont = isEmbeddedFont(fontName); String originalFontName = fontName; - if (!embeedFont) - { + if (!embeedFont) { fontName = getSubstitute(fontName); } - if(DEBUG) - { + if(DEBUG) { String fontSubstitute = ""; - if (!originalFontName.equals(fontName)) - { + if (!originalFontName.equals(fontName)) { fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } DEBUG_STREAM.println("GxAttris: "); @@ -472,12 +401,10 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo DEBUG_STREAM.println("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); } - if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) - { + if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { // Por ahora no soportamos barcode } - else - { + else { // Por ahora no soportamos barcode } this.fontUnderline = fontUnderline; @@ -490,18 +417,14 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo backFill = (backMode != 0); try { - if (PDFFont.isType1(fontName)) - { - for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) - { + if (PDFFont.isType1(fontName)) { + for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) { if(Type1FontMetrics.CJKNames[i][0].equalsIgnoreCase(fontName) || - Type1FontMetrics.CJKNames[i][1].equalsIgnoreCase(fontName)) - { + Type1FontMetrics.CJKNames[i][1].equalsIgnoreCase(fontName)) { String style = ""; if (fontBold && fontItalic) style = "BoldItalic"; - else - { + else { if (fontItalic) style = "Italic"; if (fontBold) @@ -512,22 +435,18 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo break; } } - if (!isCJK) - { + if (!isCJK) { int style = 0; if (fontBold && fontItalic) style = style + 3; - else - { + else { if (fontItalic) style = style + 2; if (fontBold) style = style + 1; } - for(int i=0;i= 2 && !((align & 16) == 16) && htmlformat != 1) - { + if (linesCount >= 2 && !((align & 16) == 16) && htmlformat != 1) { if (valign == PDFReportPDFBox.VerticalAlign.TOP.value()) bottom = top + (int)reconvertScale(lineHeight); else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) @@ -780,23 +683,18 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) int alignment = align & 3; boolean autoResize = (align & 256) == 256; - if (htmlformat == 1) - { + if (htmlformat == 1) { //Por ahora no soportamos la impresion de HTML } else - if (1 == 2)//(barcode!=null) - { + if (1 == 2){ //(barcode!=null) //Por ahora no soportamos la impresion de barcodes } - else - { + else { - if(backFill) - { + if(backFill) { PDRectangle rectangle = new PDRectangle(); - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment rectangle.setLowerLeftX((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2); rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin); @@ -827,12 +725,10 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) int underlineHeight = (int)underlineSeparation + (int)(underlineSeparation/4); PDRectangle underline; - if (fontUnderline) - { + if (fontUnderline) { underline = new PDRectangle(); - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment underline.setLowerLeftX((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2); underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation); @@ -859,13 +755,11 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) contentStream.close(); } - if (fontStrikethru) - { + if (fontStrikethru) { underline = new PDRectangle(); float strikethruSeparation = lineHeight / 2; - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment underline.setLowerLeftX((leftAux + rightAux)/2 + leftMargin - rectangleWidth/2); underline.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin -bottomMargin + startHeight - underlineSeparation + strikethruSeparation); @@ -892,10 +786,8 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) contentStream.close(); } - if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) - { - if (!templateCreated) - { + if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) { + if (!templateCreated) { formXObjecttemplate = new PDFormXObject(document); template = new PDPageContentStream(document, formXObjecttemplate, outputStream); formXObjecttemplate.setResources(new PDResources()); @@ -918,62 +810,38 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; boolean wrap = ((align & 16) == 16); - if (wrap || justified) - { + if (wrap || justified) { bottomAux = (float)convertScale(bottomOri); topAux = (float)convertScale(topOri); - float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); - PDAnnotationText annotation = new PDAnnotationText(); - String alignmentString; - switch(alignment) { - case 1: - alignmentString = "center"; - break; - case 2: - alignmentString = "right"; - break; - default: - alignmentString = "left"; - } - annotation.setDefaultAppearance("/" + font.getName() + " " + fontSize + " Tf " + leading + " TL 0 g " + alignmentString + " <>BDC q BT /F1 " + fontSize + " Tf " + leading + " TL Tj ET Q EMC"); - annotation.setContents(sTxt); - - PDRectangle annotationRectangle = new PDRectangle(); - annotationRectangle.setLowerLeftX(leftAux + leftMargin); - annotationRectangle.setLowerLeftY(this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin); - annotationRectangle.setUpperRightX(rightAux + leftMargin); - annotationRectangle.setUpperRightY(this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin); - annotation.setRectangle(annotationRectangle); - document.getPage(page - 1).getAnnotations().add(annotation); - PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1),PDPageContentStream.AppendMode.APPEND,false); - resolveTextStyling(contentStream,annotation.getContents(),leftAux + leftMargin,this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin); - contentStream.close(); + float llx = leftAux + leftMargin; + float lly = this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin; + float urx = rightAux + leftMargin; + float ury = this.pageSize.getUpperRightY() - topAux - topMargin - bottomMargin; + + showWrappedTextAligned(cb, font, alignment, sTxt, llx, lly, urx, ury); + } - else - { + else { startHeight=0; - if (!autoResize) - { + if (!autoResize) { String newsTxt = sTxt; - while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) - { + while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) { sTxt = newsTxt; newsTxt = newsTxt.substring(0, newsTxt.length()-1); TxtWidth = baseFont.getStringWidth(newsTxt) / 1000 * fontSize; } } - switch(alignment) - { + switch(alignment) { case 1: // Center Alignment - showTextAligned(font, sTxt, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); + showTextAligned(cb, font,alignment, sTxt, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); break; case 2: // Right Alignment - showTextAligned(font, sTxt, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); + showTextAligned(cb, font, alignment, sTxt, rightAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); break; case 0: // Left Alignment case 3: // Justified, only one text line - showTextAligned(font, sTxt, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); + showTextAligned(cb, font, alignment, sTxt, leftAux + leftMargin, this.pageSize.getUpperRightY() - bottomAux - topMargin - bottomMargin + startHeight); break; } } @@ -983,16 +851,15 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) } } - private void resolveTextStyling(PDPageContentStream contentStream, String text, float x, float y){ + private void resolveTextStyling(PDPageContentStream contentStream, String text, float x, float y, boolean isWrapped){ try { if (this.fontBold && this.fontItalic){ contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); - //contentStream.setTextMatrix(1, 0, .2f, 1, 7, 5); - //contentStream.setTextMatrix(1, 0, .2f, 1, 0, 0); contentStream.setTextMatrix(1, Math.tan(Math.toRadians(10)), 0, 1, 0, 0); contentStream.appendRawCommands("2 Tr\n"); contentStream.showText(text); + if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); contentStream.appendRawCommands("0 Tr\n"); contentStream.endText(); } else if (this.fontBold && !this.fontItalic){ @@ -1000,58 +867,107 @@ private void resolveTextStyling(PDPageContentStream contentStream, String text, contentStream.moveTextPositionByAmount(x, y); contentStream.appendRawCommands("2 Tr\n"); contentStream.showText(text); + if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); contentStream.appendRawCommands("0 Tr\n"); contentStream.endText(); } else if (!this.fontBold && this.fontItalic){ contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); - //contentStream.setTextMatrix(1, 0, .2f, 1, 7, 5); - //contentStream.setTextMatrix(1, 0, .2f, 1, 0, 0); contentStream.setTextMatrix(1, Math.tan(Math.toRadians(10)), 0, 1, 0, 0); contentStream.showText(text); + if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); contentStream.endText(); - contentStream.restoreGraphicsState(); } else { contentStream.beginText(); - contentStream.moveTextPositionByAmount(x, y); + contentStream.newLineAtOffset(x, y); contentStream.showText(text); + if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); contentStream.endText(); } } catch (Exception e) {} } - private void showTextAligned(PDType0Font font, String text, float x, float y){ - try (PDPageContentStream contentStream = new PDPageContentStream(document, document.getPage(page - 1), PDPageContentStream.AppendMode.APPEND, false, false)){ - contentStream.saveGraphicsState(); + private void showWrappedTextAligned(PDPageContentStream contentStream, PDType0Font font, int alignment, String text, float llx, float lly, float urx, float ury) { + try { contentStream.setFont(font, fontSize); - contentStream.setLeading(2); - resolveTextStyling(contentStream,text, x, y); - contentStream.restoreGraphicsState(); - } catch (Exception e) { System.err.println(e.getMessage()); } + + List lines = new ArrayList<>(); + String[] words = text.split(" "); + StringBuilder currentLine = new StringBuilder(); + for (String word : words) { + float currentLineWidth = font.getStringWidth(currentLine + " " + word) / 1000 * fontSize; + if (currentLineWidth < urx - llx) { + if (currentLine.length() > 0) { + currentLine.append(" "); + } + currentLine.append(word); + } else { + lines.add(currentLine.toString()); + currentLine.setLength(0); + currentLine.append(word); + } + } + lines.add(currentLine.toString()); + + float leading = lines.size() == 1 ? fontSize : 1.2f * fontSize; + float totalTextHeight = fontSize * lines.size() + leading * (lines.size() - 1); + float startY = lines.size() == 1 ? lly + (ury - lly - totalTextHeight) / 2 : lly + (ury - lly - totalTextHeight) / 2 + (lines.size() - 1) * (fontSize + leading) + font.getFontDescriptor().getDescent() / 1000 * fontSize; + + for (String line : lines) { + float lineWidth = font.getStringWidth(line) / 1000 * fontSize; + float startX; + + switch (alignment) { + case 1: // Center-aligned + startX = llx + (urx - llx - lineWidth) / 2; + break; + case 2: // Right-aligned + startX = urx - lineWidth; + break; + default: // Left-aligned & Justified, only one text line + startX = llx; + break; + } + + resolveTextStyling(contentStream, line, startX, startY, true); + startY -= leading; + } + } catch (Exception e) {} } - public void GxClearAttris() {} + private void showTextAligned(PDPageContentStream contentStream, PDType0Font font,int alignment, String text, float x, float y){ + try { + contentStream.setFont(font, fontSize); + contentStream.setNonStrokingColor(foreColor); + contentStream.setLeading((float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); + float textWidth = font.getStringWidth(text) / 1000 * fontSize; + switch (alignment) { + case 0: // Left-aligned + case 3: // Justified, only one text line + break; + case 1: // Center-aligned + x = x - textWidth / 2; + break; + case 2: // Right-aligned + x = x - textWidth; + break; + } + resolveTextStyling(contentStream,text, x, y,false); + } catch (Exception e) {} + } - public static final double PAGE_SCALE_Y = 20; - public static final double PAGE_SCALE_X = 20; - public static final double GX_PAGE_SCALE_Y_OLD = 15.45; - public static final double GX_PAGE_SCALE_Y = 14.4; - private static double TO_CM_SCALE =28.6; - public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) - { + public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { try { PPP = gxYPage[0]; loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - if(outputStream != null) - { + if(outputStream != null) { if (output.equalsIgnoreCase("PRN")) outputType = Const.OUTPUT_STREAM_PRINTER; else outputType = Const.OUTPUT_STREAM; } - else - { + else { if(output.equalsIgnoreCase("SCR")) outputType = Const.OUTPUT_SCREEN; else if(output.equalsIgnoreCase("PRN")) @@ -1060,23 +976,19 @@ else if(output.equalsIgnoreCase("PRN")) if(outputType == Const.OUTPUT_FILE) TemporaryFiles.getInstance().removeFileFromList(docName); - else - { + else { String tempPrefix = docName; String tempExtension = "pdf"; int tempIndex = docName.lastIndexOf('.'); - if(tempIndex != -1) - { + if(tempIndex != -1) { tempPrefix = docName.substring(0, tempIndex); tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); } docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); } - try - { + try { setOutputStream(new FileOutputStream(docName)); - }catch(IOException accessError) - { + }catch(IOException accessError) { accessError.printStackTrace(System.err); outputStream = new com.genexus.util.NullOutputStream(); outputType = Const.OUTPUT_FILE; @@ -1117,10 +1029,8 @@ else if(output.equalsIgnoreCase("PRN")) } } - private PDRectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) - { - if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) - { + private PDRectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { + if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) { if (length == 23818 && width == 16834) return PDRectangle.A3; else if (length == 16834 && width == 11909) @@ -1143,16 +1053,13 @@ else if (length == 15840 && width == 12240) return new PDRectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); } - public void GxEndDocument() - { + public void GxEndDocument() { try { - if(document.getNumberOfPages() == 0) - { + if(document.getNumberOfPages() == 0) { document.addPage(new PDPage(this.pageSize)); pages++; } - if (template != null) - { + if (template != null) { try{ template.beginText(); template.setFont(baseFont, fontSize); @@ -1171,8 +1078,7 @@ public void GxEndDocument() } catch (IOException e){ System.err.println(e.getMessage()); } } int copies = 1; - try - { + try { copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); @@ -1204,45 +1110,38 @@ public void GxEndDocument() dict.setName(COSName.DUPLEX, duplexValue.toString()); writer.setViewerPreferences(viewerPreferences); } - catch(Exception ex) - { + catch(Exception ex) { ex.printStackTrace(System.err); } String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); - if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) - { + if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { PDDocumentCatalog catalog = document.getDocumentCatalog(); StringBuffer jsActions = new StringBuffer(); jsActions.append("var pp = this.getPrintParams();\n"); String printerAux=printerSettings.getProperty(form, Const.PRINTER); String printer = replace(printerAux, "\\", "\\\\"); - if (printer!=null && !printer.equals("")) - { + if (printer!=null && !printer.equals("")) { jsActions.append("pp.printerName = \"" + printer + "\";\n"); } - if (fit) - { + if (fit) { jsActions.append("pp.pageHandling = pp.constants.handling.fit;\n"); } - else - { + else { jsActions.append("pp.pageHandling = pp.constants.handling.none;\n"); } - if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")) - { + if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")) { jsActions.append("pp.interactive = pp.constants.interactionLevel.automatic;\n"); for(int i = 0; i < copies; i++) { jsActions.append("this.print(pp);\n"); } } - else - { + else { jsActions.append("pp.interactive = pp.constants.interactionLevel.full;\n"); jsActions.append("this.print(pp);\n"); } @@ -1260,8 +1159,7 @@ public void GxEndDocument() try{ props.save(); } catch(IOException e) { ; } - switch(outputType) - { + switch(outputType) { case Const.OUTPUT_SCREEN: try{ outputStream.close(); } catch(IOException e) { } try{ showReport(docName, modal); } @@ -1272,8 +1170,7 @@ public void GxEndDocument() case Const.OUTPUT_PRINTER: try{ outputStream.close(); } catch(IOException e) { } try{ - if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) - { + if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) { printReport(docName, this.printerOutputMode == 1); } } catch(Exception e){ @@ -1292,8 +1189,7 @@ public void GxEndDocument() e.printStackTrace(System.err); } } - public void GxStartPage() - { + public void GxStartPage() { document.addPage(new PDPage(this.pageSize)); pages = pages + 1; page = page + 1; From 9f5fe137e0f544fe7fe353bb91e6a85300952eeb Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Fri, 21 Apr 2023 09:55:10 -0300 Subject: [PATCH 18/32] Code refactoring, GXPrintInit and text writing in pdfbox --- .../genexus/reports/GXReportPDFCommons.java | 65 ++++++++++++++++++- .../com/genexus/reports/PDFReportItext.java | 62 ++---------------- .../com/genexus/reports/PDFReportPDFBox.java | 64 ++---------------- 3 files changed, 76 insertions(+), 115 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 05bb606d2..9da5a63b7 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -53,6 +53,7 @@ import com.genexus.platform.NativeFunctions; import com.genexus.reports.fonts.Utilities; import com.genexus.webpanels.HttpContextWeb; +import com.genexus.util.TemporaryFiles; import java.awt.*; import java.io.*; @@ -498,7 +499,69 @@ public void GxClearAttris() {} //en el parámetro pageLength llega 16834 que esta en Twips (16834 = 1169*14.4). 1 twip = 1/1440 inch. //Con el valor anterior 15.45 estaba quedando un margen bottom fijo que no se podia eliminar (incluso seteando mb 0). protected static double TO_CM_SCALE = 28.6; // Escala CM -> metricas PDF (utilizado en el pageMargin) - public abstract boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex); + + private boolean preGxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex){ + try { + PPP = gxYPage[0]; + loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + + if(outputStream != null) { + if (output.equalsIgnoreCase("PRN")) + outputType = Const.OUTPUT_STREAM_PRINTER; + else + outputType = Const.OUTPUT_STREAM; + } + else { + if(output.equalsIgnoreCase("SCR")) + outputType = Const.OUTPUT_SCREEN; + else if(output.equalsIgnoreCase("PRN")) + outputType = Const.OUTPUT_PRINTER; + else outputType = Const.OUTPUT_FILE; + + if(outputType == Const.OUTPUT_FILE) + TemporaryFiles.getInstance().removeFileFromList(docName); + else { + String tempPrefix = docName; + String tempExtension = "pdf"; + int tempIndex = docName.lastIndexOf('.'); + if(tempIndex != -1) { + tempPrefix = docName.substring(0, tempIndex); + tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); + } + docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); + } + try { + setOutputStream(new FileOutputStream(docName)); + }catch(IOException accessError) { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream + accessError.printStackTrace(System.err); + outputStream = new com.genexus.util.NullOutputStream(); + outputType = Const.OUTPUT_FILE; // Hago esto para no tener lios con el Acrobat + } + } + printerOutputMode = mode; + + boolean ret; + ret = props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); + ret = props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); + ret = props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); + leftMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.LEFT_MARGIN)).doubleValue()); + topMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.TOP_MARGIN)).doubleValue()); + bottomMargin = (float) (Double.valueOf(props.getGeneralProperty(Const.BOTTOM_MARGIN)).doubleValue()); + + lineCapProjectingSquare = props.getGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE).equals("true"); + barcode128AsImage = props.getGeneralProperty(Const.BARCODE128_AS_IMAGE).equals("true"); + STYLE_DOTTED = parsePattern(props.getGeneralProperty(Const.STYLE_DOTTED)); + STYLE_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_DASHED)); + STYLE_LONG_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DASHED)); + STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); + + return true; + } catch (Exception e) {return false;} + } + + public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex){ + return preGxPrintInit(output, gxXPage, gxYPage, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + } public int getPageLines() { if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index 4e349ea6e..14dfafd9f 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -2,7 +2,6 @@ import java.awt.Color; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.StringReader; import java.util.*; @@ -11,7 +10,6 @@ import com.genexus.CommonUtil; import com.genexus.ModelContext; import com.genexus.platform.NativeFunctions; -import com.genexus.util.TemporaryFiles; import com.genexus.webpanels.HttpContextWeb; import com.lowagie.text.Document; import com.lowagie.text.DocumentException; @@ -971,59 +969,8 @@ private int columnAlignment(int alignment) { } public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { - PPP = gxYPage[0]; - loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - - if(outputStream != null) { - if (output.equalsIgnoreCase("PRN")) - outputType = Const.OUTPUT_STREAM_PRINTER; - else - outputType = Const.OUTPUT_STREAM; - } - else { - if(output.equalsIgnoreCase("SCR")) - outputType = Const.OUTPUT_SCREEN; - else if(output.equalsIgnoreCase("PRN")) - outputType = Const.OUTPUT_PRINTER; - else outputType = Const.OUTPUT_FILE; - - if(outputType == Const.OUTPUT_FILE) - TemporaryFiles.getInstance().removeFileFromList(docName); - else { - String tempPrefix = docName; - String tempExtension = "pdf"; - int tempIndex = docName.lastIndexOf('.'); - if(tempIndex != -1) { - tempPrefix = docName.substring(0, tempIndex); - tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); - } - docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); - } - try { - setOutputStream(new FileOutputStream(docName)); - }catch(IOException accessError) { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream - accessError.printStackTrace(System.err); - outputStream = new com.genexus.util.NullOutputStream(); - outputType = Const.OUTPUT_FILE; // Hago esto para no tener lios con el Acrobat - } - } - printerOutputMode = mode; - - boolean ret; - ret = props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); - ret = props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); - ret = props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); - leftMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.LEFT_MARGIN)).doubleValue()); - topMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.TOP_MARGIN)).doubleValue()); - bottomMargin = (float) (Double.valueOf(props.getGeneralProperty(Const.BOTTOM_MARGIN)).doubleValue()); - - lineCapProjectingSquare = props.getGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE).equals("true"); - barcode128AsImage = props.getGeneralProperty(Const.BARCODE128_AS_IMAGE).equals("true"); - STYLE_DOTTED = parsePattern(props.getGeneralProperty(Const.STYLE_DOTTED)); - STYLE_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_DASHED)); - STYLE_LONG_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DASHED)); - STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); - + boolean preResult = super.GxPrintInit(output, gxXPage, gxYPage, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); if (props.getBooleanGeneralProperty(Const.JUSTIFIED_TYPE_ALL, false)) @@ -1043,7 +990,10 @@ else if(output.equalsIgnoreCase("PRN")) init(); - return true; + if (!preResult) + return !preResult; + else + return true; } private com.lowagie.text.Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index ec9e68ea8..b27bacfe8 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -10,7 +10,6 @@ import com.genexus.CommonUtil; import com.genexus.ModelContext; import com.genexus.platform.NativeFunctions; -import com.genexus.util.TemporaryFiles; import com.genexus.webpanels.HttpContextWeb; import com.genexus.reports.fonts.PDFFont; import com.genexus.reports.fonts.PDFFontDescriptor; @@ -889,7 +888,6 @@ private void resolveTextStyling(PDPageContentStream contentStream, String text, private void showWrappedTextAligned(PDPageContentStream contentStream, PDType0Font font, int alignment, String text, float llx, float lly, float urx, float ury) { try { - contentStream.setFont(font, fontSize); List lines = new ArrayList<>(); String[] words = text.split(" "); @@ -935,10 +933,8 @@ private void showWrappedTextAligned(PDPageContentStream contentStream, PDType0Fo } catch (Exception e) {} } - private void showTextAligned(PDPageContentStream contentStream, PDType0Font font,int alignment, String text, float x, float y){ + private void showTextAligned(PDPageContentStream contentStream, PDType0Font font, int alignment, String text, float x, float y){ try { - contentStream.setFont(font, fontSize); - contentStream.setNonStrokingColor(foreColor); contentStream.setLeading((float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); float textWidth = font.getStringWidth(text) / 1000 * fontSize; switch (alignment) { @@ -958,58 +954,7 @@ private void showTextAligned(PDPageContentStream contentStream, PDType0Font font public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { try { - PPP = gxYPage[0]; - loadPrinterSettingsProps(iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); - - if(outputStream != null) { - if (output.equalsIgnoreCase("PRN")) - outputType = Const.OUTPUT_STREAM_PRINTER; - else - outputType = Const.OUTPUT_STREAM; - } - else { - if(output.equalsIgnoreCase("SCR")) - outputType = Const.OUTPUT_SCREEN; - else if(output.equalsIgnoreCase("PRN")) - outputType = Const.OUTPUT_PRINTER; - else outputType = Const.OUTPUT_FILE; - - if(outputType == Const.OUTPUT_FILE) - TemporaryFiles.getInstance().removeFileFromList(docName); - else { - String tempPrefix = docName; - String tempExtension = "pdf"; - int tempIndex = docName.lastIndexOf('.'); - if(tempIndex != -1) { - tempPrefix = docName.substring(0, tempIndex); - tempExtension = ((docName + " ").substring(tempIndex + 1)).trim(); - } - docName = TemporaryFiles.getInstance().getTemporaryFile(tempPrefix, tempExtension); - } - try { - setOutputStream(new FileOutputStream(docName)); - }catch(IOException accessError) { - accessError.printStackTrace(System.err); - outputStream = new com.genexus.util.NullOutputStream(); - outputType = Const.OUTPUT_FILE; - } - } - printerOutputMode = mode; - - boolean ret; - ret = props.setupGeneralProperty(Const.LEFT_MARGIN, Const.DEFAULT_LEFT_MARGIN); - ret = props.setupGeneralProperty(Const.TOP_MARGIN, Const.DEFAULT_TOP_MARGIN); - ret = props.setupGeneralProperty(Const.BOTTOM_MARGIN, Const.DEFAULT_BOTTOM_MARGIN); - leftMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.LEFT_MARGIN)).doubleValue()); - topMargin = (float) (TO_CM_SCALE * Double.valueOf(props.getGeneralProperty(Const.TOP_MARGIN)).doubleValue()); - bottomMargin = (float) (Double.valueOf(props.getGeneralProperty(Const.BOTTOM_MARGIN)).doubleValue()); - - lineCapProjectingSquare = props.getGeneralProperty(Const.LINE_CAP_PROJECTING_SQUARE).equals("true"); - barcode128AsImage = props.getGeneralProperty(Const.BARCODE128_AS_IMAGE).equals("true"); - STYLE_DOTTED = parsePattern(props.getGeneralProperty(Const.STYLE_DOTTED)); - STYLE_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_DASHED)); - STYLE_LONG_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DASHED)); - STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); + boolean preResult = super.GxPrintInit(output, gxXPage, gxYPage, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); runDirection = Integer.valueOf(props.getGeneralProperty(Const.RUN_DIRECTION)).intValue(); @@ -1022,7 +967,10 @@ else if(output.equalsIgnoreCase("PRN")) init(); - return true; + if (!preResult) + return !preResult; + else + return true; } catch (Exception e) { e.printStackTrace(System.err); return false; From b16d167585a173139dad5398044aeaeefa4aedfe Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Fri, 21 Apr 2023 11:00:46 -0300 Subject: [PATCH 19/32] text styling fixes: bold, italic and fore color --- .../com/genexus/reports/PDFReportPDFBox.java | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index b27bacfe8..2962171e1 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -21,6 +21,7 @@ import org.apache.pdfbox.pdmodel.font.*; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; import org.apache.pdfbox.pdmodel.interactive.viewerpreferences.PDViewerPreferences; import org.apache.pdfbox.util.Matrix; @@ -853,36 +854,33 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) private void resolveTextStyling(PDPageContentStream contentStream, String text, float x, float y, boolean isWrapped){ try { if (this.fontBold && this.fontItalic){ + contentStream.setStrokingColor(foreColor); + contentStream.setLineWidth(fontSize * 0.1f); + contentStream.setRenderingMode(RenderingMode.FILL_STROKE); contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); - contentStream.setTextMatrix(1, Math.tan(Math.toRadians(10)), 0, 1, 0, 0); - contentStream.appendRawCommands("2 Tr\n"); - contentStream.showText(text); - if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); - contentStream.appendRawCommands("0 Tr\n"); - contentStream.endText(); + contentStream.setTextMatrix(new Matrix(1, 0, 0.2f, 1, x + 0.2f * y, y)); + contentStream.newLineAtOffset(-0.2f * y, 0); } else if (this.fontBold && !this.fontItalic){ + contentStream.setStrokingColor(foreColor); + contentStream.setLineWidth(fontSize * 0.1f); + contentStream.setRenderingMode(RenderingMode.FILL_STROKE); contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); - contentStream.appendRawCommands("2 Tr\n"); - contentStream.showText(text); - if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); - contentStream.appendRawCommands("0 Tr\n"); - contentStream.endText(); } else if (!this.fontBold && this.fontItalic){ contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); - contentStream.setTextMatrix(1, Math.tan(Math.toRadians(10)), 0, 1, 0, 0); - contentStream.showText(text); - if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); - contentStream.endText(); + contentStream.setTextMatrix(new Matrix(1, 0, 0.2f, 1, x + 0.2f * y, y)); + contentStream.newLineAtOffset(-0.2f * y, 0); } else { contentStream.beginText(); contentStream.newLineAtOffset(x, y); - contentStream.showText(text); - if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); - contentStream.endText(); } + contentStream.showText(text); + if (isWrapped) contentStream.newLineAtOffset(-x, -(float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); + contentStream.endText(); + contentStream.setLineWidth(1f); // Default line width for PDFBox 2.0.27 + contentStream.setRenderingMode(RenderingMode.FILL); // Default text rendering mode for PDFBox 2.0.27 } catch (Exception e) {} } @@ -930,7 +928,7 @@ private void showWrappedTextAligned(PDPageContentStream contentStream, PDType0Fo resolveTextStyling(contentStream, line, startX, startY, true); startY -= leading; } - } catch (Exception e) {} + } catch (Exception e) {System.err.println(e.getMessage());} } private void showTextAligned(PDPageContentStream contentStream, PDType0Font font, int alignment, String text, float x, float y){ @@ -949,7 +947,7 @@ private void showTextAligned(PDPageContentStream contentStream, PDType0Font font break; } resolveTextStyling(contentStream,text, x, y,false); - } catch (Exception e) {} + } catch (Exception e) {System.err.println(e.getMessage());} } public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { From ce5e0a210d4cdde6552bd1a1766d22e8415e8175 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Tue, 25 Apr 2023 13:54:24 -0300 Subject: [PATCH 20/32] Logging update into l4j and font rework in pdfbox implementation --- .../genexus/reports/GXReportPDFCommons.java | 24 +- .../com/genexus/reports/PDFReportItext.java | 84 ++--- .../com/genexus/reports/PDFReportPDFBox.java | 304 ++++++------------ 3 files changed, 152 insertions(+), 260 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 9da5a63b7..2ad208152 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -54,6 +54,7 @@ import com.genexus.reports.fonts.Utilities; import com.genexus.webpanels.HttpContextWeb; import com.genexus.util.TemporaryFiles; +import org.apache.logging.log4j.Logger; import java.awt.*; import java.io.*; @@ -129,6 +130,8 @@ public int value(){ } protected static char alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; + protected static Logger log = org.apache.logging.log4j.LogManager.getLogger(GXReportPDFCommons.class); + /** Setea el OutputStream a utilizar * @param outputStream Stream a utilizar */ @@ -533,7 +536,7 @@ else if(output.equalsIgnoreCase("PRN")) try { setOutputStream(new FileOutputStream(docName)); }catch(IOException accessError) { // Si no se puede generar el archivo, muestro el stackTrace y seteo el stream como NullOutputStream - accessError.printStackTrace(System.err); + log.error("preGxPrintInit: failed to set output stream", accessError); outputStream = new com.genexus.util.NullOutputStream(); outputType = Const.OUTPUT_FILE; // Hago esto para no tener lios con el Acrobat } @@ -556,7 +559,10 @@ else if(output.equalsIgnoreCase("PRN")) STYLE_LONG_DOT_DASHED = parsePattern(props.getGeneralProperty(Const.STYLE_LONG_DOT_DASHED)); return true; - } catch (Exception e) {return false;} + } catch (Exception e) { + log.error("preGxPrintInit failed" , e); + return false; + } } public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex){ @@ -564,20 +570,19 @@ public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String i } public int getPageLines() { - if(DEBUG)DEBUG_STREAM.println("getPageLines: --> " + pageLines); + log.debug("getPageLines: --> " + pageLines); return pageLines; } public int getLineHeight() { - if(DEBUG)DEBUG_STREAM.println("getLineHeight: --> " + this.lineHeight); + log.debug("getLineHeight: --> " + this.lineHeight); return this.lineHeight; } public void setPageLines(int P_lines) { - if(DEBUG)DEBUG_STREAM.println("setPageLines: " + P_lines); + log.debug("setPageLines: " + P_lines); pageLines = P_lines; } public void setLineHeight(int lineHeight) { - - if(DEBUG)DEBUG_STREAM.println("setLineHeight: " + lineHeight); + log.debug("setLineHeight: " + lineHeight); this.lineHeight = lineHeight; } @@ -604,7 +609,7 @@ public void setM_bot(int M_bot) this.M_bot = M_bot; } - public abstract void GxEndPage(); + public void GxEndPage(){} public abstract void GxEndDocument(); @@ -639,7 +644,7 @@ public void GxSetDocName(String docName) { } if(this.docName.indexOf('.') < 0) this.docName += ".pdf"; - if(DEBUG)DEBUG_STREAM.println("GxSetDocName: '" + this.docName + "'"); + log.debug("GxSetDocName: '" + this.docName + "'"); } public boolean GxPrTextInit(String ouput, int nxPage[], int nyPage[], String psIniFile, String psForm, String sPrinter, int nMode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { @@ -685,7 +690,6 @@ public void cleanup() {} public void setMetrics(String fontName, boolean bold, boolean italic, int ascent, int descent, int height, int maxAdvance, int[] sizes) {} - /** Carga la tabla de substitutos */ protected void loadSubstituteTable() { diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index 14dfafd9f..de91eff24 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -40,12 +40,10 @@ public class PDFReportItext extends GXReportPDFCommons { private com.lowagie.text.Rectangle pageSize; // Contiene las dimensiones de la página - private Font font; private BaseFont baseFont; private Barcode barcode = null; private Document document; private PdfWriter writer; - private Paragraph chunk; private PdfTemplate template; private BaseFont templateFont; public boolean lineCapProjectingSquare = true; @@ -79,7 +77,6 @@ protected void init() private void drawRectangle(PdfContentByte cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) { - float[] dashPatternTop = getDashedPattern(styleTop); float[] dashPatternBottom = getDashedPattern(styleBottom); @@ -320,8 +317,8 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo } } cb.restoreState(); - - if(DEBUG)DEBUG_STREAM.println("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); + + log.debug("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); } public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { @@ -332,8 +329,8 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int float bottomAux = (float)convertScale(bottom); float leftAux = (float)convertScale(left); float topAux = (float)convertScale(top); - - if(DEBUG)DEBUG_STREAM.println("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + + log.debug("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); float x1, y1, x2, y2; @@ -362,9 +359,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { try { - //java.awt.Image image; com.lowagie.text.Image image; - com.lowagie.text.Image imageRef; try { if (documentImages != null && documentImages.containsKey(bitmap)) { image = documentImages.get(bitmap); @@ -380,13 +375,11 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); } // Si la ruta a la imagen NO es absoluta, en aplicaciones Web le agregamos al comienzo la ruta al root de la aplicación - // más la staticContentBaseURL si ésta es relativa. + // más la staticContentBaseURL si ésta es relativa. image = com.lowagie.text.Image.getInstance(defaultRelativePrepend + bitmap); - //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(defaultRelativePrepend + bitmap); if(image == null) { // Si all\uFFFDEno se encuentra la imagen, entonces la buscamos bajo el webAppDir (para mantener compatibilidad) bitmap = webAppDir + bitmap; image = com.lowagie.text.Image.getInstance(bitmap); - //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); } else { bitmap = defaultRelativePrepend + bitmap; @@ -394,7 +387,6 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom } else { image = com.lowagie.text.Image.getInstance(bitmap); - //image = com.genexus.uifactory.awt.AWTUIFactory.getImageNoWait(bitmap); } } } @@ -404,12 +396,11 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom } if (documentImages == null) { - documentImages = new ConcurrentHashMap(); + documentImages = new ConcurrentHashMap<>(); } documentImages.putIfAbsent(bitmap, image); - - if(DEBUG)DEBUG_STREAM.println("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + log.debug("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); if(image != null) { // Si la imagen NO se encuentra, no hago nada float rightAux = (float)convertScale(right); @@ -427,13 +418,13 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom } } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("GxDrawBitMap failed:", de); } catch(IOException ioe) { - System.err.println(ioe.getMessage()); + log.error("GxDrawBitMap failed:", ioe); } catch(Exception e) { - System.err.println(e.getMessage()); + log.error("GxDrawBitMap failed:", e); } } @@ -450,10 +441,10 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo { fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } - DEBUG_STREAM.println("GxAttris: "); - DEBUG_STREAM.println("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); - DEBUG_STREAM.println("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); - DEBUG_STREAM.println("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + log.debug("GxAttris: "); + log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); } if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { @@ -543,10 +534,10 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("GxAttris failed: ", de); } catch(IOException ioe) { - System.err.println(ioe.getMessage()); + log.error("GxAttris failed: ", ioe); } } @@ -578,10 +569,10 @@ public void setAsianFont(String fontName, String style) { } } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("setAsianFont failed: ", de); } catch(IOException ioe) { - System.err.println(ioe.getMessage()); + log.error("setAsianFont failed: ", ioe); } } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { @@ -697,12 +688,12 @@ else if (valign == VerticalAlign.BOTTOM.value()) Col.go(); } }catch(Exception de){ - System.out.println("ERROR printing HTML text " + de.getMessage()); + log.error("ERROR printing HTML text ", de.getMessage()); } } else if (barcode!=null) { - if(DEBUG)DEBUG_STREAM.println("Barcode: --> " + barcode.getClass().getName()); + log.debug("Barcode: --> " + barcode.getClass().getName()); try { barcode.setCode(sTxt); barcode.setTextAlignment(alignment); @@ -730,7 +721,6 @@ else if (valign == VerticalAlign.BOTTOM.value()) } barcode.setAltText(""); barcode.setBaseline(0); - //barcode.Size = 0; if (fontSize < Const.LARGE_FONT_SIZE) barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_SMALL_FONT); @@ -744,8 +734,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) document.add(imageCode); } catch (Exception ex) { - if(DEBUG)DEBUG_STREAM.println("Error generating Barcode: --> " + barcode.getClass().getName() + ex.getMessage()); - if(DEBUG)ex.printStackTrace (); + log.error("GxDrawText: Error generating Barcode " + barcode.getClass().getName(), ex); } } else { @@ -769,7 +758,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) document.add(rectangle); } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("backfill in GxDrawText failed: ", de); } } @@ -807,7 +796,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) document.add(underline); } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("fontUnderline in GxDrawText failed: ", de); } } @@ -845,7 +834,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("fontStrikethru in GxDrawText failed: ", de); } } @@ -886,7 +875,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) } catch (DocumentException ex) { - ex.printStackTrace(System.err); + log.error("wrap in GxDrawText failed: ", ex); } } else{ //no wrap @@ -1037,7 +1026,7 @@ public void GxEndDocument() { int copies = 1; try { copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); - if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); + log.debug("Setting number of copies to " + copies); writer.addViewerPreference(PdfName.NUMCOPIES, new PdfNumber(copies)); int duplex= Integer.parseInt(printerSettings.getProperty(form, Const.DUPLEX)); @@ -1049,8 +1038,8 @@ public void GxEndDocument() { case 4: duplexValue = PdfName.DUPLEXFLIPLONGEDGE;break; default: duplexValue = PdfName.NONE; } - if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue.toString()); - writer.addViewerPreference(PdfName.DUPLEX, duplexValue); + log.debug("Setting duplex to " + duplexValue.toString()); + writer.addViewerPreference(PdfName.DUPLEX, duplexValue); } catch(Exception ex) { ex.printStackTrace(System.err); @@ -1059,9 +1048,6 @@ public void GxEndDocument() { String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { - //writer.addJavaScript("if (this.external)\n");//Specifies whether the current document is being viewed in the Acrobat application or in an external window (such as a web browser). - //writer.addJavaScript("app.alert('SI es externa' + this.external);"); - writer.addJavaScript("var pp = this.getPrintParams();\n"); String printerAux=printerSettings.getProperty(form, Const.PRINTER); String printer = replace(printerAux, "\\", "\\\\"); @@ -1069,7 +1055,6 @@ public void GxEndDocument() { if (printer!=null && !printer.equals("")) { writer.addJavaScript("pp.printerName = \"" + printer + "\";\n"); } - if (fit) { writer.addJavaScript("pp.pageHandling = pp.constants.handling.fit;\n"); } @@ -1098,7 +1083,7 @@ public void GxEndDocument() { document.close(); - if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); + log.debug("GxEndDocument!"); try{ props.save(); } catch(IOException e) { ; } @@ -1121,11 +1106,11 @@ public void GxEndDocument() { printReport(docName, this.printerOutputMode == 1); } } catch(Exception e){ // Si no se puede mostrar el reporte - e.printStackTrace(); + log.error("GxEndDocument: failed to show report ", e); } break; case Const.OUTPUT_FILE: - try{ outputStream.close(); } catch(IOException e) { ; } // Cierro el archivo + try{ outputStream.close(); } catch(IOException e) { log.error("GxEndDocument: failed to save report to file ", e); } // Cierro el archivo break; case Const.OUTPUT_STREAM: case Const.OUTPUT_STREAM_PRINTER: @@ -1138,11 +1123,4 @@ public void GxStartPage() { pages = pages +1; } - public void GxEndPage() {} - - class FontProps { - public int horizontal; - public int vertical; - } - } diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 2962171e1..0030e031e 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -28,8 +28,9 @@ public class PDFReportPDFBox extends GXReportPDFCommons{ private PDRectangle pageSize; - private PDType1Font font; - private PDType0Font baseFont; + private PDFont font; + private PDFont baseFont; + private String baseFontName; //private BarcodeUtil barcode = null; por ahora no soportamos barcode private PDDocument document; private PDDocumentCatalog writer; @@ -159,7 +160,7 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl } cb.stroke(); } catch (IOException ioe) { - System.err.println(ioe.getMessage()); + log.error("drawRectangle failed: ", ioe); } } @@ -190,7 +191,7 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); } } catch (IOException ioe) { - System.err.println(ioe.getMessage()); + log.error("roundRectangle failed: ", ioe); } } @@ -273,9 +274,9 @@ public void GxDrawRect(int left, int top, int right, int bottom, int pen, int fo } cb.restoreGraphicsState(); - if(DEBUG)DEBUG_STREAM.println("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); + log.debug("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); } catch (Exception e) { - System.err.println(e.getMessage()); + log.error("GxDrawRect failed: ", e); } } @@ -288,7 +289,7 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int float leftAux = (float)convertScale(left); float topAux = (float)convertScale(top); - if(DEBUG)DEBUG_STREAM.println("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + log.debug("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); float x1, y1, x2, y2; @@ -313,8 +314,8 @@ public void GxDrawLine(int left, int top, int right, int bottom, int width, int cb.stroke(); cb.restoreGraphicsState(); - } catch (Exception e){ - System.err.println(e.getMessage()); + } catch (IOException ioe){ + log.error("GxDrawLine failed:", ioe); } } @@ -360,8 +361,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom } documentImages.putIfAbsent(bitmap, image); - - if(DEBUG)DEBUG_STREAM.println("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + log.debug("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); if(image != null) { float rightAux = (float)convertScale(right); @@ -378,8 +378,8 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom cb.drawImage(image, x, y, (rightAux - leftAux) * aspectRatio, (bottomAux - topAux) * aspectRatio); } } - catch(Exception e) { - System.err.println(e.getMessage()); + catch(IOException ioe) { + log.error("GxDrawBitMap failed:", ioe); } } @@ -395,10 +395,10 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo if (!originalFontName.equals(fontName)) { fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } - DEBUG_STREAM.println("GxAttris: "); - DEBUG_STREAM.println("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); - DEBUG_STREAM.println("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); - DEBUG_STREAM.println("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + log.debug("GxAttris: "); + log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); } if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { @@ -450,63 +450,15 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo fontName = PDFFont.base14[i][1+style].substring(1); break; } - COSDictionary dict = new COSDictionary(); - dict.setItem(COSName.TYPE, COSName.FONT); - dict.setItem(COSName.SUBTYPE, COSName.TYPE0); - dict.setItem(COSName.BASE_FONT, COSName.getPDFName(fontName)); - dict.setItem(COSName.ENCODING, COSName.WIN_ANSI_ENCODING); - dict.setItem(COSName.DESCENDANT_FONTS, new COSArray()); - dict.setBoolean(COSName.getPDFName("Embedded"), false); - baseFont = new PDType0Font(dict); } - - switch (fontName.trim().toUpperCase()) { - case "COURIER": - font = PDType1Font.COURIER; - break; - case "COURIER_BOLD": - font = PDType1Font.COURIER_BOLD; - break; - case "COURIER_BOLD_OBLIQUE": - font = PDType1Font.COURIER_BOLD_OBLIQUE; - break; - case "COURIER_OBLIQUE": - font = PDType1Font.COURIER_OBLIQUE; - break; - case "HELVETICA": - font = PDType1Font.HELVETICA; - break; - case "HELVETICA_BOLD": - font = PDType1Font.HELVETICA_BOLD; - break; - case "HELVETICA_BOLD_OBLIQUE": - font = PDType1Font.HELVETICA_BOLD_OBLIQUE; - break; - case "HELVETICA_OBLIQUE": - font = PDType1Font.HELVETICA_OBLIQUE; - break; - case "SYMBOL": - font = PDType1Font.SYMBOL; - break; - case "TIMES_BOLD": - font = PDType1Font.TIMES_BOLD; - break; - case "TIMES_BOLD_ITALIC": - font = PDType1Font.TIMES_BOLD_ITALIC; - break; - case "TIMES_ITALIC": - font = PDType1Font.TIMES_ITALIC; - break; - case "TIMES_ROMAN": - font = PDType1Font.TIMES_ROMAN; - break; - case "ZAPF_DINGBATS": - font = PDType1Font.ZAPF_DINGBATS; - break; - default: - font = PDType1Font.HELVETICA; - break; + baseFont = createPDType1FontFromName(fontName); + if (baseFont != null) + baseFontName = baseFont.getName(); + if (baseFont == null){ + baseFont = PDType0Font.load(document, new File(getFontLocation(fontName))); + baseFontName = fontName; } + } } else { @@ -526,116 +478,70 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo if (fontPath.equals("")) { fontPath = PDFFontDescriptor.getTrueTypeFontLocation(fontName, props); if (fontPath.equals("")) { - COSDictionary dict = new COSDictionary(); - dict.setItem(COSName.TYPE, COSName.FONT); - dict.setItem(COSName.SUBTYPE, COSName.TYPE0); - dict.setItem(COSName.FONT, COSName.HELV); - dict.setItem(COSName.BASE_FONT, COSName.HELV); - dict.setItem(COSName.ENCODING, COSName.WIN_ANSI_ENCODING); - dict.setItem(COSName.DESCENDANT_FONTS, new COSArray()); - dict.setItem(COSName.FONT_FILE2, COSNull.NULL); - baseFont = new PDType0Font(dict); + baseFont = PDType1Font.HELVETICA; + baseFontName = baseFont.getName(); foundFont = false; } } - if (foundFont) { - if (isEmbeddedFont(fontName)) { - baseFont = PDType0Font.load(document,new File(fontPath)); - } - else { - PDType0Font auxFont = PDType0Font.load(document,new File(fontPath)); - COSDictionary dict = new COSDictionary(auxFont.getCOSObject()); - baseFont = new PDType0Font(dict); - switch (style) { - case ",Bold": - baseFont.getCOSObject().setInt(COSName.FONT_WEIGHT, 700); - break; - case ",Italic": - baseFont.getFontMatrix().setValue(0,1,0.2f); - baseFont.getFontDescriptor().setItalic(true); - break; - case ",BoldItalic": - baseFont.getCOSObject().setInt(COSName.FONT_WEIGHT, 700); - baseFont.getFontMatrix().setValue(0, 1, 0.2f); - baseFont.getFontDescriptor().setItalic(true); - break; - default: break; - } - baseFont.getCOSObject().setItem(COSName.ENCODING, COSName.IDENTITY_H); - baseFont.getCOSObject().setItem(COSName.FONT_FILE2, COSNull.NULL); + if (foundFont){ + baseFont = createPDType1FontFromName(fontName); + if (baseFont != null) + baseFontName = baseFont.getName(); + else{ + baseFont = PDType0Font.load(document, new File(getFontLocation(fontName))); + baseFontName = fontName; } } } } catch(Exception e) { - System.err.println(e.getMessage()); + log.error("GxAttris failed: ", e); + } + } + + private static PDType1Font createPDType1FontFromName(String fontName) { + switch (fontName) { + case "Times-Roman": + return PDType1Font.TIMES_ROMAN; + case "Times-Bold": + return PDType1Font.TIMES_BOLD; + case "Times-Italic": + return PDType1Font.TIMES_ITALIC; + case "Times-BoldItalic": + return PDType1Font.TIMES_BOLD_ITALIC; + case "Helvetica": + return PDType1Font.HELVETICA; + case "Helvetica-Bold": + return PDType1Font.HELVETICA_BOLD; + case "Helvetica-Oblique": + return PDType1Font.HELVETICA_OBLIQUE; + case "Helvetica-BoldOblique": + return PDType1Font.HELVETICA_BOLD_OBLIQUE; + case "Courier": + return PDType1Font.COURIER; + case "Courier-Bold": + return PDType1Font.COURIER_BOLD; + case "Courier-Oblique": + return PDType1Font.COURIER_OBLIQUE; + case "Courier-BoldOblique": + return PDType1Font.COURIER_BOLD_OBLIQUE; + case "Symbol": + return PDType1Font.SYMBOL; + case "ZapfDingbats": + return PDType1Font.ZAPF_DINGBATS; + default: + return null; } } public void setAsianFont(String fontName, String style) { try { - COSDictionary fontDict = new COSDictionary(); - fontDict.setName(COSName.TYPE, "Font"); - fontDict.setName(COSName.SUBTYPE, "Type0"); - fontDict.setName(COSName.STYLE, style); - COSArray differencesArray = new COSArray(); - COSDictionary encodingDict = new COSDictionary(); - encodingDict.setName(COSName.TYPE, "Encoding"); - encodingDict.setName(COSName.BASE_ENCODING, "Identity-H"); - - if (style.equals("")) { - if (fontName.equals("Japanese")){ - fontDict.setName(COSName.BASE_FONT, "HeiseiMin-W3"); - differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H")); - } - if (fontName.equals("Japanese2")){ - fontDict.setName(COSName.BASE_FONT, "HeiseiKakuGo-W5"); - differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H")); - } - if (fontName.equals("SimplifiedChinese")){ - fontDict.setName(COSName.BASE_FONT, "STSong-Light"); - differencesArray.add(COSName.getPDFName("UniGB-UCS2-H")); - } - if (fontName.equals("TraditionalChinese")){ - fontDict.setName(COSName.BASE_FONT, "MHei-Medium"); - differencesArray.add(COSName.getPDFName("UniGB-UCS2-H")); - } - if (fontName.equals("Korean")) { - fontDict.setName(COSName.BASE_FONT, "HYSMyeongJo-Medium"); - differencesArray.add(COSName.getPDFName("UniKS-UCS2-H")); - } - fontDict.setItem(COSName.ENCODING, encodingDict); - fontDict.setItem(COSName.DESC, null); - baseFont = new PDType0Font(fontDict); - } - else { - if (fontName.equals("Japanese")){ - fontDict.setName(COSName.BASE_FONT, "HeiseiMin-W3" + style); - differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H")); - } - if (fontName.equals("Japanese2")){ - fontDict.setName(COSName.BASE_FONT, "HeiseiKakuGo-W5" + style); - differencesArray.add(COSName.getPDFName("UniJIS-UCS2-HW-H" + style)); - } - if (fontName.equals("SimplifiedChinese")){ - fontDict.setName(COSName.BASE_FONT, "STSong-Light"); - differencesArray.add(COSName.getPDFName("UniGB-UCS2-H" + style)); - } - if (fontName.equals("TraditionalChinese")){ - fontDict.setName(COSName.BASE_FONT, "MHei-Medium"); - differencesArray.add(COSName.getPDFName("UniGB-UCS2-H" + style)); - } - if (fontName.equals("Korean")) { - fontDict.setName(COSName.BASE_FONT, "HYSMyeongJo-Medium"); - differencesArray.add(COSName.getPDFName("UniKS-UCS2-H" + style)); - } - fontDict.setItem(COSName.ENCODING, encodingDict); - fontDict.setItem(COSName.DESC, null); - baseFont = new PDType0Font(fontDict); - } + String fontPath = getFontLocation(fontName); + baseFont = PDType0Font.load(document, new File(fontPath)); + baseFontName = fontName; } catch(Exception e) { - System.err.println(e.getMessage()); + log.error("setAsianFont failed: ", e); } } public void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) { @@ -650,10 +556,9 @@ public void GxDrawText(String sTxt, int left, int top, int right, int bottom, in sTxt = CommonUtil.rtrim(sTxt); - COSDictionary fontDict = baseFont.getCOSObject(); - COSDictionary newFontDict = new COSDictionary(fontDict); - newFontDict.setFloat(COSName.SIZE, fontSize); - PDType0Font font = new PDType0Font(newFontDict); + PDFont font = createPDType1FontFromName(baseFont.getFontDescriptor().getFontName()); + if (font == null) + font = PDType0Font.load(document, new File(getFontLocation(baseFontName))); cb.setFont(font,fontSize); cb.setNonStrokingColor(foreColor); @@ -675,7 +580,6 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; float topAux = (float)convertScale(top) + ((float)convertScale(bottom-top) - captionHeight)/2; - float startHeight = bottomAux - topAux - captionHeight; float leftAux = (float)convertScale(left); @@ -799,7 +703,7 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) contentStream.transform(Matrix.getTranslateInstance(leftAux + leftMargin, leftAux + leftMargin)); contentStream.drawForm(form); contentStream.close(); - templateFont = baseFont; + templateFont = new PDType0Font(baseFont.getCOSObject()); templateFontSize = fontSize; templateColorFill = foreColor; return; @@ -846,8 +750,8 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) } } } - } catch (Exception e){ - System.err.println(e.getMessage()); + } catch (IOException ioe){ + log.error("GxDrawText failed: ", ioe); } } @@ -855,7 +759,7 @@ private void resolveTextStyling(PDPageContentStream contentStream, String text, try { if (this.fontBold && this.fontItalic){ contentStream.setStrokingColor(foreColor); - contentStream.setLineWidth(fontSize * 0.1f); + contentStream.setLineWidth(fontSize * 0.05f); contentStream.setRenderingMode(RenderingMode.FILL_STROKE); contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); @@ -863,7 +767,7 @@ private void resolveTextStyling(PDPageContentStream contentStream, String text, contentStream.newLineAtOffset(-0.2f * y, 0); } else if (this.fontBold && !this.fontItalic){ contentStream.setStrokingColor(foreColor); - contentStream.setLineWidth(fontSize * 0.1f); + contentStream.setLineWidth(fontSize * 0.05f); contentStream.setRenderingMode(RenderingMode.FILL_STROKE); contentStream.beginText(); contentStream.moveTextPositionByAmount(x, y); @@ -881,12 +785,13 @@ private void resolveTextStyling(PDPageContentStream contentStream, String text, contentStream.endText(); contentStream.setLineWidth(1f); // Default line width for PDFBox 2.0.27 contentStream.setRenderingMode(RenderingMode.FILL); // Default text rendering mode for PDFBox 2.0.27 - } catch (Exception e) {} + } catch (IOException ioe) { + log.error("failed to apply text styling: ", ioe); + } } - private void showWrappedTextAligned(PDPageContentStream contentStream, PDType0Font font, int alignment, String text, float llx, float lly, float urx, float ury) { + private void showWrappedTextAligned(PDPageContentStream contentStream, PDFont font, int alignment, String text, float llx, float lly, float urx, float ury) { try { - List lines = new ArrayList<>(); String[] words = text.split(" "); StringBuilder currentLine = new StringBuilder(); @@ -928,10 +833,12 @@ private void showWrappedTextAligned(PDPageContentStream contentStream, PDType0Fo resolveTextStyling(contentStream, line, startX, startY, true); startY -= leading; } - } catch (Exception e) {System.err.println(e.getMessage());} + } catch (IOException ioe) { + log.error("failed to draw wrapped text: ", ioe); + } } - private void showTextAligned(PDPageContentStream contentStream, PDType0Font font, int alignment, String text, float x, float y){ + private void showTextAligned(PDPageContentStream contentStream, PDFont font, int alignment, String text, float x, float y){ try { contentStream.setLeading((float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue())); float textWidth = font.getStringWidth(text) / 1000 * fontSize; @@ -947,7 +854,9 @@ private void showTextAligned(PDPageContentStream contentStream, PDType0Font font break; } resolveTextStyling(contentStream,text, x, y,false); - } catch (Exception e) {System.err.println(e.getMessage());} + } catch (IOException ioe) { + log.error("failed to draw aligned text: ", ioe); + } } public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { @@ -970,7 +879,7 @@ public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String i else return true; } catch (Exception e) { - e.printStackTrace(System.err); + log.error("GxPrintInit failed" , e); return false; } } @@ -1021,12 +930,14 @@ public void GxEndDocument() { } template.close(); - } catch (IOException e){ System.err.println(e.getMessage()); } + } catch (IOException e){ + log.error("GxEndDocument: failed to apply template" , e);; + } } int copies = 1; try { copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); - if(DEBUG)DEBUG_STREAM.println("Setting number of copies to " + copies); + log.debug("Setting number of copies to " + copies); writer = document.getDocumentCatalog(); @@ -1047,7 +958,7 @@ public void GxEndDocument() { case 4: duplexValue = COSName.DUPLEX; break; default: duplexValue = COSName.NONE; } - if(DEBUG)DEBUG_STREAM.println("Setting duplex to " + duplexValue); + log.debug("Setting duplex to " + duplexValue); writer = document.getDocumentCatalog(); dict = writer.getViewerPreferences().getCOSObject(); if (dict == null) {dict = new COSDictionary();} @@ -1056,8 +967,8 @@ public void GxEndDocument() { dict.setName(COSName.DUPLEX, duplexValue.toString()); writer.setViewerPreferences(viewerPreferences); } - catch(Exception ex) { - ex.printStackTrace(System.err); + catch(Exception e) { + log.error("GxEndDocument: failed to apply viewer preferences ", e); } String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); @@ -1097,11 +1008,11 @@ public void GxEndDocument() { try { document.save(outputStream); document.close(); - } catch (IOException e) { - System.err.println(e.getMessage()); + } catch (IOException ioe) { + log.error("GxEndDocument: failed to save document to the output stream", ioe); } - if(DEBUG)DEBUG_STREAM.println("GxEndDocument!"); + log.debug("GxEndDocument!"); try{ props.save(); } catch(IOException e) { ; } @@ -1110,7 +1021,7 @@ public void GxEndDocument() { try{ outputStream.close(); } catch(IOException e) { } try{ showReport(docName, modal); } catch(Exception e) { - e.printStackTrace(); + log.error("GxEndDocument: failed to show report ", e); } break; case Const.OUTPUT_PRINTER: @@ -1120,11 +1031,11 @@ public void GxEndDocument() { printReport(docName, this.printerOutputMode == 1); } } catch(Exception e){ - e.printStackTrace(); + log.error("GxEndDocument: failed to print report ", e); } break; case Const.OUTPUT_FILE: - try{ outputStream.close(); } catch(IOException e) { ; } + try{ outputStream.close(); } catch (IOException e) { log.error("GxEndDocument: failed to save report to file ", e); } break; case Const.OUTPUT_STREAM: case Const.OUTPUT_STREAM_PRINTER: @@ -1132,7 +1043,7 @@ public void GxEndDocument() { } outputStream = null; } catch (Exception e){ - e.printStackTrace(System.err); + log.error("GxEndDocument failed: ", e);; } } public void GxStartPage() { @@ -1141,5 +1052,4 @@ public void GxStartPage() { page = page + 1; } - public void GxEndPage() {} } \ No newline at end of file From 08e9060e1a06e0fd73439bde4127b7d225f6f6aa Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 26 Apr 2023 09:57:25 -0300 Subject: [PATCH 21/32] GxDrawBitMap now supports all possible bitmap locations --- java/src/main/java/com/genexus/GXutil.java | 11 ++++++++++- java/src/main/java/com/genexus/GxImageUtil.java | 2 +- .../java/com/genexus/reports/GXReportPDFCommons.java | 4 ---- .../java/com/genexus/reports/PDFReportPDFBox.java | 6 +++--- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/java/src/main/java/com/genexus/GXutil.java b/java/src/main/java/com/genexus/GXutil.java index dbae021f1..cf4a3c265 100644 --- a/java/src/main/java/com/genexus/GXutil.java +++ b/java/src/main/java/com/genexus/GXutil.java @@ -1568,7 +1568,16 @@ public static String blobFromBytes(byte[] bytesString) gxFile.fromBytes(bytesString); com.genexus.webpanels.BlobsCleaner.getInstance().addBlobFile(filePath); return filePath; - } + } + + public static String blobFromBytes(byte[] bytesString, String extension) + { + String filePath = Preferences.getDefaultPreferences().getBLOB_PATH() + com.genexus.PrivateUtilities.getTempFileName(extension); + com.genexus.util.GXFile gxFile = new com.genexus.util.GXFile(filePath); + gxFile.fromBytes(bytesString); + com.genexus.webpanels.BlobsCleaner.getInstance().addBlobFile(filePath); + return filePath; + } public static java.util.UUID strToGuid(String value) { diff --git a/java/src/main/java/com/genexus/GxImageUtil.java b/java/src/main/java/com/genexus/GxImageUtil.java index 975c27f6a..03b11d2ef 100644 --- a/java/src/main/java/com/genexus/GxImageUtil.java +++ b/java/src/main/java/com/genexus/GxImageUtil.java @@ -126,7 +126,7 @@ private static String writeImage(BufferedImage croppedImage, String destinationF } else { outStream.flush(); byte[] imageInByte = outStream.toByteArray(); - return GXutil.blobFromBytes(imageInByte); + return GXutil.blobFromBytes(imageInByte,CommonUtil.getFileType(newFileName)); } } } diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 2ad208152..29ed5e179 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -62,7 +62,6 @@ public abstract class GXReportPDFCommons implements IReportHandler{ protected int lineHeight, pageLines; - protected int pageOrientation; protected boolean fontUnderline; protected boolean fontStrikethru; protected int fontSize; @@ -75,7 +74,6 @@ public abstract class GXReportPDFCommons implements IReportHandler{ protected ParseINI printerSettings; protected String form; protected Vector stringTotalPages; - protected boolean isPageDirty; protected int outputType = -1; protected int printerOutputMode = -1; protected boolean modal = false; @@ -88,8 +86,6 @@ public abstract class GXReportPDFCommons implements IReportHandler{ protected static String defaultRelativePrependINI = null; protected static String webAppDir = null; public static boolean DEBUG = false; - protected int currLine; - protected int lastLine = 0; private static String predefinedSearchPath = ""; protected float leftMargin; protected float topMargin; diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 0030e031e..5feedd103 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -16,6 +16,7 @@ import com.genexus.reports.fonts.Type1FontMetrics; import org.apache.pdfbox.cos.*; +import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.pdmodel.*; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.*; @@ -28,7 +29,6 @@ public class PDFReportPDFBox extends GXReportPDFCommons{ private PDRectangle pageSize; - private PDFont font; private PDFont baseFont; private String baseFontName; //private BarcodeUtil barcode = null; por ahora no soportamos barcode @@ -55,7 +55,7 @@ protected void init() { document = new PDDocument(); } catch(Exception e) { - System.err.println(e.getMessage()); + log.error("failed to initialize new PDFBox document: ", e); } } @@ -353,7 +353,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom } catch(java.lang.IllegalArgumentException ex) { URL url= new java.net.URL(bitmap); - image = PDImageXObject.createFromFile(url.toString(),document); + image = PDImageXObject.createFromByteArray(document, IOUtils.toByteArray(url.openStream()),bitmap); } if (documentImages == null) { From 22be488f754780d2b40618557ac15b136842c70f Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Thu, 27 Apr 2023 14:11:39 -0300 Subject: [PATCH 22/32] barcode support in pdfbox implementation --- java/pom.xml | 5 ++ .../com/genexus/reports/PDFReportPDFBox.java | 68 ++++++++++++++++--- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/java/pom.xml b/java/pom.xml index 7d4ceb620..c30533025 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -115,6 +115,11 @@ pdfbox 2.0.27 + + com.google.zxing + core + 3.5.1 + com.sap.conn.jco sapjco3 diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 5feedd103..a3229d8b2 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -1,6 +1,7 @@ package com.genexus.reports; import java.awt.Color; +import java.awt.image.BufferedImage; import java.io.*; import java.net.URL; import java.util.ArrayList; @@ -15,12 +16,16 @@ import com.genexus.reports.fonts.PDFFontDescriptor; import com.genexus.reports.fonts.Type1FontMetrics; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.oned.Code128Writer; import org.apache.pdfbox.cos.*; import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.pdmodel.*; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.*; import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject; +import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; import org.apache.pdfbox.pdmodel.interactive.action.PDActionJavaScript; @@ -31,7 +36,8 @@ public class PDFReportPDFBox extends GXReportPDFCommons{ private PDRectangle pageSize; private PDFont baseFont; private String baseFontName; - //private BarcodeUtil barcode = null; por ahora no soportamos barcode + private BitMatrix barcode = null; + private String barcodeType = null; private PDDocument document; private PDDocumentCatalog writer; private PDPageContentStream template; @@ -401,12 +407,9 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); } - if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { - // Por ahora no soportamos barcode - } - else { - // Por ahora no soportamos barcode - } + if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) + barcodeType = "barcode128"; + this.fontUnderline = fontUnderline; this.fontStrikethru = fontStrikethru; this.fontSize = fontSize; @@ -588,11 +591,56 @@ else if (valign == PDFReportPDFBox.VerticalAlign.BOTTOM.value()) boolean autoResize = (align & 256) == 256; if (htmlformat == 1) { - //Por ahora no soportamos la impresion de HTML + //As for now, HTML printing is not supported } else - if (1 == 2){ //(barcode!=null) - //Por ahora no soportamos la impresion de barcodes + if (barcodeType != null){ + log.debug("Barcode: --> " + barcode.getClass().getName()); + try { + PDRectangle rectangle = new PDRectangle(); + switch (alignment) { + case 1: // Center Alignment + rectangle.setLowerLeftX( (leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2); + rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin); + rectangle.setUpperRightX((leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2); + rectangle.setUpperRightY(this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 2: // Right Alignment + rectangle.setLowerLeftX( rightAux + leftMargin - rectangleWidth); + rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin); + rectangle.setUpperRightX(rightAux + leftMargin); + rectangle.setUpperRightY(this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 0: // Left Alignment + rectangle.setLowerLeftX( leftAux + leftMargin); + rectangle.setLowerLeftY(this.pageSize.getUpperRightY() - (float)convertScale(bottom) - topMargin - bottomMargin); + rectangle.setUpperRightX(leftAux + leftMargin + rectangleWidth); + rectangle.setUpperRightY(this.pageSize.getUpperRightY() - (float)convertScale(top) - topMargin - bottomMargin); + break; + } + if (barcodeType.equals("barcode128")){ + Code128Writer barcodeWriter = new Code128Writer(); + barcode = barcodeWriter.encode(sTxt, BarcodeFormat.CODE_128, Math.round(rectangle.getWidth()), Math.round(rectangle.getHeight())); + } + + BufferedImage imageCode = new BufferedImage(barcode.getWidth(), barcode.getHeight(), BufferedImage.TYPE_INT_RGB); + for (int x = 0; x < barcode.getWidth(); x++) + for (int y = 0; y < barcode.getHeight(); y++) { + int color; + if (foreColor == null || backColor == null) + color = Color.BLACK.getRGB(); + else + color = barcode.get(x, y) ? foreColor.getRGB() : backColor.getRGB(); + imageCode.setRGB(x, y, color); + } + float scale = Math.min(rectangle.getHeight() / imageCode.getHeight(), 1.0f); + float newImageWidth = imageCode.getWidth() * scale; + float newImageHeight = imageCode.getHeight() * scale; + cb.drawImage(LosslessFactory.createFromImage(document, imageCode),leftAux + leftMargin, rectangle.getLowerLeftY(),newImageWidth, newImageHeight); + } + catch (Exception ex) { + log.error("GxDrawText: Error generating Barcode " + barcode.getClass().getName(), ex); + } } else { From bfabaf95042ab03fe396e6be3f839a7a348984cd Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Thu, 4 May 2023 14:14:25 -0300 Subject: [PATCH 23/32] Fixed remaining logging mistakes plus code prettify --- .../com/genexus/reports/PDFReportItext.java | 31 +++++++------------ .../com/genexus/reports/PDFReportPDFBox.java | 1 - 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext.java index de91eff24..1dbe02473 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext.java @@ -51,22 +51,20 @@ public class PDFReportItext extends GXReportPDFCommons ConcurrentHashMap documentImages; public int runDirection = PdfWriter.RUN_DIRECTION_LTR; - public PDFReportItext(ModelContext context) - { + public PDFReportItext(ModelContext context) { super(context); document = null; pageSize = null; documentImages = new ConcurrentHashMap<>(); } - protected void init() - { + protected void init() { Document.compress = true; try { writer = PdfWriter.getInstance(document, outputStream); } catch(DocumentException de) { - System.err.println(de.getMessage()); + log.error("failed to initialize document: ", de); } document.open(); } @@ -189,8 +187,7 @@ private void drawRectangle(PdfContentByte cb, float x, float y, float w, float h else { cb.lineTo(x, y + radioBL); } - if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) - { + if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) { cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); } } @@ -437,8 +434,7 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo } if(DEBUG) { String fontSubstitute = ""; - if (!originalFontName.equals(fontName)) - { + if (!originalFontName.equals(fontName)) { fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } log.debug("GxAttris: "); @@ -828,12 +824,10 @@ else if (valign == VerticalAlign.BOTTOM.value()) break; } underline.setBackgroundColor(foreColor); - try - { + try { document.add(underline); } - catch(DocumentException de) - { + catch(DocumentException de) { log.error("fontStrikethru in GxDrawText failed: ", de); } } @@ -873,8 +867,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) try{ DrawColumnText(cb, llx, lly, urx, ury, p, leading, runDirection, valign, alignment); } - catch (DocumentException ex) - { + catch (DocumentException ex) { log.error("wrap in GxDrawText failed: ", ex); } } @@ -911,8 +904,7 @@ else if (valign == VerticalAlign.BOTTOM.value()) boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ return super.pageHeightExceeded(bottomAux,drawingPageHeight); } - ColumnText SimulateDrawColumnText(PdfContentByte cb, Rectangle rect, Paragraph p, float leading, int runDirection, int alignment) throws DocumentException - { + ColumnText SimulateDrawColumnText(PdfContentByte cb, Rectangle rect, Paragraph p, float leading, int runDirection, int alignment) throws DocumentException { ColumnText Col = new ColumnText(cb); Col.setRunDirection(runDirection); Col.setAlignment(alignment); @@ -1042,7 +1034,7 @@ public void GxEndDocument() { writer.addViewerPreference(PdfName.DUPLEX, duplexValue); } catch(Exception ex) { - ex.printStackTrace(System.err); + log.error("GxEndDocument failed to apply viewer preferences: ", ex); } String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); @@ -1066,8 +1058,7 @@ public void GxEndDocument() { writer.addJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n"); //No print dialog is displayed. During printing a progress monitor and cancel //dialog is displayed and removed automatically when printing is complete. - for(int i = 0; i < copies; i++) - { + for(int i = 0; i < copies; i++) { writer.addJavaScript("this.print(pp);\n"); } } diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index a3229d8b2..1fb4ceeaa 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -975,7 +975,6 @@ public void GxEndDocument() { try (PDPageContentStream templatePainter = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,false)) { templatePainter.drawForm(formXObjecttemplate); } - } template.close(); } catch (IOException e){ From 73a9d02b78cf9ea8cef252a0fa36b7664a0e9483 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Tue, 16 May 2023 09:55:10 -0300 Subject: [PATCH 24/32] iText7 support --- java/pom.xml | 11 + .../java/com/genexus/reports/GXReport.java | 175 ++-- .../genexus/reports/GXReportPDFCommons.java | 9 +- ...FReportItext.java => PDFReportItext2.java} | 4 +- .../com/genexus/reports/PDFReportItext7.java | 969 ++++++++++++++++++ .../com/genexus/webpanels/GXWebReport.java | 50 +- 6 files changed, 1067 insertions(+), 151 deletions(-) rename java/src/main/java/com/genexus/reports/{PDFReportItext.java => PDFReportItext2.java} (99%) create mode 100644 java/src/main/java/com/genexus/reports/PDFReportItext7.java diff --git a/java/pom.xml b/java/pom.xml index c30533025..125334849 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -105,6 +105,17 @@ + + com.itextpdf + itext7-core + 7.2.5 + pom + + + com.itextpdf + html2pdf + 4.0.5 + com.lowagie itextasian diff --git a/java/src/main/java/com/genexus/reports/GXReport.java b/java/src/main/java/com/genexus/reports/GXReport.java index 8b896005f..35e3939ad 100644 --- a/java/src/main/java/com/genexus/reports/GXReport.java +++ b/java/src/main/java/com/genexus/reports/GXReport.java @@ -4,70 +4,68 @@ import com.genexus.ModelContext; import com.genexus.ProcessInterruptedException; -public abstract class GXReport extends GXProcedure -{ +import org.apache.logging.log4j.Logger; + +public abstract class GXReport extends GXProcedure { protected static final int OUTPUT_RVIEWER = 1; protected static final int OUTPUT_PDF = 2; - // Tiene que ser protected porque se pasa como par�metro en los reports protected GXReportMetadata reportMetadata; protected IReportHandler reportHandler; - protected int lineHeight; protected int Gx_line; protected int P_lines; protected int gxXPage; protected int gxYPage; protected int Gx_page; - protected String Gx_out = ""; // Esto est� asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask. + protected String Gx_out = ""; // Esto esto asi porque no me pude deshacer de una comparacion contra Gx_out antes del ask. + + protected static Logger log = org.apache.logging.log4j.LogManager.getLogger(GXReport.class); public GXReport(int remoteHandle, ModelContext context, String location) { super(remoteHandle, context, location); } - public GXReport(boolean inNewUTL, int remoteHandle, ModelContext context, String location) - { + public GXReport(boolean inNewUTL, int remoteHandle, ModelContext context, String location) { super(inNewUTL, remoteHandle, context, location); } - public static byte openGXReport(String document) - { - if(document.toLowerCase().endsWith(".pdf")) - { // Si es un .pdf - try - { - PDFReportItext.showReport(document, false); - }catch(Exception e) - { - System.err.println(e.toString()); + public static byte openGXReport(String document) { + if(document.toLowerCase().endsWith(".pdf")) { // Si es un .pdf + try { + String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); + if (implementation.equals("ITEXT2")) + PDFReportItext2.showReport(document, false); + else if (implementation.equals("ITEXT7")) + PDFReportItext7.showReport(document, false); + else + PDFReportPDFBox.showReport(document, false); + } catch(Exception e) { + log.error("GXReport failed to open report " + document + " : ", e); return -1; } - }else - { + } else { GXReportViewerThreaded.GxOpenDoc(document); } return 0; } - protected void setPrintAtClient() + protected void setPrintAtClient() { setPrintAtClient(""); } - - protected void setPrintAtClient(String printerRule) - { - String blobPath = com.genexus.Preferences.getDefaultPreferences().getBLOB_PATH(); - String fileName = com.genexus.PrivateUtilities.getTempFileName(blobPath, "clientReport", getOutputType() == OUTPUT_PDF ? "pdf":"gxr"); + + protected void setPrintAtClient(String printerRule) { + String blobPath = com.genexus.Preferences.getDefaultPreferences().getBLOB_PATH(); + String fileName = com.genexus.PrivateUtilities.getTempFileName(blobPath, "clientReport", getOutputType() == OUTPUT_PDF ? "pdf":"gxr"); - getPrinter().GxSetDocName(fileName); - getPrinter().GxSetDocFormat("GXR"); - if (httpContext != null) - { - httpContext.printReportAtClient(fileName, printerRule); - } - com.genexus.webpanels.BlobsCleaner.getInstance().addBlobFile(fileName); - } + getPrinter().GxSetDocName(fileName); + getPrinter().GxSetDocFormat("GXR"); + if (httpContext != null) + httpContext.printReportAtClient(fileName, printerRule); + com.genexus.webpanels.BlobsCleaner.getInstance().addBlobFile(fileName); + } public void setPrinter(IReportHandler reportHandler) { @@ -84,53 +82,29 @@ public IReportHandler getPrinter() } else if (getOutputType() == OUTPUT_PDF) { - reportHandler = new PDFReportItext(context); - - try - { - ((PDFReportItext) reportHandler).setOutputStream(getOutputStream()); - } - catch (Exception e) - { - } + try { + String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); + if (implementation.equals("ITEXT2")) + reportHandler = new PDFReportPDFBox(context); + else if (implementation.equals("ITEXT7")) + reportHandler = new PDFReportItext7(context); + else + reportHandler = new PDFReportPDFBox(context); + ((GXReportPDFCommons) reportHandler).setOutputStream(httpContext.getOutputStream()); + } catch (Exception e) {} } - else - { + else { throw new RuntimeException("Unrecognized report type: " + getOutputType()); } } - return reportHandler; } -/* - public String format(String value, String picture) - { - return PictureFormatter.format(value, picture); - } - - public String format(long value, String picture) - { - return localUtil.format(value, picture); - } - - public String format(java.util.Date value, String picture) - { - return localUtil.format(value, picture); - } - - public String format(double value, String picture) - { - return localUtil.format(value, picture); - } -*/ - protected void GxEndPage() throws ProcessInterruptedException - { + protected void GxEndPage() throws ProcessInterruptedException { if (reportHandler != null) reportHandler.GxEndPage(); } - protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) - { + protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { int x[] = {gxXPage}; int y[] = {gxYPage}; @@ -143,8 +117,7 @@ protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, Strin return ret; } - protected boolean initPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) - { + protected boolean initPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { int x[] = {gxXPage}; int y[] = {gxYPage}; @@ -157,83 +130,59 @@ protected boolean initPrinter(String output, int gxXPage, int gxYPage, String in return ret; } - protected void endPrinter() - { - try - { + protected void endPrinter() { + try { getPrinter().GxEndPrinter(); waitPrinterEnd(); - } - catch (Exception e) - { - } + } catch (Exception e) {} } - protected void waitPrinterEnd() - { - if (reportHandler != null && Gx_out.equals("SCR") && reportHandler.getModal()) - { - while (reportHandler.GxIsAlive()); - } - -/* IGUIContext ctx = context.getGUIContext(); - if (ctx instanceof com.genexus.ui.GUIContext) - { - ((com.genexus.ui.GUIContext) ctx).getWorkpanel().setFocus(); + protected void waitPrinterEnd() { + if (reportHandler != null && Gx_out.equals("SCR") && reportHandler.getModal()) { + while (reportHandler.GxIsAlive()); } -*/ } - protected int getOutputType() - { + protected int getOutputType() { return OUTPUT_RVIEWER; } - protected java.io.OutputStream getOutputStream() - { + protected java.io.OutputStream getOutputStream() { throw new RuntimeException("Output stream not set"); } //M�todos para la implementaci�n de reportes din�micos - - protected void loadReportMetadata(String name) - { + + protected void loadReportMetadata(String name) { reportMetadata = new GXReportMetadata(name, getPrinter()); reportMetadata.load(); } - protected int GxDrawDynamicGetPrintBlockHeight(int printBlock) - { + protected int GxDrawDynamicGetPrintBlockHeight(int printBlock) { return reportMetadata.GxDrawGetPrintBlockHeight(printBlock); } - protected void GxDrawDynamicText(int printBlock, int controlId, int Gx_line) - { + protected void GxDrawDynamicText(int printBlock, int controlId, int Gx_line) { reportMetadata.GxDrawText(printBlock, controlId, Gx_line); } - protected void GxDrawDynamicText(int printBlock, int controlId, String value, int Gx_line) - { + protected void GxDrawDynamicText(int printBlock, int controlId, String value, int Gx_line) { reportMetadata.GxDrawText(printBlock, controlId, Gx_line, value); } - protected void GxDrawDynamicLine(int printBlock, int controlId, int Gx_line) - { + protected void GxDrawDynamicLine(int printBlock, int controlId, int Gx_line) { reportMetadata.GxDrawLine(printBlock, controlId, Gx_line); } - protected void GxDrawDynamicRect(int printBlock, int controlId, int Gx_line) - { + protected void GxDrawDynamicRect(int printBlock, int controlId, int Gx_line) { reportMetadata.GxDrawRect(printBlock, controlId, Gx_line); } - protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int Gx_line) - { + protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int Gx_line) { reportMetadata.GxDrawBitMap(printBlock, controlId, Gx_line, value, 0); } - protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int aspectRatio, int Gx_line) - { + protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int aspectRatio, int Gx_line) { reportMetadata.GxDrawBitMap(printBlock, controlId, Gx_line, value, aspectRatio); } } diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 29ed5e179..c97c33979 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -149,8 +149,7 @@ protected static String getAcrobatLocation() throws Exception { } // Primero debo obtener la ubicación + ejecutable del Acrobat String acrobatLocation = props.getGeneralProperty(Const.ACROBAT_LOCATION); // Veo si esta fijada la ubicación del Acrobat en la property - if(acrobatLocation == null) - { + if(acrobatLocation == null) { if(NativeFunctions.isUnix()) { // Si estoy en Unix no puedo ir a buscar el registry ;) throw new Exception("Try setting Acrobat location & executable in property '" + Const.ACROBAT_LOCATION + "' of PDFReport.ini"); } @@ -176,7 +175,7 @@ public static void printReport(String pdfFilename, boolean silent) throws Except try { // Primero debo obtener la ubicación + ejecutable del Acrobat acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) { + } catch(Exception acrobatNotFound) { throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); } @@ -204,7 +203,7 @@ public static void showReport(String filename, boolean modal) throws Exception { try { // Primero debo obtener la ubicación + ejecutable del Acrobat acrobatLocation = getAcrobatLocation(); - }catch(Exception acrobatNotFound) { + } catch(Exception acrobatNotFound) { throw new Exception("Acrobat cannot be found in this machine: " + acrobatNotFound.getMessage()); } @@ -308,7 +307,7 @@ protected void loadPrinterSettingsProps(String iniFile, String form, String prin protected void loadProps() { try{ props = new ParseINI(configurationFile, configurationTemplateFile); - }catch(IOException e){ props = new ParseINI(); } + } catch(IOException e){ props = new ParseINI(); } props.setupGeneralProperty(Const.PDF_REPORT_INI_VERSION_ENTRY, Const.PDF_REPORT_INI_VERSION); props.setupGeneralProperty(Const.EMBEED_SECTION, Const.EMBEED_DEFAULT); diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext.java b/java/src/main/java/com/genexus/reports/PDFReportItext2.java similarity index 99% rename from java/src/main/java/com/genexus/reports/PDFReportItext.java rename to java/src/main/java/com/genexus/reports/PDFReportItext2.java index 1dbe02473..e77aa7fd7 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext2.java @@ -37,7 +37,7 @@ import com.genexus.reports.fonts.PDFFontDescriptor; import com.genexus.reports.fonts.Type1FontMetrics; -public class PDFReportItext extends GXReportPDFCommons +public class PDFReportItext2 extends GXReportPDFCommons { private com.lowagie.text.Rectangle pageSize; // Contiene las dimensiones de la página private BaseFont baseFont; @@ -51,7 +51,7 @@ public class PDFReportItext extends GXReportPDFCommons ConcurrentHashMap documentImages; public int runDirection = PdfWriter.RUN_DIRECTION_LTR; - public PDFReportItext(ModelContext context) { + public PDFReportItext2(ModelContext context) { super(context); document = null; pageSize = null; diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext7.java b/java/src/main/java/com/genexus/reports/PDFReportItext7.java new file mode 100644 index 000000000..9692c5459 --- /dev/null +++ b/java/src/main/java/com/genexus/reports/PDFReportItext7.java @@ -0,0 +1,969 @@ +package com.genexus.reports; + +import com.genexus.CommonUtil; +import com.genexus.ModelContext; +import com.genexus.platform.NativeFunctions; +import com.genexus.reports.fonts.PDFFont; +import com.genexus.reports.fonts.PDFFontDescriptor; +import com.genexus.reports.fonts.Type1FontMetrics; +import com.genexus.webpanels.HttpContextWeb; + +import com.itextpdf.barcodes.Barcode128; +import com.itextpdf.html2pdf.HtmlConverter; +import com.itextpdf.io.font.PdfEncodings; +import com.itextpdf.io.font.constants.StandardFonts; +import com.itextpdf.io.font.otf.Glyph; +import com.itextpdf.io.font.otf.GlyphLine; +import com.itextpdf.io.image.ImageData; +import com.itextpdf.io.image.ImageDataFactory; +import com.itextpdf.kernel.colors.DeviceRgb; +import com.itextpdf.kernel.font.PdfFont; +import com.itextpdf.kernel.font.PdfFontFactory; +import com.itextpdf.kernel.font.PdfFontFactory.EmbeddingStrategy; +import com.itextpdf.kernel.geom.PageSize; +import com.itextpdf.kernel.geom.Rectangle; +import com.itextpdf.kernel.pdf.*; +import com.itextpdf.kernel.pdf.PdfViewerPreferences.PdfViewerPreferencesConstants; +import com.itextpdf.kernel.pdf.action.PdfAction; +import com.itextpdf.kernel.pdf.canvas.PdfCanvas; +import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants.LineCapStyle; +import com.itextpdf.kernel.pdf.xobject.PdfFormXObject; +import com.itextpdf.layout.Document; +import com.itextpdf.layout.Style; +import com.itextpdf.layout.borders.Border; +import com.itextpdf.layout.element.*; +import com.itextpdf.layout.element.Image; +import com.itextpdf.layout.properties.*; +import com.itextpdf.kernel.pdf.PdfDocument; +import com.itextpdf.layout.splitting.DefaultSplitCharacters; +import com.itextpdf.layout.Canvas; + +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.zip.Deflater; + +public class PDFReportItext7 extends GXReportPDFCommons +{ + private Rectangle pageSize; + private PdfFont baseFont; + private Barcode128 barcode = null; + private Document document; + private PdfDocument pdfDocument; + private PdfPage pdfPage; + private PdfWriter writer; + private PdfFormXObject template; + private PdfFont templateFont; + public boolean lineCapProjectingSquare = true; + public boolean barcode128AsImage = true; + ConcurrentHashMap documentImages; + + public PDFReportItext7(ModelContext context) { + super(context); + document = null; + pdfDocument = null; + pageSize = null; + documentImages = new ConcurrentHashMap<>(); + } + + protected void init() { + writer = new PdfWriter(outputStream); + writer.setCompressionLevel(Deflater.BEST_COMPRESSION); + pdfDocument = new PdfDocument(writer); + document = new Document(pdfDocument); + } + + private void drawRectangle(PdfCanvas cb, float x, float y, float w, float h, + int styleTop, int styleBottom, int styleRight, int styleLeft, + float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) { + + float[] dashPatternTop = getDashedPattern(styleTop); + float[] dashPatternBottom = getDashedPattern(styleBottom); + float[] dashPatternLeft = getDashedPattern(styleLeft); + float[] dashPatternRight = getDashedPattern(styleRight); + + //-------------------bottom line--------------------- + if (styleBottom!=STYLE_NONE_CONST) { + cb.setLineDash(dashPatternBottom, 0); + } + + float b = 0.4477f; + if (radioBL>0) { + cb.moveTo(x + radioBL, y); + } + else { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) { + cb.moveTo(x + penAux, y); + } + else { + cb.moveTo(x, y); + } + } + + //-------------------bottom right corner--------------------- + + if (styleBottom!=STYLE_NONE_CONST){ //si es null es Style None y no traza la linea + + if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) { + cb.lineTo(x + w - penAux, y); + } + else { + cb.lineTo(x + w - radioBR, y); + } + if (radioBR>0 && styleRight!=STYLE_NONE_CONST) { + cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + + } + + //-------------------right line--------------------- + + if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) { + cb.stroke(); + cb.setLineDash(dashPatternRight, 0); + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) { + cb.moveTo(x + w, y + penAux); + } + else { + cb.moveTo(x + w, y + radioBR); + } + } + + //-------------------top right corner--------------------- + if (styleRight!=STYLE_NONE_CONST) { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) { + cb.lineTo (x + w, y + h - penAux); + } + else { + cb.lineTo (x + w, y + h - radioTR); + } + if (radioTR>0 && styleTop!=STYLE_NONE_CONST) { + cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + } + + //-------------------top line--------------------- + + if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) { + cb.stroke(); + cb.setLineDash(dashPatternTop, 0); + if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) { + cb.moveTo(x + w - penAux, y + h); + } + else { + cb.moveTo(x + w - radioTR, y + h); + } + } + + //-------------------top left corner--------------------- + if (styleTop!=STYLE_NONE_CONST) { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) { + cb.lineTo(x + penAux, y + h); + } + else { + cb.lineTo(x + radioTL, y + h); + } + if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) { + cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + } + + //-------------------left line--------------------- + + if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) { + cb.stroke(); + cb.setLineDash(dashPatternLeft, 0); + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) { + cb.moveTo(x, y + h - penAux); + } + else { + cb.moveTo(x, y + h - radioTL); + } + } + + //-------------------bottom left corner--------------------- + if (styleLeft!=STYLE_NONE_CONST) { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) { + cb.lineTo(x, y + penAux); + } + else { + cb.lineTo(x, y + radioBL); + } + if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) + { + cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } + cb.stroke(); + + } + private void roundRectangle(PdfCanvas cb, float x, float y, float w, float h, + float radioTL, float radioTR, float radioBL, float radioBR) { + + //-------------------bottom line--------------------- + + float b = 0.4477f; + if (radioBL>0) { + cb.moveTo(x + radioBL, y); + } + else { + cb.moveTo(x, y); + } + + //-------------------bottom right corner--------------------- + + cb.lineTo(x + w - radioBR, y); + if (radioBR>0) { + cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + + + cb.lineTo (x + w, y + h - radioTR); + if (radioTR>0) { + cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + + cb.lineTo(x + radioTL, y + h); + if (radioTL>0) { + cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + cb.lineTo(x, y + radioBL); + if (radioBL>0) { + cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + + } + + public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { + + PdfCanvas cb = new PdfCanvas(pdfPage); + + float penAux = (float)convertScale(pen); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + cb.saveState(); + + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.getTop() - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.getTop() - topAux - topMargin - bottomMargin; + + cb.setLineWidth(penAux); + cb.setLineCapStyle(LineCapStyle.PROJECTING_SQUARE); + + if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) { + cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); + + Rectangle rect = new Rectangle(x1, y1, x2 - x1, y2 - y1); + rect.increaseHeight((float) (fontSize * 0.15)); + rect.increaseWidth((float) (fontSize * 0.15)); + cb.rectangle(rect); + + if (backMode!=0) { + cb.setFillColorRgb(backRed, backGreen, backBlue); + cb.fill(); + } else { + cb.stroke(); + } + } + else { + float w = x2 - x1; + float h = y2 - y1; + if (w < 0) { + x1 += w; + w = -w; + } + if (h < 0) { + y1 += h; + h = -h; + } + + float cRadioTL = (float)convertScale(cornerRadioTL); + float cRadioTR = (float)convertScale(cornerRadioTR); + float cRadioBL = (float)convertScale(cornerRadioBL); + float cRadioBR = (float)convertScale(cornerRadioBR); + + int max = (int)Math.min(w, h); + cRadioTL = Math.max(0, Math.min(cRadioTL, max/2)); + cRadioTR = Math.max(0, Math.min(cRadioTR, max/2)); + cRadioBL = Math.max(0, Math.min(cRadioBL, max/2)); + cRadioBR = Math.max(0, Math.min(cRadioBR, max/2)); + + if (backMode!=0) { + cb.setFillColorRgb(backRed, backGreen, backBlue); + cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); + cb.setLineWidth(0); + roundRectangle(cb, x1, y1, w, h, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR); + cb.setFillColor(new DeviceRgb(new Color(backRed, backGreen, backBlue))); + cb.fillStroke(); + cb.setLineWidth(penAux); + } + if (pen > 0) { + cb.setFillColorRgb(foreRed, foreGreen, foreBlue); + cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); + drawRectangle(cb, x1, y1, w, h, + styleTop, styleBottom, styleRight, styleLeft, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR, penAux, false); + } + } + cb.restoreState(); + + log.debug("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); + } + + public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { + PdfCanvas cb = new PdfCanvas(pdfPage); + + float widthAux = (float)convertScale(width); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + log.debug("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + + float x1, y1, x2, y2; + + x1 = leftAux + leftMargin; + y1 = pageSize.getTop() - bottomAux - topMargin -bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.getTop() - topAux - topMargin -bottomMargin; + + cb.saveState(); + cb.setFillColorRgb(foreRed, foreGreen, foreBlue); + cb.setLineWidth(widthAux); + + if (lineCapProjectingSquare) { + cb.setLineCapStyle(LineCapStyle.PROJECTING_SQUARE); + } + if (style!=0) { + float[] dashPattern = getDashedPattern(style); + cb.setLineDash(dashPattern, 0); + } + cb.moveTo(x1, y1); + cb.lineTo(x2, y2); + cb.stroke(); + + cb.restoreState(); + } + + public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { + try { + ImageData imageData; + try { + if (documentImages != null && documentImages.containsKey(bitmap)) { + imageData = ImageDataFactory.create(bitmap); + } + else { + + if (!NativeFunctions.isWindows() && new File(bitmap).isAbsolute() && bitmap.startsWith(httpContext.getStaticContentBase())) { + bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); + } + + if (!new File(bitmap).isAbsolute() && !bitmap.toLowerCase().startsWith("http:") && !bitmap.toLowerCase().startsWith("https:")) { + if (bitmap.startsWith(httpContext.getStaticContentBase())) { + bitmap = bitmap.replace(httpContext.getStaticContentBase(), ""); + } + imageData = ImageDataFactory.create(defaultRelativePrepend + bitmap); + if(imageData == null) { + bitmap = webAppDir + bitmap; + imageData = ImageDataFactory.create(bitmap); + } + else { + bitmap = defaultRelativePrepend + bitmap; + } + } + else { + imageData = ImageDataFactory.create(bitmap); + } + } + } + catch(java.lang.IllegalArgumentException ex) { + URL url= new java.net.URL(bitmap); + imageData = ImageDataFactory.create(url); + } + + if (documentImages == null) { + documentImages = new ConcurrentHashMap<>(); + } + documentImages.putIfAbsent(bitmap, new Image(imageData)); + + log.debug("GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + + if(imageData != null) { + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + Image image = new Image(imageData); + image.setFixedPosition(leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin); + if (aspectRatio == 0) + image.scaleAbsolute(rightAux - leftAux , bottomAux - topAux); + else + image.scaleToFit(rightAux - leftAux , bottomAux - topAux); + document.add(image); + } + } + catch(IOException ioe) { + log.error("GxDrawBitMap failed:", ioe); + } + catch(Exception e) { + log.error("GxDrawBitMap failed:", e); + } + } + + public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fontItalic, boolean fontUnderline, boolean fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) { + boolean isCJK = false; + boolean embeddedFont = isEmbeddedFont(fontName); + String originalFontName = fontName; + if (!embeddedFont) { + fontName = getSubstitute(fontName); + } + if(DEBUG) { + String fontSubstitute = ""; + if (!originalFontName.equals(fontName)) { + fontSubstitute = "Original Font: " + originalFontName + " Substitute"; + } + log.debug("GxAttris: "); + log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + } + if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { + barcode = new Barcode128(pdfDocument); + barcode.setCodeType(Barcode128.CODE128); + } + else { + barcode = null; + } + this.fontUnderline = fontUnderline; + this.fontStrikethru = fontStrikethru; + this.fontSize = fontSize; + this.fontBold = fontBold; + this.fontItalic = fontItalic; + foreColor = new Color(foreRed, foreGreen, foreBlue); + backColor = new Color(backRed, backGreen, backBlue); + backFill = (backMode != 0); + try { + if (PDFFont.isType1(fontName)) { + for(int i = 0; i < Type1FontMetrics.CJKNames.length; i++) { + if(Type1FontMetrics.CJKNames[i][0].equalsIgnoreCase(fontName) || + Type1FontMetrics.CJKNames[i][1].equalsIgnoreCase(fontName)) { + String style = ""; + if (fontBold && fontItalic) + style = "BoldItalic"; + else { + if (fontItalic) + style = "Italic"; + if (fontBold) + style = "Bold"; + } + setAsianFont(fontName, style); + isCJK = true; + break; + } + } + if (!isCJK) { + int style = 0; + if (fontBold && fontItalic) + style = style + 3; + else if (fontItalic) + style = style + 2; + else if (fontBold) + style = style + 1; + for(int i=0;i= 2 && !((align & 16) == 16) && htmlformat != 1) + if (valign == VerticalAlign.TOP.value()) + bottom = top + (int)reconvertScale(lineHeight); + else if (valign == VerticalAlign.BOTTOM.value()) + top = bottom - (int)reconvertScale(lineHeight); + + float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom-top) - captionHeight)/2; + float topAux; + + float leftAux = (float)convertScale(left); + float rightAux = (float)convertScale(right); + int alignment = align & 3; + boolean autoResize = (align & 256) == 256; + + if (htmlformat == 1) { + try { + bottomAux = (float)convertScale(bottom); + topAux = (float)convertScale(top); + float drawingPageHeight = this.pageSize.getTop() - topMargin - bottomMargin; + + float llx = leftAux + leftMargin; + float lly = drawingPageHeight - bottomAux; + float urx = rightAux + leftMargin; + float ury = drawingPageHeight - topAux; + + // Define the rectangle where the content will be displayed + Rectangle htmlRectangle = new Rectangle(llx, lly, urx - llx, ury - lly); + Canvas canvas = new Canvas(pdfDocument.getPage(page), htmlRectangle); + YPosition yPosition = new YPosition(htmlRectangle.getTop()); + TextAlignment txtAlignment = getTextAlignment(alignment); + + //Iterate over the elements (a.k.a the parsed HTML string) and handle each case accordingly + List elements = HtmlConverter.convertToElements(sTxt); + for (IElement element : elements) + processHTMLElement(canvas,htmlRectangle, yPosition, txtAlignment, (IBlockElement) element); + } catch (Exception e) { + log.error("GxDrawText failed to print HTML text : ", e); + } + } + else + if (barcode != null) { + log.debug("Barcode: --> " + barcode.getClass().getName()); + try { + barcode.setCode(sTxt); + barcode.setTextAlignment(alignment); + Rectangle rectangle = new Rectangle(0, 0); + switch (alignment) { + case 1: // Center Alignment + rectangle = new Rectangle((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + Math.abs(((leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2) - ((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2)) , + Math.abs((this.pageSize.getTop() - (float)convertScale(top) - topMargin - bottomMargin) - (this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin))); + break; + case 2: // Right Alignment + rectangle = new Rectangle(rightAux + leftMargin - rectangleWidth, + this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + Math.abs((rightAux + leftMargin) - (rightAux + leftMargin - rectangleWidth)), + Math.abs((this.pageSize.getTop() - (float)convertScale(top) - topMargin - bottomMargin) - (this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin))); + break; + case 0: // Left Alignment + rectangle = new Rectangle(leftAux + leftMargin, + this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + Math.abs((leftAux + leftMargin + rectangleWidth) - (leftAux + leftMargin)), + Math.abs((this.pageSize.getTop() - (float)convertScale(top) - topMargin - bottomMargin) - (this.pageSize.getTop() - (float)convertScale(bottom) - topMargin - bottomMargin))); + break; + } + barcode.setAltText(""); + barcode.setBaseline(0); + + if (fontSize < Const.LARGE_FONT_SIZE) + barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_SMALL_FONT); + else + barcode.setX(Const.OPTIMAL_MINIMU_BAR_WIDTH_LARGE_FONT); + + Image imageCode = new Image(ImageDataFactory.create(barcode.createAwtImage(backFill ? backColor : null, foreColor), foreColor)); + imageCode.setFixedPosition(leftAux + leftMargin, rectangle.getBottom()); + barcode.setBarHeight(rectangle.getHeight()); + imageCode.scaleToFit(rectangle.getWidth(), rectangle.getHeight()); + document.add(imageCode); + } + catch (Exception ex) { + log.error("GxDrawText: Error generating Barcode " + barcode.getClass().getName(), ex); + } + } + else { + + if(sTxt.trim().equalsIgnoreCase("{{Pages}}")) { + if (!templateCreated) { + template = new PdfFormXObject(new Rectangle(right - left, bottom - top)); + templateCreated = true; + } + cb.addXObjectAt(template, leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin -bottomMargin); + templateFont = baseFont; + templateFontSize = fontSize; + templateColorFill = foreColor; + return; + } + + float textBlockWidth = rightAux - leftAux; + float TxtWidth = baseFont.getWidth(sTxt, fontSize); + boolean justified = (alignment == 3) && textBlockWidth < TxtWidth; + boolean wrap = ((align & 16) == 16); + + float leading = (float)(Double.valueOf(props.getGeneralProperty(Const.LEADING)).doubleValue()); + Style style = new Style(); + if (fontBold) style.setBold(); + if (fontItalic) style.setItalic(); + if (fontStrikethru) style.setUnderline(fontSize / 6, fontSize / 2); + if (fontUnderline) style.setUnderline(fontSize / 6,0); + style.setFont(font); + style.setFontSize(fontSize); + style.setFontColor(new DeviceRgb(foreColor)); + + + if (wrap || justified) { + bottomAux = (float)convertScale(bottomOri); + topAux = (float)convertScale(topOri); + + float llx = leftAux + leftMargin; + float lly = this.pageSize.getTop() - bottomAux - topMargin - bottomMargin; + float urx = rightAux + leftMargin; + float ury = this.pageSize.getTop() - topAux - topMargin - bottomMargin; + + try{ + DrawTextColumn(llx, lly, urx, ury, sTxt, leading, valign, alignment, style, wrap); + } + catch (Exception ex) { + log.error("Text wrap in GxDrawText failed: ", ex); + } + } else { + if (!autoResize) { + String newsTxt = sTxt; + while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) { + sTxt = newsTxt; + newsTxt = newsTxt.substring(0, newsTxt.length()-1); + TxtWidth = baseFont.getWidth(newsTxt, fontSize); + } + } + + Paragraph p = new Paragraph(sTxt); + p.addStyle(style); + + switch(alignment) { + case 1: // Center Alignment + document.showTextAligned(p, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.CENTER, VerticalAlignment.MIDDLE,0); + break; + case 2: // Right Alignment + document.showTextAligned(p, rightAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.RIGHT, VerticalAlignment.MIDDLE,0); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + document.showTextAligned(p, leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.LEFT, VerticalAlignment.MIDDLE,0); + break; + } + } + } + } + + void processHTMLElement(Canvas canvas, Rectangle htmlRectangle, YPosition currentYPosition, TextAlignment txtAlignment, IBlockElement blockElement){ + float padding = 5f; + if (blockElement instanceof Paragraph){ + Paragraph p = (Paragraph) blockElement; + + // calculate the height of the Paragraph + float marginTop = (p.getMarginTop() != null) ? p.getMarginTop().getValue() : 0; + float marginBottom = (p.getMarginBottom() != null) ? p.getMarginBottom().getValue() : 0; + float paddingTop = (p.getPaddingTop() != null) ? p.getPaddingTop().getValue() : 0; + float paddingBottom = (p.getPaddingBottom() != null) ? p.getPaddingBottom().getValue() : 0; + float height = marginTop + marginBottom + paddingTop + paddingBottom; + + // check if the currentYPosition has enough space for the new Paragraph + if ((currentYPosition.getCurrentYPosition() - height) < htmlRectangle.getBottom()) { + // add new page and reset the currentYPosition + canvas = new Canvas(new PdfCanvas(pdfDocument.addNewPage()), htmlRectangle); + currentYPosition.setCurrentYPosition(htmlRectangle.getTop()); + } + + canvas.showTextAligned(p, htmlRectangle.getLeft(), currentYPosition.getCurrentYPosition() - p.getMarginTop().getValue(), txtAlignment); + currentYPosition.setCurrentYPosition(currentYPosition.getCurrentYPosition() - (height + padding)); + } else if (blockElement instanceof Div) { + Div div = (Div) blockElement; + // Iterate through the children of the Div + for (IElement child : div.getChildren()) + if (child instanceof IBlockElement) + // Process the child element recursively + processHTMLElement(canvas,htmlRectangle, currentYPosition, txtAlignment, (IBlockElement) child); + } + } + + public class YPosition { + float currentYPosition; + + public YPosition(float currentYPosition) { + this.currentYPosition = currentYPosition; + } + + public float getCurrentYPosition() { + return currentYPosition; + } + + public void setCurrentYPosition(float currentYPosition) { + this.currentYPosition = currentYPosition; + } + } + + boolean pageHeightExceeded(float bottomAux, float drawingPageHeight){ + return super.pageHeightExceeded(bottomAux,drawingPageHeight); + } + + private TextAlignment getTextAlignment(int alignment){ + switch(alignment) { + case 1: // Center Alignment + return TextAlignment.CENTER; + case 2: // Right Alignment + return TextAlignment.RIGHT; + case 0: // Left Alignment + case 3: // Justified, only one text line + return TextAlignment.LEFT; + default: + return TextAlignment.JUSTIFIED; + } + } + + void DrawTextColumn(float llx, float lly, float urx, float ury, String text, float leading, int valign, int alignment, Style style, boolean wrap){ + float y = lly; + if (valign == VerticalAlign.MIDDLE.value()) + ury = ury - ((y - lly) / 2) + leading; + else if (valign == VerticalAlign.BOTTOM.value()) + ury = ury - (y - lly- leading); + else if (valign == VerticalAlign.TOP.value()) + ury = ury + leading/2; + + Paragraph p = new Paragraph(text); + p.addStyle(style); + TextAlignment txtAlignment = getTextAlignment(alignment); + p.setTextAlignment(txtAlignment); + if (wrap) { + p.setProperty(Property.SPLIT_CHARACTERS, new CustomSplitCharacters()); + Table table = new Table(1); + table.setFixedPosition(page,llx, lly, urx - llx); + Cell cell = new Cell(); + cell.setWidth(urx - llx); + cell.setHeight(ury - lly); + cell.setBorder(Border.NO_BORDER); + cell.setVerticalAlignment(VerticalAlignment.MIDDLE); + cell.add(p); + table.addCell(cell); + document.add(table); + } else + document.showTextAligned(p, llx, lly, this.page, txtAlignment, VerticalAlignment.MIDDLE,0); + } + + private static class CustomSplitCharacters extends DefaultSplitCharacters { + @Override + public boolean isSplitCharacter(GlyphLine text, int glyphPos) { + if (!text.get(glyphPos).hasValidUnicode()) { + return false; + } + boolean baseResult = super.isSplitCharacter(text, glyphPos); + boolean myResult = false; + Glyph glyph = text.get(glyphPos); + if (glyph.getUnicode() == '_') { + myResult = true; + } + return myResult || baseResult; + } + } + + public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { + boolean preResult = super.GxPrintInit(output, gxXPage, gxYPage, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + + this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); + gxXPage[0] = (int)this.pageSize.getRight(); + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); + else + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); + + init(); + + if (!preResult) + return !preResult; + else + return true; + } + + private Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { + if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) { + if (length == 23818 && width == 16834) + return PageSize.A3; + else if (length == 16834 && width == 11909) + return PageSize.A4; + else if (length == 11909 && width == 8395) + return PageSize.A5; + else if (length == 20016 && width == 5731) + return PageSize.B4; + else if (length == 14170 && width == 9979) + return PageSize.B5; + else if (length == 15120 && width == 10440) + return PageSize.EXECUTIVE; + else if (length == 20160 && width == 12240) + return PageSize.LEGAL; + else if (length == 15840 && width == 12240) + return PageSize.LETTER; + else + return new Rectangle((int)(width / PAGE_SCALE_X) , (int)(length / PAGE_SCALE_Y) ); + } + return new Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); + } + + public void GxEndDocument() { + if(pdfDocument.getNumberOfPages() == 0) { + pdfDocument.addNewPage(); + } + + if (template != null) { + PdfCanvas cb = new PdfCanvas(pdfPage); + cb.beginText(); + cb.setFontAndSize(templateFont, templateFontSize); + cb.setTextMatrix(0,0); + cb.setFillColor(new DeviceRgb(templateColorFill)); + cb.showText(String.valueOf(pages)); + cb.endText(); + } + int copies = 1; + try { + copies = Integer.parseInt(printerSettings.getProperty(form, Const.COPIES)); + log.debug("Setting number of copies to " + copies); + PdfViewerPreferences viewerPreferences = new PdfViewerPreferences(); + viewerPreferences.setNumCopies(copies); + + int duplex= Integer.parseInt(printerSettings.getProperty(form, Const.DUPLEX)); + PdfViewerPreferencesConstants duplexValue; + switch (duplex){ + case 1: duplexValue = PdfViewerPreferencesConstants.SIMPLEX; break; + case 2: + case 3: + duplexValue = PdfViewerPreferencesConstants.DUPLEX_FLIP_SHORT_EDGE; break; + case 4: duplexValue = PdfViewerPreferencesConstants.DUPLEX_FLIP_LONG_EDGE; break; + default: duplexValue = PdfViewerPreferencesConstants.NONE; + } + log.debug("Setting duplex to " + duplexValue); + viewerPreferences.setDuplex(duplexValue); + pdfDocument.getCatalog().setViewerPreferences(viewerPreferences); + } + catch(Exception ex) { + log.error("GxEndDocument failed to add viewer preferences: ", ex); + } + + String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); + boolean fit= props.getGeneralProperty(Const.ADJUST_TO_PAPER).equals("true"); + if ((outputType==Const.OUTPUT_PRINTER || outputType==Const.OUTPUT_STREAM_PRINTER) && (httpContext instanceof HttpContextWeb && serverPrinting.equals("false"))) { + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("var pp = this.getPrintParams();\n")); + String printerAux=printerSettings.getProperty(form, Const.PRINTER); + String printer = replace(printerAux, "\\", "\\\\"); + + if (printer!=null && !printer.equals("")) { + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("pp.printerName = \"" + printer + "\";\n")); + } + if (fit) { + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("pp.pageHandling = pp.constants.handling.fit;\n")); + } + else { + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("pp.pageHandling = pp.constants.handling.none;\n")); + } + + if (printerSettings.getProperty(form, Const.MODE, "3").startsWith("0")){ + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("pp.interactive = pp.constants.interactionLevel.automatic;\n")); + for(int i = 0; i < copies; i++) { + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("this.print(pp);\n")); + } + } + else{ + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("pp.interactive = pp.constants.interactionLevel.full;\n")); + pdfDocument.getCatalog().setAdditionalAction(PdfName.WC, PdfAction.createJavaScript("this.print(pp);\n")); + } + } + + document.close(); + + log.debug("GxEndDocument!"); + + try{ props.save(); } catch(IOException e) { ; } + + switch(outputType) { + case Const.OUTPUT_SCREEN: + try{ outputStream.close(); } catch(IOException e) { ; } + try{ showReport(docName, modal); } catch(Exception e) { + e.printStackTrace(); + } + break; + case Const.OUTPUT_PRINTER: + try{ outputStream.close(); } catch(IOException e) { ; } + try{ + if (!(httpContext instanceof HttpContextWeb) || !serverPrinting.equals("false")) { + printReport(docName, this.printerOutputMode == 1); + } + } catch(Exception e){ + log.error("GxEndDocument: failed to show report ", e); + } + break; + case Const.OUTPUT_FILE: + try{ outputStream.close(); } catch(IOException e) { log.error("GxEndDocument: failed to save report to file ", e); } + break; + case Const.OUTPUT_STREAM: + case Const.OUTPUT_STREAM_PRINTER: + default: break; + } + outputStream = null; + } + + public void GxStartPage() { + pdfPage = pdfDocument.addNewPage(); + pages = pages +1; + } + +} diff --git a/java/src/main/java/com/genexus/webpanels/GXWebReport.java b/java/src/main/java/com/genexus/webpanels/GXWebReport.java index 0785e9714..1bc094725 100644 --- a/java/src/main/java/com/genexus/webpanels/GXWebReport.java +++ b/java/src/main/java/com/genexus/webpanels/GXWebReport.java @@ -36,15 +36,16 @@ protected void initState(ModelContext context, UserInformation ui) super.initState(context, ui); httpContext.setBuffered(true); httpContext.setBinary(true); - if (implementation.equals("PDFBOX")) + if (implementation.equals("ITEXT2")) reportHandler = new PDFReportPDFBox(context); + else if (implementation.equals("ITEXT7")) + reportHandler = new PDFReportItext7(context); else - reportHandler = new PDFReportItext(context); + reportHandler = new PDFReportPDFBox(context); initValues(); } - protected void preExecute() - { + protected void preExecute() { httpContext.setContentType("application/pdf"); httpContext.setStream(); ((GXReportPDFCommons) reportHandler).setOutputStream(httpContext.getOutputStream()); @@ -56,8 +57,7 @@ protected void setOutputFileName(String outputFileName){ protected void setOutputType(String outputType){ filetype = outputType.toLowerCase(); } - private void initValues() - { + private void initValues() { Gx_line = 0; P_lines = 0; gxXPage = 0; @@ -77,14 +77,11 @@ public IReportHandler getPrinter() return reportHandler; } - protected void GxEndPage() throws ProcessInterruptedException - { - if (reportHandler != null) - reportHandler.GxEndPage(); + protected void GxEndPage() throws ProcessInterruptedException { + if (reportHandler != null) reportHandler.GxEndPage(); } - protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) - { + protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int nPaperLength, int nPaperWidth, int nGridX, int nGridY, int nPageLines) { int x[] = {gxXPage}; int y[] = {gxYPage}; @@ -97,8 +94,7 @@ protected boolean initTextPrinter(String output, int gxXPage, int gxYPage, Strin return ret; } - protected boolean initPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) - { + protected boolean initPrinter(String output, int gxXPage, int gxYPage, String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { int x[] = {gxXPage}; int y[] = {gxYPage}; setResponseOuputFileName(); @@ -133,45 +129,37 @@ protected java.io.OutputStream getOutputStream() throw new RuntimeException("Output stream not set"); } - //M�todos para la implementaci�n de reportes din�micos - protected void loadReportMetadata(String name) - { + //Metodos para la implementacion de reportes dinamicos + protected void loadReportMetadata(String name) { reportMetadata = new GXReportMetadata(name, reportHandler); reportMetadata.load(); } - protected int GxDrawDynamicGetPrintBlockHeight(int printBlock) - { + protected int GxDrawDynamicGetPrintBlockHeight(int printBlock) { return reportMetadata.GxDrawGetPrintBlockHeight(printBlock); } - protected void GxDrawDynamicText(int printBlock, int controlId, int Gx_line) - { + protected void GxDrawDynamicText(int printBlock, int controlId, int Gx_line) { reportMetadata.GxDrawText(printBlock, controlId, Gx_line); } - protected void GxDrawDynamicText(int printBlock, int controlId, String value, int Gx_line) - { + protected void GxDrawDynamicText(int printBlock, int controlId, String value, int Gx_line) { reportMetadata.GxDrawText(printBlock, controlId, Gx_line, value); } - protected void GxDrawDynamicLine(int printBlock, int controlId, int Gx_line) - { + protected void GxDrawDynamicLine(int printBlock, int controlId, int Gx_line) { reportMetadata.GxDrawLine(printBlock, controlId, Gx_line); } - protected void GxDrawDynamicRect(int printBlock, int controlId, int Gx_line) - { + protected void GxDrawDynamicRect(int printBlock, int controlId, int Gx_line) { reportMetadata.GxDrawRect(printBlock, controlId, Gx_line); } - protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int Gx_line) - { + protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int Gx_line) { reportMetadata.GxDrawBitMap(printBlock, controlId, Gx_line, value, 0); } - protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int aspectRatio, int Gx_line) - { + protected void GxDrawDynamicBitMap(int printBlock, int controlId, String value, int aspectRatio, int Gx_line) { reportMetadata.GxDrawBitMap(printBlock, controlId, Gx_line, value, aspectRatio); } From ea5a6575a7c36e39260c84aaa19945b56498605d Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 17 May 2023 15:55:35 -0300 Subject: [PATCH 25/32] Remove PDFReportItext --- .../main/java/com/genexus/GXWebReport.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/java/src/main/java/com/genexus/GXWebReport.java b/java/src/main/java/com/genexus/GXWebReport.java index d6f084b6d..56de552a2 100644 --- a/java/src/main/java/com/genexus/GXWebReport.java +++ b/java/src/main/java/com/genexus/GXWebReport.java @@ -2,9 +2,7 @@ import com.genexus.db.UserInformation; import com.genexus.internet.HttpContext; -import com.genexus.reports.GXReportMetadata; -import com.genexus.reports.IReportHandler; -import com.genexus.reports.PDFReportItext; +import com.genexus.reports.*; import com.genexus.webpanels.GXWebProcedure; public abstract class GXWebReport extends GXWebProcedure @@ -37,9 +35,13 @@ protected void initState(ModelContext context, UserInformation ui) httpContext.setBuffered(true); httpContext.setBinary(true); - - reportHandler = new PDFReportItext(context); - + String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); + if (implementation.equals("ITEXT2")) + reportHandler = new PDFReportItext2(context); + else if (implementation.equals("ITEXT7")) + reportHandler = new PDFReportItext7(context); + else + reportHandler = new PDFReportPDFBox(context); initValues(); } @@ -47,10 +49,7 @@ protected void preExecute() { httpContext.setContentType("application/pdf"); httpContext.setStream(); - - // Tiene que ir despues del setStream porque sino el getOutputStream apunta - // a otro lado. - ((PDFReportItext) reportHandler).setOutputStream(httpContext.getOutputStream()); + ((GXReportPDFCommons) reportHandler).setOutputStream(httpContext.getOutputStream()); } protected void setOutputFileName(String outputFileName){ From 79b3d8d940b9d63f229d5a3afb5086121bb7dc04 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Fri, 19 May 2023 16:07:39 -0300 Subject: [PATCH 26/32] Fix implementation reading in client.cfg --- java/src/main/java/com/genexus/GXWebReport.java | 2 +- java/src/main/java/com/genexus/reports/GXReport.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/src/main/java/com/genexus/GXWebReport.java b/java/src/main/java/com/genexus/GXWebReport.java index 56de552a2..ee6aa69c2 100644 --- a/java/src/main/java/com/genexus/GXWebReport.java +++ b/java/src/main/java/com/genexus/GXWebReport.java @@ -36,7 +36,7 @@ protected void initState(ModelContext context, UserInformation ui) httpContext.setBuffered(true); httpContext.setBinary(true); String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); - if (implementation.equals("ITEXT2")) + if (implementation.equals("ITEXT")) reportHandler = new PDFReportItext2(context); else if (implementation.equals("ITEXT7")) reportHandler = new PDFReportItext7(context); diff --git a/java/src/main/java/com/genexus/reports/GXReport.java b/java/src/main/java/com/genexus/reports/GXReport.java index 234cca1e4..6ce1cb6f4 100644 --- a/java/src/main/java/com/genexus/reports/GXReport.java +++ b/java/src/main/java/com/genexus/reports/GXReport.java @@ -35,7 +35,7 @@ public static byte openGXReport(String document) { if(document.toLowerCase().endsWith(".pdf")) { // Si es un .pdf try { String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); - if (implementation.equals("ITEXT2")) + if (implementation.equals("ITEXT")) PDFReportItext2.showReport(document, false); else if (implementation.equals("ITEXT7")) PDFReportItext7.showReport(document, false); @@ -79,7 +79,7 @@ else if (getOutputType() == OUTPUT_PDF) { try { String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); - if (implementation.equals("ITEXT2")) + if (implementation.equals("ITEXT")) reportHandler = new PDFReportPDFBox(context); else if (implementation.equals("ITEXT7")) reportHandler = new PDFReportItext7(context); From 9ad48bd4c593de6d53ba65d2b76f81eebd3ea904 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Fri, 19 May 2023 20:19:01 -0300 Subject: [PATCH 27/32] Deleted unnecessary code and add debug for itext7 --- .../java/com/genexus/reports/GXReport.java | 19 +- .../genexus/reports/GXReportPDFCommons.java | 11 - .../com/genexus/reports/PDFReportItext2.java | 18 +- .../com/genexus/reports/PDFReportItext7.java | 547 +++++++++--------- .../com/genexus/reports/PDFReportPDFBox.java | 23 +- 5 files changed, 308 insertions(+), 310 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/GXReport.java b/java/src/main/java/com/genexus/reports/GXReport.java index 6ce1cb6f4..ba426d85e 100644 --- a/java/src/main/java/com/genexus/reports/GXReport.java +++ b/java/src/main/java/com/genexus/reports/GXReport.java @@ -34,13 +34,7 @@ public GXReport(boolean inNewUTL, int remoteHandle, ModelContext context, String public static byte openGXReport(String document) { if(document.toLowerCase().endsWith(".pdf")) { // Si es un .pdf try { - String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); - if (implementation.equals("ITEXT")) - PDFReportItext2.showReport(document, false); - else if (implementation.equals("ITEXT7")) - PDFReportItext7.showReport(document, false); - else - PDFReportPDFBox.showReport(document, false); + GXReportPDFCommons.showReport(document, false); } catch(Exception e) { log.error("GXReport failed to open report " + document + " : ", e); return -1; @@ -78,15 +72,10 @@ public IReportHandler getPrinter() else if (getOutputType() == OUTPUT_PDF) { try { - String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); - if (implementation.equals("ITEXT")) - reportHandler = new PDFReportPDFBox(context); - else if (implementation.equals("ITEXT7")) - reportHandler = new PDFReportItext7(context); - else - reportHandler = new PDFReportPDFBox(context); ((GXReportPDFCommons) reportHandler).setOutputStream(httpContext.getOutputStream()); - } catch (Exception e) {} + } catch (Exception e) { + log.error("Failed to set output stream: ", e); + } } else { throw new RuntimeException("Unrecognized report type: " + getOutputType()); diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index c97c33979..400351700 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -68,7 +68,6 @@ public abstract class GXReportPDFCommons implements IReportHandler{ protected boolean fontBold = false; protected boolean fontItalic = false; protected Color backColor, foreColor; - public static PrintStream DEBUG_STREAM = System.out; protected OutputStream outputStream = null; protected static ParseINI props = new ParseINI(); protected ParseINI printerSettings; @@ -85,7 +84,6 @@ public abstract class GXReportPDFCommons implements IReportHandler{ protected static String defaultRelativePrepend = null; protected static String defaultRelativePrependINI = null; protected static String webAppDir = null; - public static boolean DEBUG = false; private static String predefinedSearchPath = ""; protected float leftMargin; protected float topMargin; @@ -335,15 +333,6 @@ protected void loadProps() { loadSubstituteTable(); // Cargo la tabla de substitutos de fonts - if(props.getBooleanGeneralProperty("DEBUG", false)) { - DEBUG = true; - DEBUG_STREAM = System.out; - } - else { - DEBUG = false; - DEBUG_STREAM = new PrintStream(new com.genexus.util.NullOutputStream()); - } - Utilities.addPredefinedSearchPaths(new String[]{System.getProperty("java.awt.fonts", "c:\\windows\\fonts"), System.getProperty("com.ms.windir", "c:\\windows") + "\\fonts"}); } diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext2.java b/java/src/main/java/com/genexus/reports/PDFReportItext2.java index e77aa7fd7..4a15366b0 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext2.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext2.java @@ -64,7 +64,7 @@ protected void init() { writer = PdfWriter.getInstance(document, outputStream); } catch(DocumentException de) { - log.error("failed to initialize document: ", de); + log.error("Failed to initialize new iText2 document: ", de); } document.open(); } @@ -432,16 +432,14 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo if (!embeedFont) { fontName = getSubstitute(fontName); // Veo si hay substitutos solo si el font no va a ir embebido } - if(DEBUG) { - String fontSubstitute = ""; - if (!originalFontName.equals(fontName)) { - fontSubstitute = "Original Font: " + originalFontName + " Substitute"; - } - log.debug("GxAttris: "); - log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); - log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); - log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + + String fontSubstitute = ""; + if (!originalFontName.equals(fontName)) { + fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } + log.debug("GxAttris: "); + log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")");log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { barcode = new Barcode128(); diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext7.java b/java/src/main/java/com/genexus/reports/PDFReportItext7.java index 9692c5459..d5e6656dd 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext7.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext7.java @@ -70,292 +70,308 @@ public PDFReportItext7(ModelContext context) { } protected void init() { - writer = new PdfWriter(outputStream); - writer.setCompressionLevel(Deflater.BEST_COMPRESSION); - pdfDocument = new PdfDocument(writer); - document = new Document(pdfDocument); + try { + writer = new PdfWriter(outputStream); + writer.setCompressionLevel(Deflater.BEST_COMPRESSION); + pdfDocument = new PdfDocument(writer); + document = new Document(pdfDocument); + } catch (Exception e){ + log.error("Failed to initialize new iText7 document: ", e); + } } private void drawRectangle(PdfCanvas cb, float x, float y, float w, float h, int styleTop, int styleBottom, int styleRight, int styleLeft, float radioTL, float radioTR, float radioBL, float radioBR, float penAux, boolean hideCorners) { + try { + float[] dashPatternTop = getDashedPattern(styleTop); + float[] dashPatternBottom = getDashedPattern(styleBottom); + float[] dashPatternLeft = getDashedPattern(styleLeft); + float[] dashPatternRight = getDashedPattern(styleRight); - float[] dashPatternTop = getDashedPattern(styleTop); - float[] dashPatternBottom = getDashedPattern(styleBottom); - float[] dashPatternLeft = getDashedPattern(styleLeft); - float[] dashPatternRight = getDashedPattern(styleRight); - - //-------------------bottom line--------------------- - if (styleBottom!=STYLE_NONE_CONST) { - cb.setLineDash(dashPatternBottom, 0); - } + //-------------------bottom line--------------------- + if (styleBottom!=STYLE_NONE_CONST) { + cb.setLineDash(dashPatternBottom, 0); + } - float b = 0.4477f; - if (radioBL>0) { - cb.moveTo(x + radioBL, y); - } - else { - if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) { - cb.moveTo(x + penAux, y); + float b = 0.4477f; + if (radioBL>0) { + cb.moveTo(x + radioBL, y); } else { - cb.moveTo(x, y); + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioBL==0) { + cb.moveTo(x + penAux, y); + } + else { + cb.moveTo(x, y); + } } - } - //-------------------bottom right corner--------------------- + //-------------------bottom right corner--------------------- - if (styleBottom!=STYLE_NONE_CONST){ //si es null es Style None y no traza la linea + if (styleBottom!=STYLE_NONE_CONST){ //si es null es Style None y no traza la linea - if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) { - cb.lineTo(x + w - penAux, y); - } - else { - cb.lineTo(x + w - radioBR, y); - } - if (radioBR>0 && styleRight!=STYLE_NONE_CONST) { - cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); - } + if (hideCorners && styleRight==STYLE_NONE_CONST && radioBR==0) { + cb.lineTo(x + w - penAux, y); + } + else { + cb.lineTo(x + w - radioBR, y); + } + if (radioBR>0 && styleRight!=STYLE_NONE_CONST) { + cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } - } + } - //-------------------right line--------------------- + //-------------------right line--------------------- - if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) { - cb.stroke(); - cb.setLineDash(dashPatternRight, 0); - if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) { - cb.moveTo(x + w, y + penAux); - } - else { - cb.moveTo(x + w, y + radioBR); + if (styleRight!=STYLE_NONE_CONST && dashPatternRight!=dashPatternBottom) { + cb.stroke(); + cb.setLineDash(dashPatternRight, 0); + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBR==0) { + cb.moveTo(x + w, y + penAux); + } + else { + cb.moveTo(x + w, y + radioBR); + } } - } - //-------------------top right corner--------------------- - if (styleRight!=STYLE_NONE_CONST) { - if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) { - cb.lineTo (x + w, y + h - penAux); - } - else { - cb.lineTo (x + w, y + h - radioTR); - } - if (radioTR>0 && styleTop!=STYLE_NONE_CONST) { - cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + //-------------------top right corner--------------------- + if (styleRight!=STYLE_NONE_CONST) { + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTR==0) { + cb.lineTo (x + w, y + h - penAux); + } + else { + cb.lineTo (x + w, y + h - radioTR); + } + if (radioTR>0 && styleTop!=STYLE_NONE_CONST) { + cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } } - } - //-------------------top line--------------------- + //-------------------top line--------------------- - if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) { - cb.stroke(); - cb.setLineDash(dashPatternTop, 0); - if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) { - cb.moveTo(x + w - penAux, y + h); - } - else { - cb.moveTo(x + w - radioTR, y + h); + if (styleTop!=STYLE_NONE_CONST && dashPatternTop!=dashPatternRight) { + cb.stroke(); + cb.setLineDash(dashPatternTop, 0); + if (hideCorners && styleRight==STYLE_NONE_CONST && radioTR==0) { + cb.moveTo(x + w - penAux, y + h); + } + else { + cb.moveTo(x + w - radioTR, y + h); + } } - } - //-------------------top left corner--------------------- - if (styleTop!=STYLE_NONE_CONST) { - if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) { - cb.lineTo(x + penAux, y + h); - } - else { - cb.lineTo(x + radioTL, y + h); - } - if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) { - cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + //-------------------top left corner--------------------- + if (styleTop!=STYLE_NONE_CONST) { + if (hideCorners && styleLeft==STYLE_NONE_CONST && radioTL==0) { + cb.lineTo(x + penAux, y + h); + } + else { + cb.lineTo(x + radioTL, y + h); + } + if (radioTL>0 && styleLeft!=STYLE_NONE_CONST) { + cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } } - } - //-------------------left line--------------------- + //-------------------left line--------------------- - if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) { - cb.stroke(); - cb.setLineDash(dashPatternLeft, 0); - if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) { - cb.moveTo(x, y + h - penAux); - } - else { - cb.moveTo(x, y + h - radioTL); + if (styleLeft!=STYLE_NONE_CONST && dashPatternLeft!=dashPatternTop) { + cb.stroke(); + cb.setLineDash(dashPatternLeft, 0); + if (hideCorners && styleTop==STYLE_NONE_CONST && radioTL==0) { + cb.moveTo(x, y + h - penAux); + } + else { + cb.moveTo(x, y + h - radioTL); + } } - } - //-------------------bottom left corner--------------------- - if (styleLeft!=STYLE_NONE_CONST) { - if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) { - cb.lineTo(x, y + penAux); - } - else { - cb.lineTo(x, y + radioBL); - } - if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) - { - cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + //-------------------bottom left corner--------------------- + if (styleLeft!=STYLE_NONE_CONST) { + if (hideCorners && styleBottom==STYLE_NONE_CONST && radioBL==0) { + cb.lineTo(x, y + penAux); + } + else { + cb.lineTo(x, y + radioBL); + } + if (radioBL>0 && styleBottom!=STYLE_NONE_CONST) + { + cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } } + cb.stroke(); + } catch (Exception e) { + log.error("drawRectangle failed: ", e); } - cb.stroke(); - } private void roundRectangle(PdfCanvas cb, float x, float y, float w, float h, float radioTL, float radioTR, float radioBL, float radioBR) { + try { + //-------------------bottom line--------------------- - //-------------------bottom line--------------------- - - float b = 0.4477f; - if (radioBL>0) { - cb.moveTo(x + radioBL, y); - } - else { - cb.moveTo(x, y); - } + float b = 0.4477f; + if (radioBL>0) { + cb.moveTo(x + radioBL, y); + } + else { + cb.moveTo(x, y); + } - //-------------------bottom right corner--------------------- + //-------------------bottom right corner--------------------- - cb.lineTo(x + w - radioBR, y); - if (radioBR>0) { - cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); - } + cb.lineTo(x + w - radioBR, y); + if (radioBR>0) { + cb.curveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } - cb.lineTo (x + w, y + h - radioTR); - if (radioTR>0) { - cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); - } + cb.lineTo (x + w, y + h - radioTR); + if (radioTR>0) { + cb.curveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } - cb.lineTo(x + radioTL, y + h); - if (radioTL>0) { - cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); - } - cb.lineTo(x, y + radioBL); - if (radioBL>0) { - cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + cb.lineTo(x + radioTL, y + h); + if (radioTL>0) { + cb.curveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + cb.lineTo(x, y + radioBL); + if (radioBL>0) { + cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } catch (Exception e) { + log.error("drawRectangle failed: ", e); } - } public void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) { - PdfCanvas cb = new PdfCanvas(pdfPage); + try { + PdfCanvas cb = new PdfCanvas(pdfPage); - float penAux = (float)convertScale(pen); - float rightAux = (float)convertScale(right); - float bottomAux = (float)convertScale(bottom); - float leftAux = (float)convertScale(left); - float topAux = (float)convertScale(top); + float penAux = (float)convertScale(pen); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); - cb.saveState(); + cb.saveState(); - float x1, y1, x2, y2; - x1 = leftAux + leftMargin; - y1 = pageSize.getTop() - bottomAux - topMargin - bottomMargin; - x2 = rightAux + leftMargin; - y2 = pageSize.getTop() - topAux - topMargin - bottomMargin; + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.getTop() - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.getTop() - topAux - topMargin - bottomMargin; - cb.setLineWidth(penAux); - cb.setLineCapStyle(LineCapStyle.PROJECTING_SQUARE); + cb.setLineWidth(penAux); + cb.setLineCapStyle(LineCapStyle.PROJECTING_SQUARE); - if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) { - cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); + if (cornerRadioBL==0 && cornerRadioBR==0 && cornerRadioTL==0 && cornerRadioTR==0 && styleBottom==0 && styleLeft==0 && styleRight==0 && styleTop==0) { + cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); - Rectangle rect = new Rectangle(x1, y1, x2 - x1, y2 - y1); - rect.increaseHeight((float) (fontSize * 0.15)); - rect.increaseWidth((float) (fontSize * 0.15)); - cb.rectangle(rect); + Rectangle rect = new Rectangle(x1, y1, x2 - x1, y2 - y1); + rect.increaseHeight((float) (fontSize * 0.15)); + rect.increaseWidth((float) (fontSize * 0.15)); + cb.rectangle(rect); - if (backMode!=0) { - cb.setFillColorRgb(backRed, backGreen, backBlue); - cb.fill(); - } else { - cb.stroke(); + if (backMode!=0) { + cb.setFillColorRgb(backRed, backGreen, backBlue); + cb.fill(); + } else { + cb.stroke(); + } } - } - else { - float w = x2 - x1; - float h = y2 - y1; - if (w < 0) { - x1 += w; - w = -w; - } - if (h < 0) { - y1 += h; - h = -h; - } - - float cRadioTL = (float)convertScale(cornerRadioTL); - float cRadioTR = (float)convertScale(cornerRadioTR); - float cRadioBL = (float)convertScale(cornerRadioBL); - float cRadioBR = (float)convertScale(cornerRadioBR); - - int max = (int)Math.min(w, h); - cRadioTL = Math.max(0, Math.min(cRadioTL, max/2)); - cRadioTR = Math.max(0, Math.min(cRadioTR, max/2)); - cRadioBL = Math.max(0, Math.min(cRadioBL, max/2)); - cRadioBR = Math.max(0, Math.min(cRadioBR, max/2)); - - if (backMode!=0) { - cb.setFillColorRgb(backRed, backGreen, backBlue); - cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); - cb.setLineWidth(0); - roundRectangle(cb, x1, y1, w, h, - cRadioTL, cRadioTR, - cRadioBL, cRadioBR); - cb.setFillColor(new DeviceRgb(new Color(backRed, backGreen, backBlue))); - cb.fillStroke(); - cb.setLineWidth(penAux); - } - if (pen > 0) { - cb.setFillColorRgb(foreRed, foreGreen, foreBlue); - cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); - drawRectangle(cb, x1, y1, w, h, - styleTop, styleBottom, styleRight, styleLeft, - cRadioTL, cRadioTR, - cRadioBL, cRadioBR, penAux, false); + else { + float w = x2 - x1; + float h = y2 - y1; + if (w < 0) { + x1 += w; + w = -w; + } + if (h < 0) { + y1 += h; + h = -h; + } + + float cRadioTL = (float)convertScale(cornerRadioTL); + float cRadioTR = (float)convertScale(cornerRadioTR); + float cRadioBL = (float)convertScale(cornerRadioBL); + float cRadioBR = (float)convertScale(cornerRadioBR); + + int max = (int)Math.min(w, h); + cRadioTL = Math.max(0, Math.min(cRadioTL, max/2)); + cRadioTR = Math.max(0, Math.min(cRadioTR, max/2)); + cRadioBL = Math.max(0, Math.min(cRadioBL, max/2)); + cRadioBR = Math.max(0, Math.min(cRadioBR, max/2)); + + if (backMode!=0) { + cb.setFillColorRgb(backRed, backGreen, backBlue); + cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); + cb.setLineWidth(0); + roundRectangle(cb, x1, y1, w, h, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR); + cb.setFillColor(new DeviceRgb(new Color(backRed, backGreen, backBlue))); + cb.fillStroke(); + cb.setLineWidth(penAux); + } + if (pen > 0) { + cb.setFillColorRgb(foreRed, foreGreen, foreBlue); + cb.setStrokeColorRgb(foreRed, foreGreen, foreBlue); + drawRectangle(cb, x1, y1, w, h, + styleTop, styleBottom, styleRight, styleLeft, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR, penAux, false); + } } + cb.restoreState(); + } catch (Exception e) { + log.error("GxDrawRect failed: ", e); } - cb.restoreState(); log.debug("GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen); } public void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) { - PdfCanvas cb = new PdfCanvas(pdfPage); + try { + PdfCanvas cb = new PdfCanvas(pdfPage); - float widthAux = (float)convertScale(width); - float rightAux = (float)convertScale(right); - float bottomAux = (float)convertScale(bottom); - float leftAux = (float)convertScale(left); - float topAux = (float)convertScale(top); + float widthAux = (float)convertScale(width); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); - log.debug("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + log.debug("GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); - float x1, y1, x2, y2; + float x1, y1, x2, y2; - x1 = leftAux + leftMargin; - y1 = pageSize.getTop() - bottomAux - topMargin -bottomMargin; - x2 = rightAux + leftMargin; - y2 = pageSize.getTop() - topAux - topMargin -bottomMargin; + x1 = leftAux + leftMargin; + y1 = pageSize.getTop() - bottomAux - topMargin -bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.getTop() - topAux - topMargin -bottomMargin; - cb.saveState(); - cb.setFillColorRgb(foreRed, foreGreen, foreBlue); - cb.setLineWidth(widthAux); + cb.saveState(); + cb.setFillColorRgb(foreRed, foreGreen, foreBlue); + cb.setLineWidth(widthAux); - if (lineCapProjectingSquare) { - cb.setLineCapStyle(LineCapStyle.PROJECTING_SQUARE); - } - if (style!=0) { - float[] dashPattern = getDashedPattern(style); - cb.setLineDash(dashPattern, 0); - } - cb.moveTo(x1, y1); - cb.lineTo(x2, y2); - cb.stroke(); + if (lineCapProjectingSquare) { + cb.setLineCapStyle(LineCapStyle.PROJECTING_SQUARE); + } + if (style!=0) { + float[] dashPattern = getDashedPattern(style); + cb.setLineDash(dashPattern, 0); + } + cb.moveTo(x1, y1); + cb.lineTo(x2, y2); + cb.stroke(); - cb.restoreState(); + cb.restoreState(); + } catch (Exception e) { + log.error("GxDrawLine failed:", e); + } } public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) { @@ -431,16 +447,16 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo if (!embeddedFont) { fontName = getSubstitute(fontName); } - if(DEBUG) { - String fontSubstitute = ""; - if (!originalFontName.equals(fontName)) { - fontSubstitute = "Original Font: " + originalFontName + " Substitute"; - } - log.debug("GxAttris: "); - log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); - log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); - log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + + String fontSubstitute = ""; + if (!originalFontName.equals(fontName)) { + fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } + log.debug("GxAttris: "); + log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) { barcode = new Barcode128(pdfDocument); barcode.setCodeType(Barcode128.CODE128); @@ -663,7 +679,6 @@ else if (valign == VerticalAlign.BOTTOM.value()) style.setFontSize(fontSize); style.setFontColor(new DeviceRgb(foreColor)); - if (wrap || justified) { bottomAux = (float)convertScale(bottomOri); topAux = (float)convertScale(topOri); @@ -680,29 +695,33 @@ else if (valign == VerticalAlign.BOTTOM.value()) log.error("Text wrap in GxDrawText failed: ", ex); } } else { - if (!autoResize) { - String newsTxt = sTxt; - while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) { - sTxt = newsTxt; - newsTxt = newsTxt.substring(0, newsTxt.length()-1); - TxtWidth = baseFont.getWidth(newsTxt, fontSize); + try { + if (!autoResize) { + String newsTxt = sTxt; + while(TxtWidth > textBlockWidth && (newsTxt.length()-1>=0)) { + sTxt = newsTxt; + newsTxt = newsTxt.substring(0, newsTxt.length()-1); + TxtWidth = baseFont.getWidth(newsTxt, fontSize); + } } - } - Paragraph p = new Paragraph(sTxt); - p.addStyle(style); + Paragraph p = new Paragraph(sTxt); + p.addStyle(style); - switch(alignment) { - case 1: // Center Alignment - document.showTextAligned(p, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.CENTER, VerticalAlignment.MIDDLE,0); - break; - case 2: // Right Alignment - document.showTextAligned(p, rightAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.RIGHT, VerticalAlignment.MIDDLE,0); - break; - case 0: // Left Alignment - case 3: // Justified, only one text line - document.showTextAligned(p, leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.LEFT, VerticalAlignment.MIDDLE,0); - break; + switch(alignment) { + case 1: // Center Alignment + document.showTextAligned(p, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.CENTER, VerticalAlignment.MIDDLE,0); + break; + case 2: // Right Alignment + document.showTextAligned(p, rightAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.RIGHT, VerticalAlignment.MIDDLE,0); + break; + case 0: // Left Alignment + case 3: // Justified, only one text line + document.showTextAligned(p, leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin, page, TextAlignment.LEFT, VerticalAlignment.MIDDLE,0); + break; + } + } catch (Exception e) { + log.error("GxDrawText failed to draw simple text: ", e); } } } @@ -820,20 +839,24 @@ public boolean isSplitCharacter(GlyphLine text, int glyphPos) { public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String iniFile, String form, String printer, int mode, int orientation, int pageSize, int pageLength, int pageWidth, int scale, int copies, int defSrc, int quality, int color, int duplex) { boolean preResult = super.GxPrintInit(output, gxXPage, gxYPage, iniFile, form, printer, mode, orientation, pageSize, pageLength, pageWidth, scale, copies, defSrc, quality, color, duplex); + try { + this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); + gxXPage[0] = (int)this.pageSize.getRight(); + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); + else + gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); - this.pageSize = computePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, false)); - gxXPage[0] = (int)this.pageSize.getRight(); - if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) - gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y); - else - gxYPage[0] = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); - - init(); + init(); - if (!preResult) - return !preResult; - else - return true; + if (!preResult) + return !preResult; + else + return true; + } catch (Exception e){ + log.error("GxPrintInit faile" , e); + return false; + } } private Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { @@ -938,7 +961,7 @@ public void GxEndDocument() { case Const.OUTPUT_SCREEN: try{ outputStream.close(); } catch(IOException e) { ; } try{ showReport(docName, modal); } catch(Exception e) { - e.printStackTrace(); + log.error("GxEndDocument: failed to show report on screen ", e ); } break; case Const.OUTPUT_PRINTER: diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 1fb4ceeaa..5292bbd25 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -61,7 +61,7 @@ protected void init() { document = new PDDocument(); } catch(Exception e) { - log.error("failed to initialize new PDFBox document: ", e); + log.error("Failed to initialize new PDFBox document: ", e); } } @@ -166,7 +166,7 @@ private void drawRectangle(PDPageContentStream cb, float x, float y, float w, fl } cb.stroke(); } catch (IOException ioe) { - log.error("drawRectangle failed: ", ioe); + log.error("roundRectangle failed: ", ioe); } } @@ -197,7 +197,7 @@ private void roundRectangle(PDPageContentStream cb, float x, float y, float w, f cb.curveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); } } catch (IOException ioe) { - log.error("roundRectangle failed: ", ioe); + log.error("drawRectangle failed: ", ioe); } } @@ -396,16 +396,15 @@ public void GxAttris(String fontName, int fontSize, boolean fontBold, boolean fo if (!embeedFont) { fontName = getSubstitute(fontName); } - if(DEBUG) { - String fontSubstitute = ""; - if (!originalFontName.equals(fontName)) { - fontSubstitute = "Original Font: " + originalFontName + " Substitute"; - } - log.debug("GxAttris: "); - log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); - log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); - log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + + String fontSubstitute = ""; + if (!originalFontName.equals(fontName)) { + fontSubstitute = "Original Font: " + originalFontName + " Substitute"; } + log.debug("GxAttris: "); + log.debug("\\-> " + fontSubstitute + "Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + log.debug("\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + log.debug("\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); if (barcode128AsImage && fontName.toLowerCase().indexOf("barcode 128") >= 0 || fontName.toLowerCase().indexOf("barcode128") >= 0) barcodeType = "barcode128"; From aa211aaaff9a4c6fa2c8885c0383776b9b261c53 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Sun, 21 May 2023 11:06:21 -0300 Subject: [PATCH 28/32] Fix fullgx test 7322 --- java/src/main/java/com/genexus/reports/GXReport.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/src/main/java/com/genexus/reports/GXReport.java b/java/src/main/java/com/genexus/reports/GXReport.java index ba426d85e..bbc54707f 100644 --- a/java/src/main/java/com/genexus/reports/GXReport.java +++ b/java/src/main/java/com/genexus/reports/GXReport.java @@ -72,6 +72,13 @@ public IReportHandler getPrinter() else if (getOutputType() == OUTPUT_PDF) { try { + String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); + if (implementation.equals("ITEXT")) + reportHandler = new PDFReportPDFBox(context); + else if (implementation.equals("ITEXT7")) + reportHandler = new PDFReportItext7(context); + else + reportHandler = new PDFReportPDFBox(context); ((GXReportPDFCommons) reportHandler).setOutputStream(httpContext.getOutputStream()); } catch (Exception e) { log.error("Failed to set output stream: ", e); From 811aa59e05c440719de21bc5a3482d81aa77b883 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Tue, 23 May 2023 11:17:24 -0300 Subject: [PATCH 29/32] Particular log for each report implementation --- .../src/main/java/com/genexus/reports/GXReportPDFCommons.java | 2 +- java/src/main/java/com/genexus/reports/PDFReportItext2.java | 4 ++++ java/src/main/java/com/genexus/reports/PDFReportItext7.java | 4 ++++ java/src/main/java/com/genexus/reports/PDFReportPDFBox.java | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java index 400351700..d2f53098e 100644 --- a/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java +++ b/java/src/main/java/com/genexus/reports/GXReportPDFCommons.java @@ -124,7 +124,7 @@ public int value(){ } protected static char alternateSeparator = File.separatorChar == '/' ? '\\' : '/'; - protected static Logger log = org.apache.logging.log4j.LogManager.getLogger(GXReportPDFCommons.class); + protected static Logger log; /** Setea el OutputStream a utilizar * @param outputStream Stream a utilizar diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext2.java b/java/src/main/java/com/genexus/reports/PDFReportItext2.java index 4a15366b0..1dbfeeee4 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext2.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext2.java @@ -51,6 +51,10 @@ public class PDFReportItext2 extends GXReportPDFCommons ConcurrentHashMap documentImages; public int runDirection = PdfWriter.RUN_DIRECTION_LTR; + static { + log = org.apache.logging.log4j.LogManager.getLogger(PDFReportItext2.class); + } + public PDFReportItext2(ModelContext context) { super(context); document = null; diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext7.java b/java/src/main/java/com/genexus/reports/PDFReportItext7.java index d5e6656dd..de69520bf 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext7.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext7.java @@ -61,6 +61,10 @@ public class PDFReportItext7 extends GXReportPDFCommons public boolean barcode128AsImage = true; ConcurrentHashMap documentImages; + static { + log = org.apache.logging.log4j.LogManager.getLogger(PDFReportItext7.class); + } + public PDFReportItext7(ModelContext context) { super(context); document = null; diff --git a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java index 5292bbd25..5894ae563 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java +++ b/java/src/main/java/com/genexus/reports/PDFReportPDFBox.java @@ -49,6 +49,10 @@ public class PDFReportPDFBox extends GXReportPDFCommons{ public int runDirection = 0; private int page; + static { + log = org.apache.logging.log4j.LogManager.getLogger(PDFReportPDFBox.class); + } + public PDFReportPDFBox(ModelContext context) { super(context); document = null; From 4fc797eb240cf12d4c303619ffe0ef68c0d94970 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Tue, 23 May 2023 17:19:40 -0300 Subject: [PATCH 30/32] Fix wrong call to implementation constructor --- java/src/main/java/com/genexus/reports/GXReport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/main/java/com/genexus/reports/GXReport.java b/java/src/main/java/com/genexus/reports/GXReport.java index bbc54707f..a13e28331 100644 --- a/java/src/main/java/com/genexus/reports/GXReport.java +++ b/java/src/main/java/com/genexus/reports/GXReport.java @@ -74,7 +74,7 @@ else if (getOutputType() == OUTPUT_PDF) try { String implementation = com.genexus.Application.getClientContext().getClientPreferences().getPDF_RPT_LIBRARY(); if (implementation.equals("ITEXT")) - reportHandler = new PDFReportPDFBox(context); + reportHandler = new PDFReportItext2(context); else if (implementation.equals("ITEXT7")) reportHandler = new PDFReportItext7(context); else From 0c68e9395e81370672f80c2a60c71793eff2e332 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Tue, 23 May 2023 17:56:43 -0300 Subject: [PATCH 31/32] Adjusted pagesize of iText7 reports --- .../java/com/genexus/reports/PDFReportItext7.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext7.java b/java/src/main/java/com/genexus/reports/PDFReportItext7.java index de69520bf..cd75a166d 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext7.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext7.java @@ -37,6 +37,7 @@ import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.layout.splitting.DefaultSplitCharacters; import com.itextpdf.layout.Canvas; +import org.opensaml.xml.signature.P; import java.awt.*; import java.io.File; @@ -46,9 +47,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.zip.Deflater; -public class PDFReportItext7 extends GXReportPDFCommons -{ - private Rectangle pageSize; +public class PDFReportItext7 extends GXReportPDFCommons { + private PageSize pageSize; private PdfFont baseFont; private Barcode128 barcode = null; private Document document; @@ -78,7 +78,9 @@ protected void init() { writer = new PdfWriter(outputStream); writer.setCompressionLevel(Deflater.BEST_COMPRESSION); pdfDocument = new PdfDocument(writer); + pdfDocument.setDefaultPageSize(this.pageSize); document = new Document(pdfDocument); + } catch (Exception e){ log.error("Failed to initialize new iText7 document: ", e); } @@ -863,7 +865,7 @@ public boolean GxPrintInit(String output, int gxXPage[], int gxYPage[], String i } } - private Rectangle computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { + private PageSize computePageSize(float leftMargin, float topMargin, int width, int length, boolean marginsInsideBorder) { if ((leftMargin == 0 && topMargin == 0)||marginsInsideBorder) { if (length == 23818 && width == 16834) return PageSize.A3; @@ -882,9 +884,9 @@ else if (length == 20160 && width == 12240) else if (length == 15840 && width == 12240) return PageSize.LETTER; else - return new Rectangle((int)(width / PAGE_SCALE_X) , (int)(length / PAGE_SCALE_Y) ); + return new PageSize(new Rectangle((int)(width / PAGE_SCALE_X) , (int)(length / PAGE_SCALE_Y) )); } - return new Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin); + return new PageSize(new Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin)); } public void GxEndDocument() { From af2fbb0e753ece7f781e94dcb2aaed45e796fda9 Mon Sep 17 00:00:00 2001 From: tomas-sexenian Date: Wed, 24 May 2023 12:15:31 -0300 Subject: [PATCH 32/32] Fix pagination error when images exceed page size --- .../java/com/genexus/reports/PDFReportItext2.java | 4 ++-- .../java/com/genexus/reports/PDFReportItext7.java | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext2.java b/java/src/main/java/com/genexus/reports/PDFReportItext2.java index 1dbfeeee4..cc4514674 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext2.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext2.java @@ -65,10 +65,10 @@ public PDFReportItext2(ModelContext context) { protected void init() { Document.compress = true; try { - writer = PdfWriter.getInstance(document, outputStream); + writer = PdfWriter.getInstance(document, outputStream); } catch(DocumentException de) { - log.error("Failed to initialize new iText2 document: ", de); + log.error("Failed to initialize new iText2 document: ", de); } document.open(); } diff --git a/java/src/main/java/com/genexus/reports/PDFReportItext7.java b/java/src/main/java/com/genexus/reports/PDFReportItext7.java index cd75a166d..26960c750 100644 --- a/java/src/main/java/com/genexus/reports/PDFReportItext7.java +++ b/java/src/main/java/com/genexus/reports/PDFReportItext7.java @@ -37,7 +37,6 @@ import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.layout.splitting.DefaultSplitCharacters; import com.itextpdf.layout.Canvas; -import org.opensaml.xml.signature.P; import java.awt.*; import java.io.File; @@ -430,7 +429,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom float topAux = (float)convertScale(top); Image image = new Image(imageData); - image.setFixedPosition(leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin); + image.setFixedPosition(page,leftAux + leftMargin, this.pageSize.getTop() - bottomAux - topMargin - bottomMargin); if (aspectRatio == 0) image.scaleAbsolute(rightAux - leftAux , bottomAux - topAux); else @@ -587,6 +586,8 @@ else if (valign == VerticalAlign.BOTTOM.value()) boolean autoResize = (align & 256) == 256; if (htmlformat == 1) { + //As of now, you might experience unexpected behaviour since not all possible + //HTML code is supported try { bottomAux = (float)convertScale(bottom); topAux = (float)convertScale(top); @@ -748,7 +749,9 @@ void processHTMLElement(Canvas canvas, Rectangle htmlRectangle, YPosition curren // check if the currentYPosition has enough space for the new Paragraph if ((currentYPosition.getCurrentYPosition() - height) < htmlRectangle.getBottom()) { // add new page and reset the currentYPosition - canvas = new Canvas(new PdfCanvas(pdfDocument.addNewPage()), htmlRectangle); + pdfPage = pdfDocument.addNewPage(); + pages++; + canvas = new Canvas(new PdfCanvas(pdfPage), htmlRectangle); currentYPosition.setCurrentYPosition(htmlRectangle.getTop()); } @@ -891,7 +894,8 @@ else if (length == 15840 && width == 12240) public void GxEndDocument() { if(pdfDocument.getNumberOfPages() == 0) { - pdfDocument.addNewPage(); + pdfPage = pdfDocument.addNewPage(); + pages++; } if (template != null) {