├── src ├── test │ ├── resources │ │ ├── Bertrand1-figure.png │ │ └── Bertrand1-figure-withres.png │ └── java │ │ └── net │ │ └── sf │ │ └── mcf2pdf │ │ └── util │ │ └── ImageUtilTest.java └── main │ ├── resources │ ├── linux-x86-64 │ │ └── libwebp.so │ ├── win32-x86-64 │ │ └── libwebp.dll │ └── log4j.properties │ ├── java │ └── net │ │ └── sf │ │ └── mcf2pdf │ │ ├── mcfconfig │ │ ├── Decoration.java │ │ ├── Template.java │ │ ├── Clipart.java │ │ ├── Fotoarea.java │ │ └── Fading.java │ │ ├── mcfelements │ │ ├── McfBorder.java │ │ ├── McfClipart.java │ │ ├── McfBackground.java │ │ ├── McfImageBackground.java │ │ ├── McfAreaContent.java │ │ ├── McfText.java │ │ ├── impl │ │ │ ├── AbstractMcfAreaContentImpl.java │ │ │ ├── McfClipartImpl.java │ │ │ ├── McfImageBackgroundImpl.java │ │ │ ├── McfBorderImpl.java │ │ │ ├── McfBackgroundImpl.java │ │ │ ├── McfPageImpl.java │ │ │ ├── McfTextImpl.java │ │ │ ├── McfImageImpl.java │ │ │ ├── McfFotobookImpl.java │ │ │ ├── McfAreaImpl.java │ │ │ └── DigesterConfiguratorImpl.java │ │ ├── McfImage.java │ │ ├── util │ │ │ ├── webp │ │ │ │ ├── WebpLib.java │ │ │ │ └── Webp.java │ │ │ ├── DigesterUtil.java │ │ │ ├── McfFileUtil.java │ │ │ ├── ClpInputStream.java │ │ │ ├── PdfUtil.java │ │ │ ├── XslFoDocumentBuilder.java │ │ │ ├── FadingComposite.java │ │ │ └── ImageUtil.java │ │ ├── McfFotobook.java │ │ ├── McfPage.java │ │ ├── McfArea.java │ │ ├── DigesterConfigurator.java │ │ └── FotobookBuilder.java │ │ ├── mcfglobals │ │ ├── McfFotoFrame.java │ │ ├── McfAlbumType.java │ │ ├── impl │ │ │ ├── McfProductCatalogueImpl.java │ │ │ └── McfAlbumTypeImpl.java │ │ ├── McfProductCatalogue.java │ │ └── McfResourceScanner.java │ │ ├── pagebuild │ │ ├── AbstractPageBuilder.java │ │ ├── PageImageBackground.java │ │ ├── FormattedText.java │ │ ├── PageBuilder.java │ │ ├── PageClipart.java │ │ ├── PageBinding.java │ │ ├── SVGPageBuilder.java │ │ ├── BitmapPageBuilder.java │ │ ├── PageDrawable.java │ │ ├── FormattedTextParagraph.java │ │ ├── PageBackground.java │ │ ├── PageRenderContext.java │ │ ├── PageImage.java │ │ └── PageText.java │ │ ├── Main.java │ │ └── Mcf2FoConverter.java │ └── assembly │ ├── licenseText.properties │ ├── mcf2pdf │ ├── classpath.unix │ ├── src.xml │ ├── classpath.win │ ├── classpath-filter.win │ ├── mcf2pdf.bat │ ├── zip.xml │ └── tgz.xml ├── .settings ├── org.eclipse.m2e.core.prefs ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── .gitignore ├── log4j.properties ├── .project ├── .classpath ├── README.md ├── README.old.md └── pom.xml /src/test/resources/Bertrand1-figure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/albrechtf/mcf2pdf/HEAD/src/test/resources/Bertrand1-figure.png -------------------------------------------------------------------------------- /src/main/resources/linux-x86-64/libwebp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/albrechtf/mcf2pdf/HEAD/src/main/resources/linux-x86-64/libwebp.so -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /src/main/resources/win32-x86-64/libwebp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/albrechtf/mcf2pdf/HEAD/src/main/resources/win32-x86-64/libwebp.dll -------------------------------------------------------------------------------- /src/test/resources/Bertrand1-figure-withres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/albrechtf/mcf2pdf/HEAD/src/test/resources/Bertrand1-figure-withres.png -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | /bin 14 | /target 15 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfconfig/Decoration.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfconfig; 2 | 3 | public class Decoration { 4 | private Fading fading; 5 | 6 | public Fading getFading() { 7 | return fading; 8 | } 9 | public void setFading(Fading fading) { 10 | this.fading = fading; 11 | } 12 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfBorder.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfelements; 2 | 3 | import java.awt.Color; 4 | 5 | public interface McfBorder { 6 | 7 | public Color getColor(); 8 | 9 | public float getOffset(); 10 | 11 | public float getWidth(); 12 | 13 | public boolean isEnabled(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/assembly/licenseText.properties: -------------------------------------------------------------------------------- 1 | licenseText=This file is part of mcf2pdf.\n * Copyright (c) 2011 Florian Albrecht.\n * \n * mcf2pdf is distributed under the Terms and Conditions of the\n * Common Development and Distribution License (CDDL), version 1.0\n * A copy of the license text is bundled with this software,\n * and can be accessed here:\n * http://www.opensource.org/licenses/CDDL-1.0 -------------------------------------------------------------------------------- /log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, console 2 | 3 | log4j.appender.console=org.apache.log4j.ConsoleAppender 4 | 5 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 6 | log4j.appender.console.layout.ConversionPattern=[%-5p] %C %m%n 7 | 8 | log4j.logger.org.apache=ERROR 9 | log4j.logger.org.apache.commons.digester3.Digester=OFF 10 | log4j.logger.net.sf.mcf2pdf.mcfelements.impl.DigesterConfiguratorImpl$1=ERROR 11 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfClipart.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfClipart extends McfAreaContent { 10 | 11 | public String getUniqueName(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=DEBUG, console 2 | 3 | log4j.appender.console=org.apache.log4j.ConsoleAppender 4 | 5 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 6 | log4j.appender.console.layout.ConversionPattern=[%-5p] %C %m%n 7 | 8 | log4j.logger.org.apache=ERROR 9 | log4j.logger.org.apache.commons.digester3.Digester=OFF 10 | log4j.logger.net.sf.mcf2pdf.mcfelements.impl.DigesterConfiguratorImpl$1=ERROR 11 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfconfig/Template.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfconfig; 2 | 3 | public class Template { 4 | private String name; 5 | private String filename; 6 | 7 | public String getName() { 8 | return name; 9 | } 10 | public void setName(String name) { 11 | this.name = name; 12 | } 13 | public String getFilename() { 14 | return filename; 15 | } 16 | public void setFilename(String filename) { 17 | this.filename = filename; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfBackground.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfBackground { 10 | 11 | public McfPage getPage(); 12 | 13 | public String getTemplateName(); 14 | 15 | public int getType(); 16 | 17 | public int getLayout(); 18 | 19 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfImageBackground.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfImageBackground extends McfImage { 10 | 11 | public final static String RIGHT_OR_BOTTOM = "RIGHT_OR_BOTTOM"; 12 | 13 | public String getBackgroundPosition(); 14 | 15 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfAreaContent.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfAreaContent { 10 | 11 | public static enum ContentType { 12 | IMAGE, IMAGEBACKGROUND, CLIPART, TEXT 13 | } 14 | 15 | public McfArea getArea(); 16 | 17 | public ContentType getContentType(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfText.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfText extends McfAreaContent { 10 | 11 | public boolean isSpineText(); 12 | 13 | public String getHtmlContent(); 14 | 15 | public float getVerticalIndentMargin(); 16 | 17 | public float getIndentMargin(); 18 | 19 | public int getBackgroundColorAlpha(); 20 | 21 | } -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | mcf2pdf 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.m2e.core.maven2Nature 21 | org.eclipse.jdt.core.javanature 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfglobals/McfFotoFrame.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfglobals; 2 | 3 | import java.io.File; 4 | 5 | import net.sf.mcf2pdf.mcfconfig.Fading; 6 | 7 | public class McfFotoFrame { 8 | private File clipart; 9 | private File fading; 10 | private Fading config; 11 | 12 | public McfFotoFrame(File clipart, File fading, Fading config) { 13 | this.clipart = clipart; 14 | this.fading = fading; 15 | this.config = config; 16 | } 17 | 18 | public File getClipart() { 19 | return clipart; 20 | } 21 | 22 | public File getFading() { 23 | return fading; 24 | } 25 | 26 | public Fading getConfig() { 27 | return config; 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfconfig/Clipart.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfconfig; 2 | 3 | public class Clipart { 4 | private String file; 5 | private String designElementType; 6 | private double ratio; 7 | 8 | public String getFile() { 9 | return file; 10 | } 11 | public void setFile(String file) { 12 | this.file = file; 13 | } 14 | public String getDesignElementType() { 15 | return designElementType; 16 | } 17 | public void setDesignElementType(String designElementType) { 18 | this.designElementType = designElementType; 19 | } 20 | public double getRatio() { 21 | return ratio; 22 | } 23 | public void setRatio(double ratio) { 24 | this.ratio = ratio; 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/AbstractMcfAreaContentImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import net.sf.mcf2pdf.mcfelements.McfArea; 7 | import net.sf.mcf2pdf.mcfelements.McfAreaContent; 8 | 9 | public abstract class AbstractMcfAreaContentImpl implements McfAreaContent { 10 | 11 | private McfArea area; 12 | 13 | public McfArea getArea() { 14 | return area; 15 | } 16 | 17 | public void setArea(McfArea area) { 18 | this.area = area; 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfconfig/Fotoarea.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfconfig; 2 | 3 | public class Fotoarea { 4 | private double x; 5 | private double y; 6 | private double width; 7 | private double height; 8 | 9 | public double getX() { 10 | return x; 11 | } 12 | public void setX(double x) { 13 | this.x = x; 14 | } 15 | public double getY() { 16 | return y; 17 | } 18 | public void setY(double y) { 19 | this.y = y; 20 | } 21 | public double getWidth() { 22 | return width; 23 | } 24 | public void setWidth(double width) { 25 | this.width = width; 26 | } 27 | public double getHeight() { 28 | return height; 29 | } 30 | public void setHeight(double height) { 31 | this.height = height; 32 | } 33 | } -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/AbstractPageBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.util.List; 7 | import java.util.Vector; 8 | 9 | public abstract class AbstractPageBuilder implements PageBuilder { 10 | 11 | private List pageContents = new Vector(); 12 | 13 | @Override 14 | public void addDrawable(PageDrawable drawable) { 15 | pageContents.add(drawable); 16 | } 17 | 18 | protected final List getDrawables() { 19 | return pageContents; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfImage.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfImage extends McfAreaContent { 10 | 11 | public String getParentChildRelationshipNature(); 12 | 13 | public float getScale(); 14 | 15 | public int getUseABK(); 16 | 17 | public int getLeft(); 18 | 19 | public int getTop(); 20 | 21 | public String getFileNameMaster(); 22 | 23 | public String getSafeContainerLocation(); 24 | 25 | public String getFileName(); 26 | 27 | public String getFadingFile(); 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfClipartImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import net.sf.mcf2pdf.mcfelements.McfClipart; 7 | 8 | public class McfClipartImpl extends AbstractMcfAreaContentImpl implements McfClipart { 9 | 10 | private String uniqueName; 11 | 12 | @Override 13 | public ContentType getContentType() { 14 | return ContentType.CLIPART; 15 | } 16 | 17 | public String getUniqueName() { 18 | return uniqueName; 19 | } 20 | 21 | public void setUniqueName(String uniqueName) { 22 | this.uniqueName = uniqueName; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfglobals/McfAlbumType.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfglobals; 5 | 6 | /** 7 | * TODO comment 8 | */ 9 | public interface McfAlbumType { 10 | 11 | public String getName(); 12 | 13 | public int getSafetyMargin(); 14 | 15 | public int getBleedMargin(); 16 | 17 | public int getNormalPageHorizontalClamp(); 18 | 19 | public int getUsableWidth(); 20 | 21 | public int getUsableHeight(); 22 | 23 | public int getBleedMarginCover(); 24 | 25 | public int getCoverExtraVertical(); 26 | 27 | public int getCoverExtraHorizontal(); 28 | 29 | public int getSpineWidth(int normalPageCount); 30 | 31 | } -------------------------------------------------------------------------------- /src/main/assembly/mcf2pdf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Startup Script for mcf2pdf program. 4 | # 5 | 6 | # Adjust these variables to your local installation of the MCF software 7 | MCF_INSTALL_DIR= 8 | 9 | # This is the default value of the software 10 | MCF_TEMP_DIR=~/.mcf 11 | 12 | # 13 | # Java Options. You can adjust the amount of reserved memory (RAM) here. 14 | # 15 | MCF2PDF_JAVA_OPTS="-Xms64M -Xmx128M" 16 | 17 | 18 | # check if this file has to be adjusted! 19 | if [ "$MCF_INSTALL_DIR" == "" ] 20 | then 21 | echo "The installation directory of the MCF software has not been set! Please edit the file $0 with a text editor first." 22 | exit 3 23 | fi 24 | 25 | java $MCF2PDF_JAVA_OPTS -classpath "${classpath}:$MCF_INSTALL_DIR:mcf2pdf-${project.version}.jar" net.sf.mcf2pdf.Main -i "$MCF_INSTALL_DIR" -t "$MCF_TEMP_DIR" "$@" 26 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/webp/WebpLib.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfelements.util.webp; 2 | 3 | import com.sun.jna.Library; 4 | import com.sun.jna.Pointer; 5 | 6 | /** 7 | * JNA interface with all required methods to be dynamically linked and accessed 8 | * from the shared WebP library. Derived from https://code.woboq.org/qt5/qtimageformats/src/3rdparty/libwebp/src/webp/decode.h.html 10 | * 11 | * @author Florian Albrecht 12 | * 13 | */ 14 | public interface WebpLib extends Library { 15 | 16 | int WebPGetInfo(byte[] data, int data_size, int[] width, int[] height); 17 | 18 | Pointer WebPDecodeRGBAInto(byte[] data, int data_size, byte[] output_buffer, int output_buffer_size, 19 | int output_stride); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfFotobook.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | import java.io.File; 7 | import java.util.List; 8 | 9 | /** 10 | * TODO comment 11 | */ 12 | public interface McfFotobook { 13 | 14 | public File getFile(); 15 | 16 | public List getPages(); 17 | 18 | public int getProductType(); 19 | 20 | public String getProductName(); 21 | 22 | public String getVersion(); 23 | 24 | public String getCreatedWithHPSVersion(); 25 | 26 | public String getProgramVersion(); 27 | 28 | public String getImageDir(); 29 | 30 | public int getNormalPages(); 31 | 32 | public int getTotalPages(); 33 | 34 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfImageBackgroundImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import net.sf.mcf2pdf.mcfelements.McfImageBackground; 7 | 8 | public class McfImageBackgroundImpl extends McfImageImpl implements McfImageBackground { 9 | 10 | private String backgroundPosition; 11 | 12 | @Override 13 | public ContentType getContentType() { 14 | return ContentType.IMAGEBACKGROUND; 15 | } 16 | 17 | public String getBackgroundPosition() { 18 | return backgroundPosition; 19 | } 20 | 21 | public void setBackgroundPosition(String backgroundPosition) { 22 | this.backgroundPosition = backgroundPosition; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/net/sf/mcf2pdf/util/ImageUtilTest.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.util; 2 | 3 | import java.io.File; 4 | 5 | import org.junit.Assert; 6 | import org.junit.Ignore; 7 | import org.junit.Test; 8 | 9 | import net.sf.mcf2pdf.mcfelements.util.ImageUtil; 10 | 11 | public class ImageUtilTest { 12 | 13 | @Test 14 | @Ignore("Currently disabled as no longer used by CEWE?!") 15 | public void testPngWithRes() throws Exception { 16 | float[] res = ImageUtil.getImageResolution(new File("./src/test/resources/Bertrand1-figure-withres.png")); 17 | Assert.assertEquals(72.009f, res[0], 0.01f); 18 | Assert.assertEquals(72.009f, res[1], 0.01f); 19 | } 20 | 21 | @Test 22 | public void testPngWithoutRes() throws Exception { 23 | float[] res = ImageUtil.getImageResolution(new File("./src/test/resources/Bertrand1-figure.png")); 24 | Assert.assertEquals(180.0f, res[0], 0.01f); 25 | Assert.assertEquals(180.0f, res[1], 0.01f); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfPage.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | import java.util.List; 7 | import java.util.regex.Pattern; 8 | 9 | /** 10 | * TODO comment 11 | */ 12 | public interface McfPage { 13 | 14 | public final static Pattern FULLCOVER = Pattern.compile("FULLCOVER|fullcover"); 15 | 16 | public final static Pattern CONTENT = Pattern.compile("CONTENT|normalpage"); 17 | 18 | public final static Pattern EMPTY = Pattern.compile("EMPTY|emptypage"); 19 | 20 | public final static Pattern SPINE = Pattern.compile("SPINE|spine"); 21 | 22 | public McfFotobook getFotobook(); 23 | 24 | public List getAreas(); 25 | 26 | public List getBackgrounds(); 27 | 28 | public int getPageNr(); 29 | 30 | public String getType(); 31 | 32 | } -------------------------------------------------------------------------------- /src/main/assembly/classpath.unix: -------------------------------------------------------------------------------- 1 | classpath=lib/jdom-1.1.jar:lib/fop-1.0.jar:lib/xmlgraphics-commons-1.4.jar:lib/batik-svg-dom-1.7.jar:lib/batik-anim-1.7.jar:lib/batik-parser-1.7.jar:lib/batik-bridge-1.7.jar:lib/batik-script-1.7.jar:lib/batik-js-1.7.jar:lib/batik-xml-1.7.jar:lib/xalan-2.6.0.jar:lib/batik-awt-util-1.7.jar:lib/batik-gvt-1.7.jar:lib/batik-transcoder-1.7.jar:lib/batik-extension-1.7.jar:lib/batik-ext-1.7.jar:lib/commons-io-1.3.1.jar:lib/avalon-framework-api-4.3.1.jar:lib/avalon-framework-impl-4.3.1.jar:lib/batik-svggen-1.7.jar:lib/batik-util-1.7.jar:lib/xml-apis-1.3.04.jar:lib/batik-swing-1.7.jar:lib/batik-css-1.7.jar:lib/batik-dom-1.7.jar:lib/batik-gui-util-1.7.jar:lib/xml-apis-ext-1.3.04.jar:lib/batik-codec-1.7.jar:lib/commons-digester3-3.1.jar:lib/commons-logging-1.1.1.jar:lib/commons-beanutils-1.8.3.jar:lib/commons-cli-1.2.jar:lib/log4j-1.2.9.jar:lib/jempbox-1.6.0.jar:lib/metadata-extractor-2.9.1.jar:lib/xmpcore-5.1.2.jar:lib/pngj-2.1.0.jar:lib/jna-4.1.0.jar:lib/jna-platform-4.1.0.jar:lib/junit-4.11.jar:lib/hamcrest-core-1.3.jar:lib/jai-imageio-core-1.3.0.jar -------------------------------------------------------------------------------- /src/main/assembly/src.xml: -------------------------------------------------------------------------------- 1 | 4 | src 5 | 6 | tar.gz 7 | 8 | true 9 | 10 | 11 | src 12 | src 13 | true 14 | 15 | 16 | / 17 | 18 | README 19 | LICENSE 20 | 21 | true 22 | 23 | 24 | / 25 | 26 | pom.xml 27 | 28 | false 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/assembly/classpath.win: -------------------------------------------------------------------------------- 1 | classpath=lib\\jdom-1.1.jar;lib\\fop-1.0.jar;lib\\xmlgraphics-commons-1.4.jar;lib\\batik-svg-dom-1.7.jar;lib\\batik-anim-1.7.jar;lib\\batik-parser-1.7.jar;lib\\batik-bridge-1.7.jar;lib\\batik-script-1.7.jar;lib\\batik-js-1.7.jar;lib\\batik-xml-1.7.jar;lib\\xalan-2.6.0.jar;lib\\batik-awt-util-1.7.jar;lib\\batik-gvt-1.7.jar;lib\\batik-transcoder-1.7.jar;lib\\batik-extension-1.7.jar;lib\\batik-ext-1.7.jar;lib\\commons-io-1.3.1.jar;lib\\avalon-framework-api-4.3.1.jar;lib\\avalon-framework-impl-4.3.1.jar;lib\\batik-svggen-1.7.jar;lib\\batik-util-1.7.jar;lib\\xml-apis-1.3.04.jar;lib\\batik-swing-1.7.jar;lib\\batik-css-1.7.jar;lib\\batik-dom-1.7.jar;lib\\batik-gui-util-1.7.jar;lib\\xml-apis-ext-1.3.04.jar;lib\\batik-codec-1.7.jar;lib\\commons-digester3-3.1.jar;lib\\commons-logging-1.1.1.jar;lib\\commons-beanutils-1.8.3.jar;lib\\commons-cli-1.2.jar;lib\\log4j-1.2.9.jar;lib\\jempbox-1.6.0.jar;lib\\metadata-extractor-2.9.1.jar;lib\\xmpcore-5.1.2.jar;lib\\pngj-2.1.0.jar;lib\\jna-4.1.0.jar;lib\\jna-platform-4.1.0.jar;lib\\junit-4.11.jar;lib\\hamcrest-core-1.3.jar;lib\\jai-imageio-core-1.3.0.jar -------------------------------------------------------------------------------- /src/main/assembly/classpath-filter.win: -------------------------------------------------------------------------------- 1 | windowsClasspath=lib\\jdom-1.1.jar;lib\\fop-1.0.jar;lib\\xmlgraphics-commons-1.4.jar;lib\\batik-svg-dom-1.7.jar;lib\\batik-anim-1.7.jar;lib\\batik-parser-1.7.jar;lib\\batik-bridge-1.7.jar;lib\\batik-script-1.7.jar;lib\\batik-js-1.7.jar;lib\\batik-xml-1.7.jar;lib\\xalan-2.6.0.jar;lib\\batik-awt-util-1.7.jar;lib\\batik-gvt-1.7.jar;lib\\batik-transcoder-1.7.jar;lib\\batik-extension-1.7.jar;lib\\batik-ext-1.7.jar;lib\\commons-io-1.3.1.jar;lib\\avalon-framework-api-4.3.1.jar;lib\\avalon-framework-impl-4.3.1.jar;lib\\batik-svggen-1.7.jar;lib\\batik-util-1.7.jar;lib\\xml-apis-1.3.04.jar;lib\\batik-swing-1.7.jar;lib\\batik-css-1.7.jar;lib\\batik-dom-1.7.jar;lib\\batik-gui-util-1.7.jar;lib\\xml-apis-ext-1.3.04.jar;lib\\batik-codec-1.7.jar;lib\\commons-digester3-3.1.jar;lib\\commons-logging-1.1.1.jar;lib\\commons-beanutils-1.8.3.jar;lib\\commons-cli-1.2.jar;lib\\log4j-1.2.9.jar;lib\\jempbox-1.6.0.jar;lib\\metadata-extractor-2.9.1.jar;lib\\xmpcore-5.1.2.jar;lib\\pngj-2.1.0.jar;lib\\jna-4.1.0.jar;lib\\jna-platform-4.1.0.jar;lib\\junit-4.11.jar;lib\\hamcrest-core-1.3.jar;lib\\jai-imageio-core-1.3.0.jar -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfBorderImpl.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfelements.impl; 2 | 3 | import java.awt.Color; 4 | 5 | import net.sf.mcf2pdf.mcfelements.McfBorder; 6 | 7 | public class McfBorderImpl implements McfBorder { 8 | 9 | private Color color; 10 | 11 | private float offset; 12 | 13 | private float width; 14 | 15 | private boolean enabled; 16 | 17 | @Override 18 | public Color getColor() { 19 | return color; 20 | } 21 | 22 | public void setColor(Color color) { 23 | this.color = color; 24 | } 25 | 26 | @Override 27 | public float getOffset() { 28 | return offset; 29 | } 30 | 31 | public void setOffset(float offset) { 32 | this.offset = offset; 33 | } 34 | 35 | @Override 36 | public float getWidth() { 37 | return width; 38 | } 39 | 40 | public void setWidth(float width) { 41 | this.width = width; 42 | } 43 | 44 | @Override 45 | public boolean isEnabled() { 46 | return enabled; 47 | } 48 | 49 | public void setEnabled(boolean enabled) { 50 | this.enabled = enabled; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfglobals/impl/McfProductCatalogueImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfglobals.impl; 5 | 6 | import java.util.List; 7 | import java.util.Vector; 8 | 9 | import net.sf.mcf2pdf.mcfglobals.McfAlbumType; 10 | import net.sf.mcf2pdf.mcfglobals.McfProductCatalogue; 11 | 12 | 13 | public class McfProductCatalogueImpl extends McfProductCatalogue { 14 | 15 | private List albumTypes = new Vector(); 16 | 17 | public McfProductCatalogueImpl() { 18 | } 19 | 20 | public void addAlbumType(McfAlbumType albumType) { 21 | albumTypes.add(albumType); 22 | } 23 | 24 | @Override 25 | public McfAlbumType getAlbumType(String name) { 26 | for (McfAlbumType a : albumTypes) { 27 | if (name.equals(a.getName())) 28 | return a; 29 | } 30 | 31 | return null; 32 | } 33 | 34 | @Override 35 | public boolean isEmpty() { 36 | return albumTypes.isEmpty(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/assembly/mcf2pdf.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM 3 | REM Startup Script for mcf2pdf program. 4 | REM 5 | 6 | REM 7 | REM Adjust these variables to your local installation of the MCF software 8 | REM A common value is: C:\Program Files\cewe-fotobuch 9 | REM 10 | SET MCF_INSTALL_DIR= 11 | 12 | REM 13 | REM Enter here the location for temporary files of the MCF software. Refer to 14 | REM the options dialog in the software for this information. 15 | REM 16 | SET MCF_TEMP_DIR= 17 | 18 | REM 19 | REM Java Options. You can adjust reserved memory (RAM) here 20 | REM 21 | SET MCF2PDF_JAVA_OPTS=-Xms64M -Xmx128M 22 | 23 | 24 | 25 | 26 | REM check if this file has to be adjusted! 27 | if "%MCF_INSTALL_DIR%" == "" GOTO echo_adjust 28 | if "%MCF_TEMP_DIR%" == "" GOTO echo_adjust 29 | 30 | java %MCF2PDF_JAVA_OPTS% -classpath "${windowsClasspath};%MCF_INSTALL_DIR%;mcf2pdf-${project.version}.jar" net.sf.mcf2pdf.Main -i "%MCF_INSTALL_DIR%" -t "%MCF_TEMP_DIR%" %1 %2 %3 %4 %5 %6 %7 %8 %9 31 | 32 | GOTO end 33 | 34 | :echo_adjust 35 | ECHO The installation and/or temporary directory of the MCF software has not been set! Please edit the file mcf2pdf.bat with a text editor first. 36 | 37 | :end 38 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/DigesterUtil.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.util; 5 | 6 | import java.util.List; 7 | 8 | import org.apache.commons.digester3.Digester; 9 | import org.apache.commons.digester3.SetPropertiesRule; 10 | 11 | /** 12 | * TODO comment 13 | */ 14 | public final class DigesterUtil { 15 | 16 | private DigesterUtil() { 17 | } 18 | 19 | public static void addSetProperties(Digester digester, String pattern, 20 | List specialAttributes) { 21 | String[] attrNames = new String[specialAttributes.size()]; 22 | String[] propNames = new String[specialAttributes.size()]; 23 | 24 | for (int i = 0; i < specialAttributes.size(); i++) { 25 | attrNames[i] = specialAttributes.get(i)[0]; 26 | propNames[i] = specialAttributes.get(i)[1]; 27 | } 28 | 29 | SetPropertiesRule rule = new SetPropertiesRule(attrNames, propNames); 30 | rule.setIgnoreMissingProperty(true); 31 | digester.addRule(pattern, rule); 32 | } 33 | 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfBackgroundImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import net.sf.mcf2pdf.mcfelements.McfBackground; 7 | import net.sf.mcf2pdf.mcfelements.McfPage; 8 | 9 | public class McfBackgroundImpl implements McfBackground { 10 | 11 | private McfPage page; 12 | 13 | private String templateName; 14 | 15 | private int type; 16 | 17 | private int layout; 18 | 19 | public McfPage getPage() { 20 | return page; 21 | } 22 | 23 | public void setPage(McfPage page) { 24 | this.page = page; 25 | } 26 | 27 | public String getTemplateName() { 28 | return templateName; 29 | } 30 | 31 | public void setTemplateName(String templateName) { 32 | this.templateName = templateName; 33 | } 34 | 35 | public int getType() { 36 | return type; 37 | } 38 | 39 | public void setType(int type) { 40 | this.type = type; 41 | } 42 | 43 | public int getLayout() { 44 | return layout; 45 | } 46 | 47 | public void setLayout(int layout) { 48 | this.layout = layout; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfconfig/Fading.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfconfig; 2 | 3 | public class Fading { 4 | private String file; 5 | private String designElementType; 6 | private double ratio; 7 | private double keepAspectRatio; 8 | 9 | private Clipart clipart; 10 | private Fotoarea fotoarea; 11 | 12 | public String getFile() { 13 | return file; 14 | } 15 | public void setFile(String file) { 16 | this.file = file; 17 | } 18 | public String getDesignElementType() { 19 | return designElementType; 20 | } 21 | public void setDesignElementType(String designElementType) { 22 | this.designElementType = designElementType; 23 | } 24 | public double getRatio() { 25 | return ratio; 26 | } 27 | public void setRatio(double ratio) { 28 | this.ratio = ratio; 29 | } 30 | public double getKeepAspectRatio() { 31 | return keepAspectRatio; 32 | } 33 | public void setKeepAspectRatio(double keepAspectRatio) { 34 | this.keepAspectRatio = keepAspectRatio; 35 | } 36 | public Clipart getClipart() { 37 | return clipart; 38 | } 39 | public void setClipart(Clipart clipart) { 40 | this.clipart = clipart; 41 | } 42 | public Fotoarea getFotoarea() { 43 | return fotoarea; 44 | } 45 | public void setFotoarea(Fotoarea fotoarea) { 46 | this.fotoarea = fotoarea; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/PageImageBackground.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Point; 7 | import java.awt.image.BufferedImage; 8 | import java.io.IOException; 9 | 10 | import net.sf.mcf2pdf.mcfelements.McfImageBackground; 11 | import net.sf.mcf2pdf.mcfglobals.McfAlbumType; 12 | 13 | 14 | /** 15 | * TODO comment 16 | */ 17 | public class PageImageBackground extends PageImage { 18 | 19 | private McfImageBackground image; 20 | 21 | public PageImageBackground(McfImageBackground image) { 22 | super(image); 23 | this.image = image; 24 | } 25 | 26 | @Override 27 | public BufferedImage renderAsBitmap(PageRenderContext context, 28 | Point drawOffsetPixels) throws IOException { 29 | BufferedImage img = super.renderAsBitmap(context, drawOffsetPixels); 30 | if (McfImageBackground.RIGHT_OR_BOTTOM.equals(image.getBackgroundPosition())) { 31 | McfAlbumType albumType = context.getAlbumType(); 32 | drawOffsetPixels.x += context.toPixel(albumType.getUsableWidth() / 10.0f + 33 | albumType.getBleedMargin() / 10.0f); 34 | } 35 | return img; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/FormattedText.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Color; 7 | 8 | public class FormattedText { 9 | 10 | private String text; 11 | 12 | private boolean bold; 13 | private boolean italic; 14 | private boolean underline; 15 | 16 | private Color textColor; 17 | 18 | private String fontFamily; 19 | private float fontSize; 20 | 21 | public FormattedText(String text, boolean bold, boolean italic, 22 | boolean underline, Color textColor, String fontFamily, float fontSize) { 23 | this.text = text; 24 | this.bold = bold; 25 | this.italic = italic; 26 | this.underline = underline; 27 | this.textColor = textColor; 28 | this.fontFamily = fontFamily; 29 | this.fontSize = fontSize; 30 | } 31 | 32 | public String getText() { 33 | return text; 34 | } 35 | 36 | public boolean isBold() { 37 | return bold; 38 | } 39 | 40 | public boolean isItalic() { 41 | return italic; 42 | } 43 | 44 | public boolean isUnderline() { 45 | return underline; 46 | } 47 | 48 | public Color getTextColor() { 49 | return textColor; 50 | } 51 | 52 | public String getFontFamily() { 53 | return fontFamily; 54 | } 55 | 56 | public float getFontSize() { 57 | return fontSize; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/McfArea.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | import java.awt.Color; 7 | import java.util.regex.Pattern; 8 | 9 | /** 10 | * TODO comment 11 | */ 12 | public interface McfArea { 13 | 14 | public final static Pattern IMAGEBACKGROUNDAREA = Pattern.compile("IMAGEBACKGROUNDAREA", Pattern.CASE_INSENSITIVE); 15 | 16 | public final static Pattern IMAGEAREA = Pattern.compile("IMAGEAREA", Pattern.CASE_INSENSITIVE); 17 | 18 | public final static Pattern TEXTAREA = Pattern.compile("FREETEXTAREA|textarea"); 19 | 20 | public final static Pattern CLIPARTAREA = Pattern.compile("CLIPARTAREA", Pattern.CASE_INSENSITIVE); 21 | 22 | public McfPage getPage(); 23 | 24 | public float getLeft(); 25 | 26 | public float getTop(); 27 | 28 | public float getHeight(); 29 | 30 | public float getWidth(); 31 | 32 | public float getRotation(); 33 | 34 | public int getZPosition(); 35 | 36 | public String getAreaType(); 37 | 38 | public boolean isBorderEnabled(); 39 | 40 | public float getBorderSize(); 41 | 42 | public Color getBorderColor(); 43 | 44 | public boolean isShadowEnabled(); 45 | 46 | public int getShadowAngle(); 47 | 48 | public int getShadowIntensity(); 49 | 50 | public float getShadowDistance(); 51 | 52 | public Color getBackgroundColor(); 53 | 54 | public McfAreaContent getContent(); 55 | 56 | public McfBorder getBorder(); 57 | 58 | } -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/PageBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.io.IOException; 7 | 8 | import net.sf.mcf2pdf.mcfelements.util.XslFoDocumentBuilder; 9 | 10 | 11 | /** 12 | * Interface for page builders. A page builder is responsible for rendering a 13 | * "single" page (single from its point of view. In the context of mcf2pdf, one 14 | * page will always reflect two pages, but this is not managed by the PageBuilder). 15 | * The page builder can receive any number of PageDrawables which 16 | * must be rendered to the page, preserving their Z ordering. The page must then 17 | * be added to a given XslFoDocumentBuilder. 18 | * 19 | */ 20 | public interface PageBuilder { 21 | 22 | /** 23 | * Adds a single drawable to the page. 24 | * 25 | * @param drawable Drawable to add. 26 | */ 27 | public void addDrawable(PageDrawable drawable); 28 | 29 | /** 30 | * Adds this page to the given document builder. Normally, now the rendering 31 | * of all drawables is performed, and then one "page" object is added to the 32 | * builder. 33 | * 34 | * @param docBuilder Document Builder to add a page element to. 35 | * 36 | * @throws IOException If any I/O related problem occurs, e.g. when reading 37 | * an image file during rendering. 38 | */ 39 | public void addToDocumentBuilder(XslFoDocumentBuilder docBuilder) throws IOException; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfPageImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Vector; 9 | 10 | import net.sf.mcf2pdf.mcfelements.*; 11 | 12 | 13 | public class McfPageImpl implements McfPage { 14 | 15 | private McfFotobook fotobook; 16 | 17 | private int pageNr; 18 | 19 | private String type; 20 | 21 | private List areas = new Vector(); 22 | 23 | private List backgrounds = new Vector(); 24 | 25 | public void addArea(McfArea area) { 26 | areas.add(area); 27 | } 28 | 29 | public List getAreas() { 30 | return Collections.unmodifiableList(areas); 31 | } 32 | 33 | public void addBackground(McfBackground bg) { 34 | backgrounds.add(bg); 35 | } 36 | 37 | public List getBackgrounds() { 38 | return Collections.unmodifiableList(backgrounds); 39 | } 40 | 41 | public McfFotobook getFotobook() { 42 | return fotobook; 43 | } 44 | 45 | public void setFotobook(McfFotobook fotobook) { 46 | this.fotobook = fotobook; 47 | } 48 | 49 | public int getPageNr() { 50 | return pageNr; 51 | } 52 | 53 | public void setPageNr(int pageNr) { 54 | this.pageNr = pageNr; 55 | } 56 | 57 | public String getType() { 58 | return type; 59 | } 60 | 61 | public void setType(String type) { 62 | this.type = type; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/assembly/zip.xml: -------------------------------------------------------------------------------- 1 | 4 | bin-windows 5 | 6 | zip 7 | 8 | true 9 | 10 | 11 | lib 12 | false 13 | false 14 | runtime 15 | 16 | 17 | 18 | 19 | 20 | lib 21 | lib 22 | 23 | 24 | / 25 | 26 | README 27 | LICENSE 28 | 29 | 644 30 | true 31 | 32 | 33 | src/main/assembly 34 | / 35 | true 36 | windows 37 | 38 | mcf2pdf.bat 39 | 40 | 41 | 42 | ${project.build.directory} 43 | / 44 | 45 | ${project.name}-${project.version}.jar 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/DigesterConfigurator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import org.apache.commons.digester3.Digester; 10 | 11 | /** 12 | * Interface for objects being able to configure a Digester object to 13 | * be ready to parse the given MCF file. 14 | */ 15 | public interface DigesterConfigurator { 16 | 17 | /** 18 | * Configures the given Digester to parse the given MCF file and create 19 | * an MCF DOM with an McfFotobook as root object.
20 | * As the root McfFotobook object has a getFile() 21 | * method, this property must somehow be set on the root object. A normal way 22 | * would be to provide a setter for this property in the used McfFotobook 23 | * implementing class. This property is then set by the FotobookBuilder 24 | * on the resulting McfFotobook object after parsing the MCF file, 25 | * using BeanUtils API.
26 | * If, for some reason, your chosen DOM implementation does not offer such a 27 | * setter for the file property, you can use the File object here to somehow 28 | * inject it into your root object class. 29 | * 30 | * @param digester Digester object to configure. 31 | * @param mcfFile MCF file which is going to be parsed. 32 | * 33 | * @throws IOException If any I/O related problem occurs, e.g. when analysing 34 | * the file is required but fails. 35 | */ 36 | public void configureDigester(Digester digester, File mcfFile) throws IOException; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/assembly/tgz.xml: -------------------------------------------------------------------------------- 1 | 4 | bin-linux 5 | 6 | tar.gz 7 | 8 | true 9 | 10 | 11 | lib 12 | false 13 | false 14 | runtime 15 | 16 | 17 | 18 | 19 | 20 | lib 21 | lib 22 | *.jar 23 | 644 24 | 25 | 26 | / 27 | 28 | README 29 | LICENSE 30 | 31 | 644 32 | true 33 | 34 | 35 | src/main/assembly 36 | / 37 | true 38 | 39 | mcf2pdf 40 | 41 | 750 42 | 43 | 44 | ${project.build.directory} 45 | / 46 | 644 47 | 48 | ${project.name}-${project.version}.jar 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfTextImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import net.sf.mcf2pdf.mcfelements.McfText; 7 | 8 | public class McfTextImpl extends AbstractMcfAreaContentImpl implements McfText { 9 | 10 | private boolean isSpineText; 11 | 12 | private String htmlContent; 13 | 14 | private float verticalIndentMargin; 15 | 16 | private float indentMargin; 17 | 18 | private int backgroundColorAlpha; 19 | 20 | 21 | @Override 22 | public ContentType getContentType() { 23 | return ContentType.TEXT; 24 | } 25 | 26 | @Override 27 | public boolean isSpineText() { 28 | return isSpineText; 29 | } 30 | 31 | public void setSpineText(boolean isSpineText) { 32 | this.isSpineText = isSpineText; 33 | } 34 | 35 | @Override 36 | public String getHtmlContent() { 37 | return htmlContent; 38 | } 39 | 40 | public void setHtmlContent(String htmlContent) { 41 | this.htmlContent = htmlContent; 42 | } 43 | 44 | @Override 45 | public float getVerticalIndentMargin() { 46 | return verticalIndentMargin; 47 | } 48 | 49 | public void setVerticalIndentMargin(float verticalIndentMargin) { 50 | this.verticalIndentMargin = verticalIndentMargin; 51 | } 52 | 53 | @Override 54 | public float getIndentMargin() { 55 | return indentMargin; 56 | } 57 | 58 | public void setIndentMargin(float indentMargin) { 59 | this.indentMargin = indentMargin; 60 | } 61 | 62 | @Override 63 | public int getBackgroundColorAlpha() { 64 | return backgroundColorAlpha; 65 | } 66 | 67 | public void setBackgroundColorAlpha(int backgroundColorAlpha) { 68 | this.backgroundColorAlpha = backgroundColorAlpha; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/PageClipart.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Point; 7 | import java.awt.image.BufferedImage; 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.io.Writer; 11 | 12 | import net.sf.mcf2pdf.mcfelements.McfClipart; 13 | import net.sf.mcf2pdf.mcfelements.util.ImageUtil; 14 | 15 | 16 | /** 17 | * TODO comment 18 | */ 19 | public class PageClipart implements PageDrawable { 20 | 21 | private McfClipart clipart; 22 | 23 | public PageClipart(McfClipart clipart) { 24 | this.clipart = clipart; 25 | } 26 | 27 | @Override 28 | public float getLeftMM() { 29 | return clipart.getArea().getLeft() / 10.0f; 30 | } 31 | 32 | @Override 33 | public float getTopMM() { 34 | return clipart.getArea().getTop() / 10.0f; 35 | } 36 | 37 | @Override 38 | public boolean isVectorGraphic() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public void renderAsSvgElement(Writer writer, PageRenderContext context) throws IOException { 44 | // TODO Auto-generated method stub 45 | 46 | } 47 | 48 | @Override 49 | public BufferedImage renderAsBitmap(PageRenderContext context, 50 | Point drawOffsetPixels) throws IOException { 51 | File f = context.getClipart(clipart.getUniqueName()); 52 | if (f == null) { 53 | context.getLog().warn("Clipart not found: " + clipart.getUniqueName()); 54 | return null; 55 | } 56 | context.getLog().debug("Rendering clipart " + f); 57 | 58 | int widthPixel = context.toPixel(clipart.getArea().getWidth() / 10.0f); 59 | int heightPixel = context.toPixel(clipart.getArea().getHeight() / 10.0f); 60 | 61 | drawOffsetPixels.x = drawOffsetPixels.y = 0; 62 | return ImageUtil.loadClpFile(f, widthPixel, heightPixel); 63 | } 64 | 65 | @Override 66 | public int getZPosition() { 67 | return clipart.getArea().getZPosition(); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/McfFileUtil.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.util; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | 9 | import net.sf.mcf2pdf.mcfelements.McfFotobook; 10 | 11 | 12 | /** 13 | * Utility class for File related "hacks" in the context of the mcf2pdf project. 14 | */ 15 | public final class McfFileUtil { 16 | 17 | private McfFileUtil() { 18 | } 19 | 20 | /** 21 | * Tries some locations to find the given image file: 22 | *
  • First, it searches for the images directory within the 23 | * directory where the fotobook is stored, and if found, searches there for 24 | * the given file.
  • 25 | *
  • If not found, it is checked if the image dir exists in the CURRENT 26 | * working directory, and if exists, it is searched for the file.
  • 27 | *
  • As a last try, the given file is searched directly from where the 28 | * fotobook is stored (this is required for some older mcf files).
  • 29 | *
    30 | * 31 | * @param fileName File name to search. Should be the filename 32 | * property of an image or imagebackground tag. 33 | * @param fotobook The fotobook to use for search. 34 | * 35 | * @return The file, if found. 36 | * 37 | * @throws FileNotFoundException If the file could not be found. 38 | */ 39 | public static File getImageFile(String fileName, McfFotobook fotobook) throws FileNotFoundException { 40 | File f = new File(new File(fotobook.getFile().getParentFile(), fotobook.getImageDir()), fileName); 41 | if (f.isFile()) 42 | return f; 43 | 44 | f = new File(new File(fotobook.getImageDir()), fileName); 45 | if (f.isFile()) 46 | return f; 47 | 48 | f = new File(fotobook.getFile().getParentFile(), fileName); 49 | if (f.isFile()) 50 | return f; 51 | 52 | throw new FileNotFoundException(fileName); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/PageBinding.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Graphics2D; 7 | import java.awt.Point; 8 | import java.awt.RenderingHints; 9 | import java.awt.image.BufferedImage; 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.io.Writer; 13 | 14 | import net.sf.mcf2pdf.mcfelements.util.ImageUtil; 15 | 16 | public class PageBinding implements PageDrawable { 17 | 18 | private BufferedImage bindingImg; 19 | 20 | private float pageWidthMM; 21 | 22 | private float pageHeightMM; 23 | 24 | public PageBinding(File fBindingImg, float pageWidthMM, float pageHeightMM) throws IOException { 25 | bindingImg = ImageUtil.readImage(fBindingImg); 26 | this.pageWidthMM = pageWidthMM; 27 | this.pageHeightMM = pageHeightMM; 28 | } 29 | 30 | @Override 31 | public boolean isVectorGraphic() { 32 | return false; 33 | } 34 | 35 | @Override 36 | public void renderAsSvgElement(Writer writer, PageRenderContext context) throws IOException { 37 | throw new UnsupportedOperationException(); 38 | } 39 | 40 | @Override 41 | public BufferedImage renderAsBitmap(PageRenderContext context, 42 | Point drawOffsetPixels) throws IOException { 43 | context.getLog().debug("Rendering page binding"); 44 | float widthMM = pageWidthMM / 16.0f; 45 | 46 | int width = context.toPixel(widthMM); 47 | int height = context.toPixel(pageHeightMM); 48 | 49 | BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 50 | Graphics2D g2d = img.createGraphics(); 51 | g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); 52 | 53 | g2d.drawImage(bindingImg, 0, 0, width, height, 0, 0, bindingImg.getWidth(), bindingImg.getHeight(), null); 54 | g2d.dispose(); 55 | 56 | drawOffsetPixels.x = context.toPixel((pageWidthMM - widthMM) / 2.0f); 57 | drawOffsetPixels.y = 0; 58 | 59 | return img; 60 | } 61 | 62 | @Override 63 | public int getZPosition() { 64 | // always on top! 65 | return 10000; 66 | } 67 | 68 | @Override 69 | public float getLeftMM() { 70 | return 0; 71 | } 72 | 73 | @Override 74 | public float getTopMM() { 75 | return 0; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mcf2pdf Converter for Mein CEWE Fotobuch (My CEWE Photobook) files to PDF 2 | 3 | ## Development discontinued 4 | 5 | Hey all, thanks for all your GitHub stars and downloads :-) As you can easily see from the change dates of the files, the development of mcf2pdf **is stalled** - at least here, in the original repo. Mainly because of lack of time on my side and too many recent changes in the MCF format. 6 | 7 | As I can see from many bug reports and requests, mcf2pdf (in this version) may not work at all with recent MCF files. 8 | 9 | But hey, there are alternatives! 10 | 11 | * There are some forks, check them out! On the upper right, click the number behind "Fork". [This fork](https://github.com/rbodziony/mcf2pdf) tried to fix at least some common issues, but has also not been updated for several years now. Other people may still continue to work on their fork. 12 | * If you are a developer, you could fork this repo and update the software yourself. 13 | * Personally, I appreciate the new "cloud service" https://www.cewe-myphotos.com/. Here you can upload your photobooks and share them with others even before printing - exactly **that** was my main motivation to create mcf2pdf (to get feedback before printing). So the need for a software like mcf2pdf is much lower - at least on my end. 14 | 15 | If you have or create a good (working) fork of mcf2pdf, feel free to let me know (e.g. via an Issue in this project), and I will link you in this README. 16 | 17 | If you are interested in the previous README file here, you can find it now at [README.old.md](./README.old.md). 18 | 19 | 20 | ## Legal Stuff (Disclaimer) 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 26 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/SVGPageBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.pagebuild; 9 | 10 | import java.awt.Dimension; 11 | import java.io.File; 12 | import java.io.IOException; 13 | 14 | import net.sf.mcf2pdf.mcfelements.util.XslFoDocumentBuilder; 15 | 16 | import org.apache.batik.dom.GenericDOMImplementation; 17 | import org.apache.batik.svggen.*; 18 | import org.w3c.dom.DOMImplementation; 19 | import org.w3c.dom.Document; 20 | 21 | 22 | /** 23 | * Vector based renderer for pages. Yet to be implemented. 24 | */ 25 | public class SVGPageBuilder extends AbstractPageBuilder { 26 | 27 | private float widthMM; 28 | 29 | private float heightMM; 30 | 31 | private PageRenderContext context; 32 | 33 | private File tempImageDir; 34 | 35 | public SVGPageBuilder(float widthMM, float heightMM, PageRenderContext context, 36 | File tempImageDir) throws IOException { 37 | this.widthMM = widthMM; 38 | this.heightMM = heightMM; 39 | this.context = context; 40 | this.tempImageDir = tempImageDir; 41 | } 42 | 43 | @Override 44 | public void addToDocumentBuilder(XslFoDocumentBuilder docBuilder) 45 | throws IOException { 46 | // Get a DOMImplementation. 47 | DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); 48 | 49 | // Create an instance of org.w3c.dom.Document. 50 | String svgNS = "http://www.w3.org/2000/svg"; 51 | Document document = domImpl.createDocument(svgNS, "svg", null); 52 | 53 | SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(document); 54 | DefaultImageHandler ihandler = new ImageHandlerJPEGEncoder(tempImageDir.getAbsolutePath(), null); 55 | ctx.setImageHandler(ihandler); 56 | 57 | // Create an instance of the SVG Generator. 58 | SVGGraphics2D graphics = new SVGGraphics2D(ctx, false); 59 | graphics.setSVGCanvasSize(new Dimension(context.toPixel(widthMM), context.toPixel(heightMM))); 60 | 61 | 62 | // TODO render all drawables to canvas 63 | 64 | 65 | graphics.dispose(); 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/FotobookBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import net.sf.mcf2pdf.mcfelements.impl.DigesterConfiguratorImpl; 10 | 11 | import org.apache.commons.beanutils.BeanUtils; 12 | import org.apache.commons.digester3.Digester; 13 | import org.xml.sax.SAXException; 14 | 15 | 16 | /** 17 | * Entry point to create an MCF DOM from a given MCF input file. 18 | */ 19 | public final class FotobookBuilder { 20 | 21 | private DigesterConfigurator configurator; 22 | 23 | /** 24 | * Creates a new MCF DOM builder with default settings. 25 | */ 26 | public FotobookBuilder() { 27 | this(new DigesterConfiguratorImpl()); 28 | } 29 | 30 | /** 31 | * Creates a new MCF DOM builder which uses the given configurator to configure 32 | * the XML Digester to use. This way, you can use your own API or add some 33 | * preprocessing to the parsing process. 34 | * 35 | * @param configurator Configurator to use to configure the internal Digester 36 | * object. 37 | */ 38 | public FotobookBuilder(DigesterConfigurator configurator) { 39 | this.configurator = configurator; 40 | } 41 | 42 | /** 43 | * Reads the given MCF input file and creates an MCF DOM reflecting the 44 | * relevant parts of the content. 45 | * 46 | * @param file MCF input file. 47 | * 48 | * @return A Fotobook object reflecting the contents of the file. 49 | * 50 | * @throws IOException If any I/O related problem occurs reading the file. 51 | * @throws SAXException If any XML related problem occurs reading the file. 52 | */ 53 | public McfFotobook readFotobook(File file) throws IOException, SAXException { 54 | Digester digester = new Digester(); 55 | configurator.configureDigester(digester, file); 56 | McfFotobook fb = digester.parse(file); 57 | 58 | // try to set file on it 59 | try { 60 | BeanUtils.setProperty(fb, "file", file); 61 | } 62 | catch (Exception e) { 63 | // ignore - digester configurator will (hopefully) do it anyhow 64 | } 65 | 66 | // if this is thrown, your McfFotobook implementation has no setFile(), 67 | // and your configurator has also not set it. 68 | if (!file.equals(fb.getFile())) 69 | throw new IllegalStateException("File could not be set on photobook. Please check used DigesterConfigurator."); 70 | 71 | return fb; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfImageImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import net.sf.mcf2pdf.mcfelements.McfImage; 7 | 8 | public class McfImageImpl extends AbstractMcfAreaContentImpl implements McfImage { 9 | 10 | private String parentChildRelationshipNature; 11 | 12 | private float scale; 13 | 14 | private int useABK; 15 | 16 | private int left; 17 | 18 | private int top; 19 | 20 | private String fileNameMaster; 21 | 22 | private String safeContainerLocation; 23 | 24 | private String fileName; 25 | 26 | private String fadingFile; 27 | 28 | @Override 29 | public ContentType getContentType() { 30 | return ContentType.IMAGE; 31 | } 32 | 33 | public String getParentChildRelationshipNature() { 34 | return parentChildRelationshipNature; 35 | } 36 | 37 | public void setParentChildRelationshipNature( 38 | String parentChildRelationshipNature) { 39 | this.parentChildRelationshipNature = parentChildRelationshipNature; 40 | } 41 | 42 | public float getScale() { 43 | return scale; 44 | } 45 | 46 | public void setScale(float scale) { 47 | this.scale = scale; 48 | } 49 | 50 | public int getUseABK() { 51 | return useABK; 52 | } 53 | 54 | public void setUseABK(int useABK) { 55 | this.useABK = useABK; 56 | } 57 | 58 | public int getLeft() { 59 | return left; 60 | } 61 | 62 | public void setLeft(int left) { 63 | this.left = left; 64 | } 65 | 66 | public int getTop() { 67 | return top; 68 | } 69 | 70 | public void setTop(int top) { 71 | this.top = top; 72 | } 73 | 74 | public String getFileNameMaster() { 75 | return fileNameMaster; 76 | } 77 | 78 | public void setFileNameMaster(String fileNameMaster) { 79 | this.fileNameMaster = fileNameMaster; 80 | } 81 | 82 | public String getSafeContainerLocation() { 83 | return safeContainerLocation; 84 | } 85 | 86 | public void setSafeContainerLocation(String safeContainerLocation) { 87 | this.safeContainerLocation = safeContainerLocation; 88 | } 89 | 90 | public String getFileName() { 91 | return fileName; 92 | } 93 | 94 | public void setFileName(String fileName) { 95 | this.fileName = fileName; 96 | } 97 | 98 | public String getFadingFile() { 99 | return fadingFile; 100 | } 101 | 102 | public void setFadingFile(String fadingFile) { 103 | this.fadingFile = fadingFile; 104 | } 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfFotobookImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import java.io.File; 7 | import java.util.Collections; 8 | import java.util.List; 9 | import java.util.Vector; 10 | 11 | import net.sf.mcf2pdf.mcfelements.McfFotobook; 12 | import net.sf.mcf2pdf.mcfelements.McfPage; 13 | 14 | 15 | public class McfFotobookImpl implements McfFotobook { 16 | 17 | public File file; 18 | 19 | private int productType; 20 | 21 | private String productName; 22 | 23 | private String version; 24 | 25 | private String createdWithHPSVersion; 26 | 27 | private String programVersion; 28 | 29 | private String imageDir; 30 | 31 | private int normalPages; 32 | 33 | private int totalPages; 34 | 35 | private List pages = new Vector(); 36 | 37 | public void addPage(McfPage page) { 38 | pages.add(page); 39 | } 40 | 41 | public List getPages() { 42 | return Collections.unmodifiableList(pages); 43 | } 44 | 45 | public int getProductType() { 46 | return productType; 47 | } 48 | 49 | public void setProductType(int productType) { 50 | this.productType = productType; 51 | } 52 | 53 | public String getProductName() { 54 | return productName; 55 | } 56 | 57 | public void setProductName(String productName) { 58 | this.productName = productName; 59 | } 60 | 61 | public String getVersion() { 62 | return version; 63 | } 64 | 65 | public void setVersion(String version) { 66 | this.version = version; 67 | } 68 | 69 | public String getCreatedWithHPSVersion() { 70 | return createdWithHPSVersion; 71 | } 72 | 73 | public void setCreatedWithHPSVersion(String createdWithHPSVersion) { 74 | this.createdWithHPSVersion = createdWithHPSVersion; 75 | } 76 | 77 | public String getProgramVersion() { 78 | return programVersion; 79 | } 80 | 81 | public void setProgramVersion(String programVersion) { 82 | this.programVersion = programVersion; 83 | } 84 | 85 | public String getImageDir() { 86 | return imageDir; 87 | } 88 | 89 | public void setImageDir(String imageDir) { 90 | this.imageDir = imageDir; 91 | } 92 | 93 | public int getNormalPages() { 94 | return normalPages; 95 | } 96 | 97 | public void setNormalPages(int normalPages) { 98 | this.normalPages = normalPages; 99 | } 100 | 101 | public int getTotalPages() { 102 | return totalPages; 103 | } 104 | 105 | public void setTotalPages(int totalPages) { 106 | this.totalPages = totalPages; 107 | } 108 | 109 | public File getFile() { 110 | return file; 111 | } 112 | 113 | public void setFile(File file) { 114 | this.file = file; 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/webp/Webp.java: -------------------------------------------------------------------------------- 1 | package net.sf.mcf2pdf.mcfelements.util.webp; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.awt.image.DataBufferByte; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.IOException; 8 | 9 | import org.apache.commons.io.IOUtils; 10 | 11 | import com.sun.jna.Native; 12 | import com.sun.jna.Platform; 13 | 14 | /** 15 | * Utility class to load the dynamic library for the WebP file format from the 16 | * CEWE installation directory, and for convenient WebP image loading using that 17 | * library. 18 | * 19 | * @author Florian Albrecht 20 | * 21 | * @see WebpLib 22 | * 23 | */ 24 | public final class Webp { 25 | 26 | private Webp() { 27 | } 28 | 29 | /** 30 | * Loads the WebP library. Under Windows, the library must be named 31 | * libwebp.dll, under Linux and Mac OS X, a 32 | * libwebp.so is expected. For Windows and Linux, the shared 33 | * library is included in the mcf2pdf package. 34 | * 35 | * @return The loaded WebP library, as a dynamic Java JNA proxy. 36 | * 37 | * @throws IOException 38 | * If the library cannot be found. 39 | */ 40 | public static WebpLib loadLibrary() throws IOException { 41 | String libName = Platform.isWindows() ? "libwebp.dll" : "libwebp.so"; 42 | return (WebpLib) Native.loadLibrary(libName, WebpLib.class); 43 | } 44 | 45 | /** 46 | * Uses the Qt5 library functions to read the given WebP image file into a 47 | * {@link BufferedImage}. 48 | * 49 | * @param webpImageFile 50 | * WebP image file to read. 51 | * @param library 52 | * Qt5 library to use. Must have been retrieved using 53 | * {@link #loadLibrary(File)}. 54 | * @return The loaded WebP image, as a {@link BufferedImage}. 55 | * @throws IOException 56 | * If the image could not be loaded. 57 | */ 58 | public static BufferedImage loadWebPImage(File webpImageFile, WebpLib library) throws IOException { 59 | int[] aw = new int[1]; 60 | int[] ah = new int[1]; 61 | 62 | FileInputStream fis = new FileInputStream(webpImageFile); 63 | byte[] rawData; 64 | try { 65 | rawData = IOUtils.toByteArray(fis); 66 | } finally { 67 | IOUtils.closeQuietly(fis); 68 | } 69 | 70 | library.WebPGetInfo(rawData, rawData.length, aw, ah); 71 | int width = aw[0]; 72 | int height = ah[0]; 73 | 74 | if (width == 0 || height == 0 || width > 10000 || height > 10000) { 75 | throw new IOException("Invalid WebP file"); 76 | } 77 | 78 | // allocate BufferedImage including byte buffer 79 | BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); 80 | DataBufferByte dbb = (DataBufferByte) img.getRaster().getDataBuffer(); 81 | byte[] target = dbb.getData(); 82 | 83 | if (library.WebPDecodeRGBAInto(rawData, rawData.length, target, target.length, width * 4) == null) { 84 | throw new IOException("Could not read WebP file"); 85 | } 86 | 87 | // bring bytes into correct order (RGBA -> ABGR) 88 | for (int i = 0; i < target.length; i += 4) { 89 | byte r = target[i]; 90 | byte g = target[i + 1]; 91 | byte b = target[i + 2]; 92 | byte a = target[i + 3]; 93 | target[i] = a; 94 | target[i + 1] = b; 95 | target[i + 2] = g; 96 | target[i + 3] = r; 97 | } 98 | 99 | return img; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfglobals/impl/McfAlbumTypeImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.mcfglobals.impl; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import net.sf.mcf2pdf.mcfglobals.McfAlbumType; 14 | 15 | 16 | public class McfAlbumTypeImpl implements McfAlbumType { 17 | 18 | private String name; 19 | 20 | private int safetyMargin; 21 | 22 | private int bleedMargin; 23 | 24 | private int normalPageHorizontalClamp; 25 | 26 | private int usableWidth; 27 | 28 | private int usableHeight; 29 | 30 | private int bleedMarginCover; 31 | 32 | private int coverExtraVertical; 33 | 34 | private int coverExtraHorizontal; 35 | 36 | private Map spineWidths = new HashMap(); 37 | 38 | @Override 39 | public String getName() { 40 | return name; 41 | } 42 | 43 | @Override 44 | public int getSafetyMargin() { 45 | return safetyMargin; 46 | } 47 | 48 | @Override 49 | public int getBleedMargin() { 50 | return bleedMargin; 51 | } 52 | 53 | 54 | @Override 55 | public int getNormalPageHorizontalClamp() { 56 | return normalPageHorizontalClamp; 57 | } 58 | 59 | @Override 60 | public int getUsableWidth() { 61 | return usableWidth; 62 | } 63 | 64 | @Override 65 | public int getUsableHeight() { 66 | return usableHeight; 67 | } 68 | 69 | @Override 70 | public int getBleedMarginCover() { 71 | return bleedMarginCover; 72 | } 73 | 74 | @Override 75 | public int getCoverExtraVertical() { 76 | return coverExtraVertical; 77 | } 78 | 79 | @Override 80 | public int getCoverExtraHorizontal() { 81 | return coverExtraHorizontal; 82 | } 83 | 84 | @Override 85 | public int getSpineWidth(int normalPageCount) { 86 | Integer key = Integer.valueOf(normalPageCount); 87 | if (!spineWidths.containsKey(key)) 88 | return 0; 89 | 90 | return spineWidths.get(key).intValue(); 91 | } 92 | 93 | public void setName(String name) { 94 | this.name = name; 95 | } 96 | 97 | public void setSafetyMargin(int safetyMargin) { 98 | this.safetyMargin = safetyMargin; 99 | } 100 | 101 | public void setBleedMargin(int bleedMargin) { 102 | this.bleedMargin = bleedMargin; 103 | } 104 | 105 | public void setNormalPageHorizontalClamp(int normalPageHorizontalClamp) { 106 | this.normalPageHorizontalClamp = normalPageHorizontalClamp; 107 | } 108 | 109 | public void setUsableWidth(int usableWidth) { 110 | this.usableWidth = usableWidth; 111 | } 112 | 113 | public void setUsableHeight(int usableHeight) { 114 | this.usableHeight = usableHeight; 115 | } 116 | 117 | public void setBleedMarginCover(int bleedMarginCover) { 118 | this.bleedMarginCover = bleedMarginCover; 119 | } 120 | 121 | public void setCoverExtraVertical(int coverExtraVertical) { 122 | this.coverExtraVertical = coverExtraVertical; 123 | } 124 | 125 | public void setCoverExtraHorizontal(int coverExtraHorizontal) { 126 | this.coverExtraHorizontal = coverExtraHorizontal; 127 | } 128 | 129 | public void addSpine(int pageCount, int width) { 130 | spineWidths.put(pageCount, width); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/ClpInputStream.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.mcfelements.util; 9 | 10 | import java.io.*; 11 | import java.nio.ByteBuffer; 12 | import java.nio.charset.Charset; 13 | 14 | /** 15 | * InputStream filter for the ugly CLP format.
    16 | * This format is a somewhat "obfuscated" SVG file. Every character of the SVG 17 | * file is written as hexadecimal representation of the byte value of that 18 | * character, and from time to time, random characters which cannot be interpreted 19 | * as hexadecimal are inserted. The first character is always an "a" which 20 | * also has to be ignored (although this would be a valid hexadecimal character).
    21 | * This class is not optimized for speed. It is kept as simple as possible, as 22 | * CLP files tend to be rather small. 23 | */ 24 | public class ClpInputStream extends FilterInputStream { 25 | 26 | private boolean firstByte = true; 27 | 28 | public ClpInputStream(InputStream in) { 29 | super(in); 30 | } 31 | 32 | @Override 33 | public int read() throws IOException { 34 | if (firstByte) { 35 | // first byte has to be ignored and must be "a" 36 | int b = in.read(); 37 | if (b == -1) 38 | return -1; // okay - empty stream 39 | if (b != 0x61) 40 | throw new IOException("CLP data must start with byte 0x61"); 41 | firstByte = false; 42 | } 43 | 44 | // read two bytes, interpret them as a string and convert that string 45 | // to a hexadecimal number. Ignore non-hexadecimal characters. 46 | int i1 = readValidCharacter(); 47 | if (i1 == -1) 48 | return -1; 49 | int i2 = readValidCharacter(); 50 | if (i2 == -1) 51 | throw new EOFException("Unexpected end of CLP data"); 52 | 53 | char c1 = (char)i1; 54 | char c2 = (char)i2; 55 | String s = new StringBuilder().append(c1).append(c2).toString(); 56 | 57 | try { 58 | return Integer.valueOf(s, 16).intValue(); 59 | } 60 | catch (NumberFormatException nfe) { 61 | // should not occur due to checks in readValidCharacter() 62 | throw new IOException("Invalid character sequence found: " + s); 63 | } 64 | } 65 | 66 | @Override 67 | public int read(byte[] b, int off, int len) throws IOException { 68 | // fallback to simple read() 69 | // TODO replace with an optimized version 70 | 71 | int cnt = 0; 72 | for (int i = 0; i < len; i++) { 73 | int n = read(); 74 | if (n == -1) 75 | return (cnt == 0 ? -1 : cnt); 76 | b[off + i] = (byte)n; 77 | cnt++; 78 | } 79 | 80 | return cnt == 0 ? -1 : cnt; 81 | } 82 | 83 | @Override 84 | public boolean markSupported() { 85 | return false; 86 | } 87 | 88 | @Override 89 | public int read(byte[] b) throws IOException { 90 | return read(b, 0, b.length); 91 | } 92 | 93 | private static Charset CS_ISO = Charset.forName("ISO-8859-1"); 94 | 95 | private int readValidCharacter() throws IOException { 96 | String s; 97 | char c; 98 | do { 99 | int b = in.read(); 100 | if (b == -1) 101 | return -1; 102 | ByteBuffer bb = ByteBuffer.wrap(new byte[] { (byte)b }); 103 | c = CS_ISO.decode(bb).charAt(0); 104 | s = "" + c; 105 | if (!s.matches("[0-9a-zA-Z]")) 106 | throw new IOException("Unexpected character found in CLP data: " + s); 107 | } 108 | while (!s.matches("[0-9a-fA-F]")); 109 | return c; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/PdfUtil.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.mcfelements.util; 9 | 10 | import java.io.BufferedOutputStream; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.io.OutputStream; 14 | 15 | import javax.xml.transform.Result; 16 | import javax.xml.transform.Source; 17 | import javax.xml.transform.Transformer; 18 | import javax.xml.transform.TransformerException; 19 | import javax.xml.transform.TransformerFactory; 20 | import javax.xml.transform.sax.SAXResult; 21 | import javax.xml.transform.stream.StreamSource; 22 | 23 | import org.apache.commons.logging.Log; 24 | import org.apache.commons.logging.LogFactory; 25 | import org.apache.fop.apps.FOPException; 26 | import org.apache.fop.apps.FOUserAgent; 27 | import org.apache.fop.apps.Fop; 28 | import org.apache.fop.apps.FopFactory; 29 | import org.apache.fop.apps.FormattingResults; 30 | import org.apache.fop.apps.MimeConstants; 31 | import org.apache.fop.apps.PageSequenceResults; 32 | 33 | /** 34 | * Utility class for working with PDFs. 35 | */ 36 | public class PdfUtil { 37 | 38 | private final static Log log = LogFactory.getLog(PdfUtil.class); 39 | 40 | /** 41 | * Converts an FO file to a PDF file using Apache FOP. 42 | * 43 | * @param fo the FO file 44 | * @param pdf the target PDF file 45 | * @param dpi the DPI resolution to use for bitmaps in the PDF 46 | * @throws IOException In case of an I/O problem 47 | * @throws FOPException In case of a FOP problem 48 | * @throws TransformerException In case of XML transformer problem 49 | */ 50 | @SuppressWarnings("rawtypes") 51 | public static void convertFO2PDF(InputStream fo, OutputStream pdf, int dpi) throws IOException, 52 | FOPException, TransformerException { 53 | 54 | FopFactory fopFactory = FopFactory.newInstance(); 55 | 56 | FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); 57 | // configure foUserAgent as desired 58 | foUserAgent.setTargetResolution(dpi); 59 | 60 | // Setup output stream. Note: Using BufferedOutputStream 61 | // for performance reasons (helpful with FileOutputStreams). 62 | OutputStream out = new BufferedOutputStream(pdf); 63 | 64 | // Construct fop with desired output format 65 | Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out); 66 | 67 | // Setup JAXP using identity transformer 68 | TransformerFactory factory = TransformerFactory.newInstance(); 69 | Transformer transformer = factory.newTransformer(); // identity 70 | // transformer 71 | 72 | // Setup input stream 73 | Source src = new StreamSource(fo); 74 | 75 | // Resulting SAX events (the generated FO) must be piped through to FOP 76 | Result res = new SAXResult(fop.getDefaultHandler()); 77 | 78 | // Start XSLT transformation and FOP processing 79 | transformer.transform(src, res); 80 | 81 | // Result processing 82 | FormattingResults foResults = fop.getResults(); 83 | java.util.List pageSequences = foResults.getPageSequences(); 84 | for (java.util.Iterator it = pageSequences.iterator(); it.hasNext();) { 85 | PageSequenceResults pageSequenceResults = (PageSequenceResults)it 86 | .next(); 87 | log.debug("PageSequence " 88 | + (String.valueOf(pageSequenceResults.getID()).length() > 0 ? pageSequenceResults 89 | .getID() : "") + " generated " 90 | + pageSequenceResults.getPageCount() + " pages."); 91 | } 92 | log.info("Generated " + foResults.getPageCount() + " PDF pages in total."); 93 | out.flush(); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/BitmapPageBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.pagebuild; 9 | 10 | import java.awt.Color; 11 | import java.awt.Graphics2D; 12 | import java.awt.Point; 13 | import java.awt.image.BufferedImage; 14 | import java.io.File; 15 | import java.io.FileNotFoundException; 16 | import java.io.IOException; 17 | import java.util.Collections; 18 | import java.util.Comparator; 19 | import java.util.List; 20 | import java.util.Vector; 21 | 22 | import javax.imageio.ImageIO; 23 | 24 | import net.sf.mcf2pdf.mcfelements.util.XslFoDocumentBuilder; 25 | 26 | import org.jdom.Element; 27 | import org.jdom.Namespace; 28 | 29 | 30 | 31 | public class BitmapPageBuilder extends AbstractPageBuilder { 32 | 33 | private File tempImageDir; 34 | 35 | private PageRenderContext context; 36 | 37 | private float widthMM; 38 | 39 | private float heightMM; 40 | 41 | private static final Comparator zComp = new Comparator() { 42 | @Override 43 | public int compare(PageDrawable p1, PageDrawable p2) { 44 | return p1.getZPosition() - p2.getZPosition(); 45 | } 46 | }; 47 | 48 | public BitmapPageBuilder(float widthMM, float heightMM, 49 | PageRenderContext context, File tempImageDir) throws IOException { 50 | this.widthMM = widthMM; 51 | this.heightMM = heightMM; 52 | this.context = context; 53 | this.tempImageDir = tempImageDir; 54 | } 55 | 56 | @Override 57 | public void addToDocumentBuilder(XslFoDocumentBuilder docBuilder) 58 | throws IOException { 59 | // render drawables onto image, regardless of type 60 | List pageContents = new Vector(getDrawables()); 61 | Collections.sort(pageContents, zComp); 62 | 63 | context.getLog().debug("Creating full page image from page elements"); 64 | 65 | BufferedImage img = new BufferedImage(context.toPixel(widthMM), 66 | context.toPixel(heightMM), BufferedImage.TYPE_INT_ARGB); 67 | Graphics2D g2d = img.createGraphics(); 68 | g2d.setColor(Color.white); 69 | g2d.fillRect(0, 0, img.getWidth(), img.getHeight()); 70 | 71 | for (PageDrawable pd : pageContents) { 72 | int left = context.toPixel(pd.getLeftMM()); 73 | int top = context.toPixel(pd.getTopMM()); 74 | 75 | Point offset = new Point(); 76 | try { 77 | BufferedImage pdImg = pd.renderAsBitmap(context, offset); 78 | if (pdImg != null) 79 | g2d.drawImage(pdImg, left + offset.x, top + offset.y, null); 80 | } 81 | catch (FileNotFoundException e) { 82 | // ignore 83 | // throw e; 84 | } 85 | } 86 | 87 | docBuilder.addPageElement(createXslFoElement(img, docBuilder.getNamespace()), widthMM, heightMM); 88 | g2d.dispose(); 89 | } 90 | 91 | private Element createXslFoElement(BufferedImage img, Namespace xslFoNs) throws IOException { 92 | // save bitmap to file 93 | File f; 94 | int i = 1; 95 | do { 96 | f = new File(tempImageDir, (i++) + ".jpg"); 97 | } 98 | while (f.isFile()); 99 | 100 | BufferedImage imgPlain = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); 101 | Graphics2D g2d = imgPlain.createGraphics(); 102 | g2d.drawImage(img, 0, 0, null); 103 | g2d.dispose(); 104 | 105 | ImageIO.write(imgPlain, "jpeg", f); 106 | 107 | Element eg = new Element("external-graphic", xslFoNs); 108 | eg.setAttribute("src", f.getAbsolutePath()); 109 | eg.setAttribute("content-width", widthMM + "mm"); 110 | eg.setAttribute("content-height", heightMM + "mm"); 111 | f.deleteOnExit(); 112 | 113 | return eg; 114 | } 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfglobals/McfProductCatalogue.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.mcfglobals; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.util.List; 13 | import java.util.Vector; 14 | 15 | import net.sf.mcf2pdf.mcfelements.util.DigesterUtil; 16 | import net.sf.mcf2pdf.mcfglobals.impl.McfAlbumTypeImpl; 17 | import net.sf.mcf2pdf.mcfglobals.impl.McfProductCatalogueImpl; 18 | 19 | import org.apache.commons.digester3.Digester; 20 | import org.xml.sax.SAXException; 21 | 22 | /** 23 | * TODO comment 24 | */ 25 | public abstract class McfProductCatalogue { 26 | 27 | public static enum CatalogueVersion { 28 | PRE_V6, V6; 29 | } 30 | 31 | public abstract McfAlbumType getAlbumType(String name); 32 | 33 | public abstract boolean isEmpty(); 34 | 35 | public static McfProductCatalogue read(InputStream in, CatalogueVersion version) throws IOException, SAXException { 36 | if (version == CatalogueVersion.V6) { 37 | return readV6(in); 38 | } 39 | 40 | // PRE_V6 41 | Digester digester = new Digester(); 42 | digester.addObjectCreate("fotobookdefinitions", McfProductCatalogueImpl.class); 43 | digester.addObjectCreate("fotobookdefinitions/album", McfAlbumTypeImpl.class); 44 | DigesterUtil.addSetProperties(digester, "fotobookdefinitions/album", getAlbumSpecialAttributes()); 45 | DigesterUtil.addSetProperties(digester, "fotobookdefinitions/album/usablesize", getUsableSizeAttributes()); 46 | digester.addCallMethod("fotobookdefinitions/album/spines/spine", "addSpine", 2, 47 | new String[] { Integer.class.getName(), Integer.class.getName() }); 48 | digester.addCallParam("fotobookdefinitions/album/spines/spine", 0, "pages"); 49 | digester.addCallParam("fotobookdefinitions/album/spines/spine", 1, "width"); 50 | digester.addSetNext("fotobookdefinitions/album", "addAlbumType"); 51 | 52 | return digester.parse(in); 53 | } 54 | 55 | private static McfProductCatalogue readV6(InputStream in) throws IOException, SAXException { 56 | Digester digester = new Digester(); 57 | digester.addObjectCreate("description", McfProductCatalogueImpl.class); 58 | digester.addObjectCreate("description/product", McfAlbumTypeImpl.class); 59 | DigesterUtil.addSetProperties(digester, "description/product", getAlbumSpecialAttributes()); 60 | DigesterUtil.addSetProperties(digester, "description/product/usablesize", getUsableSizeAttributes()); 61 | digester.addCallMethod("description/product/spines/spine", "addSpine", 2, 62 | new String[] { Integer.class.getName(), Integer.class.getName() }); 63 | digester.addCallParam("description/product/spines/spine", 0, "pages"); 64 | digester.addCallParam("description/product/spines/spine", 1, "width"); 65 | digester.addSetNext("description/product", "addAlbumType"); 66 | 67 | return digester.parse(in); 68 | } 69 | 70 | private static List getAlbumSpecialAttributes() { 71 | List result = new Vector(); 72 | result.add(new String[] { "safetymargin", "safetyMargin" }); 73 | result.add(new String[] { "bleedmargin", "bleedMargin" }); 74 | result.add(new String[] { "normalpagehorizontalclamp", "normalPageHorizontalClamp" }); 75 | result.add(new String[] { "coverextrahorizontal", "coverExtraHorizontal" }); 76 | result.add(new String[] { "coverextravertical", "coverExtraVertical" }); 77 | result.add(new String[] { "bleedmargincover", "bleedMarginCover" }); 78 | return result; 79 | } 80 | 81 | private static List getUsableSizeAttributes() { 82 | List result = new Vector(); 83 | result.add(new String[] { "width", "usableWidth" }); 84 | result.add(new String[] { "height", "usableHeight" }); 85 | return result; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/XslFoDocumentBuilder.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.mcfelements.util; 9 | 10 | import org.jdom.Document; 11 | import org.jdom.Element; 12 | import org.jdom.Namespace; 13 | 14 | /** 15 | * A builder for XSL-FO documents. This builder provides a simple way 16 | * to build a flow of pages, and internally maintains a DOM with the according 17 | * XSL-FO elements. When finished with adding content, call createDocument() 18 | * to receive the DOM object. 19 | */ 20 | public class XslFoDocumentBuilder { 21 | 22 | private Document document; 23 | 24 | private Element flow; 25 | 26 | private static final Namespace ns = Namespace.getNamespace("fo", "http://www.w3.org/1999/XSL/Format"); 27 | 28 | protected static final String EMPTY_DTD = ""; 29 | 30 | public XslFoDocumentBuilder() { 31 | document = new Document(); 32 | 33 | // create root element 34 | Element e = new Element("root", ns); 35 | 36 | document.addContent(e); 37 | } 38 | 39 | public void addPageMaster(String name, float widthMM, float heightMM) { 40 | Element m = new Element("simple-page-master", ns); 41 | m.setAttribute("master-name", name); 42 | m.setAttribute("page-width", widthMM + "mm"); 43 | m.setAttribute("page-height", heightMM + "mm"); 44 | m.setAttribute("margin", "0mm"); 45 | 46 | Element body = new Element("region-body", ns); 47 | m.addContent(body); 48 | 49 | // insert into master set, if present 50 | Element ms = document.getRootElement().getChild("layout-master-set", ns); 51 | if (ms == null) { 52 | ms = new Element("layout-master-set", ns); 53 | document.getRootElement().addContent(ms); 54 | } 55 | 56 | ms.addContent(m); 57 | } 58 | 59 | public void startFlow(String masterName) { 60 | if (flow != null) 61 | throw new IllegalStateException("Please call endFlow() first before starting a new flow!"); 62 | 63 | Element ps = new Element("page-sequence", ns); 64 | ps.setAttribute("master-reference", masterName); 65 | ps.setAttribute("id", masterName); 66 | Element f = new Element("flow", ns); 67 | f.setAttribute("flow-name", "xsl-region-body"); 68 | ps.addContent(f); 69 | document.getRootElement().addContent(ps); 70 | flow = f; 71 | } 72 | 73 | public void endFlow() { 74 | flow = null; 75 | } 76 | 77 | public void newPage() { 78 | if (flow == null) 79 | throw new IllegalStateException("Please call startFlow() first"); 80 | 81 | Element e = new Element("block", ns); 82 | e.setAttribute("break-after", "page"); 83 | e.setAttribute("padding", "0mm"); 84 | e.setAttribute("margin", "0mm"); 85 | e.setAttribute("border-width", "0mm"); 86 | flow.addContent(e); 87 | } 88 | 89 | public Document createDocument() { 90 | return (Document)document.clone(); 91 | } 92 | 93 | public Namespace getNamespace() { 94 | return ns; 95 | } 96 | 97 | public void addPageElement(Element element, float widthMM, float heightMM) { 98 | if (flow == null) 99 | throw new IllegalStateException("Please call startFlow() first"); 100 | 101 | // create block container 102 | Element bc = new Element("block-container",ns); 103 | bc.setAttribute("absolute-position", "absolute"); 104 | bc.setAttribute("left", "0mm"); 105 | bc.setAttribute("top", "0mm"); 106 | bc.setAttribute("width", widthMM + "mm"); 107 | bc.setAttribute("height", heightMM + "mm"); 108 | 109 | // create block 110 | Element b = new Element("block", ns); 111 | b.setAttribute("margin", "0mm"); 112 | b.setAttribute("padding", "0mm"); 113 | b.setAttribute("border-width", "0mm"); 114 | bc.addContent(b); 115 | 116 | b.addContent(element); 117 | 118 | flow.addContent(bc); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/util/FadingComposite.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | * All rights reserved. This file is made available under the terms of the 4 | * Common Development and Distribution License (CDDL) v1.0 which accompanies 5 | * this distribution, and is available at 6 | * http://www.opensource.org/licenses/cddl1.txt 7 | *******************************************************************************/ 8 | package net.sf.mcf2pdf.mcfelements.util; 9 | 10 | import java.awt.Composite; 11 | import java.awt.CompositeContext; 12 | import java.awt.RenderingHints; 13 | import java.awt.image.*; 14 | 15 | /** 16 | * Performs the "fading" of a rendered image with a mask image. 17 | * In MCF, the mask images have to be applied as follows: 18 | *
      19 | *
    • transparent areas have to be also transparent on target image
    • 20 | *
    • black areas are "opaque" areas of the target image
    • 21 | *
    • greyscale areas have to get an alpha value on the target image, 22 | * according to the greyscale degree.
    • 23 | *
    24 | */ 25 | public final class FadingComposite implements Composite { 26 | 27 | public static final FadingComposite INSTANCE = new FadingComposite(); 28 | 29 | private FadingComposite() { 30 | } 31 | 32 | 33 | private static boolean validateColorModel(ColorModel cm) { 34 | if (cm instanceof DirectColorModel 35 | && cm.getTransferType() == DataBuffer.TYPE_INT) { 36 | DirectColorModel directCM = (DirectColorModel)cm; 37 | 38 | return directCM.getRedMask() == 0x00FF0000 39 | && directCM.getGreenMask() == 0x0000FF00 40 | && directCM.getBlueMask() == 0x000000FF 41 | && directCM.getAlphaMask() == 0xFF000000; 42 | } 43 | 44 | return false; 45 | } 46 | 47 | /** 48 | * {@inheritDoc} 49 | */ 50 | public CompositeContext createContext(ColorModel srcColorModel, 51 | ColorModel dstColorModel, RenderingHints hints) { 52 | if (!validateColorModel(srcColorModel) 53 | || !validateColorModel(dstColorModel)) { 54 | throw new RasterFormatException("Color models are not compatible"); 55 | } 56 | 57 | return new FadingContext(this); 58 | } 59 | 60 | private static final class FadingContext implements CompositeContext { 61 | 62 | private FadingContext(FadingComposite composite) { 63 | } 64 | 65 | public void dispose() { 66 | } 67 | 68 | public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { 69 | int width = Math.min(src.getWidth(), dstIn.getWidth()); 70 | int height = Math.min(src.getHeight(), dstIn.getHeight()); 71 | 72 | int[] result = new int[4]; 73 | int[] srcPixel = new int[4]; 74 | int[] dstPixel = new int[4]; 75 | int[] srcPixels = new int[width]; 76 | int[] dstPixels = new int[width]; 77 | 78 | for (int y = 0; y < height; y++) { 79 | src.getDataElements(0, y, width, 1, srcPixels); 80 | dstIn.getDataElements(0, y, width, 1, dstPixels); 81 | for (int x = 0; x < width; x++) { 82 | // pixels are stored as INT_ARGB 83 | // our arrays are [R, G, B, A] 84 | int pixel = srcPixels[x]; 85 | srcPixel[0] = (pixel >> 16) & 0xFF; 86 | srcPixel[1] = (pixel >> 8) & 0xFF; 87 | srcPixel[2] = (pixel) & 0xFF; 88 | srcPixel[3] = (pixel >> 24) & 0xFF; 89 | 90 | pixel = dstPixels[x]; 91 | dstPixel[0] = (pixel >> 16) & 0xFF; 92 | dstPixel[1] = (pixel >> 8) & 0xFF; 93 | dstPixel[2] = (pixel) & 0xFF; 94 | dstPixel[3] = (pixel >> 24) & 0xFF; 95 | 96 | process(srcPixel, dstPixel, result); 97 | // copy back to dstPixels 98 | dstPixels[x] = ((result[3] & 0xFF) << 24) | ((result[0] & 0xFF) << 16) | 99 | ((result[1] & 0xFF) << 8) | (result[2] & 0xFF); 100 | } 101 | dstOut.setDataElements(0, y, width, 1, dstPixels); 102 | } 103 | } 104 | 105 | // The core "fading" logic 106 | private void process(int[] src, int[] dst, int[] result) { 107 | // use colors from dst, calculate alpha from src color 108 | result[0] = dst[0]; 109 | result[1] = dst[1]; 110 | result[2] = dst[2]; 111 | 112 | if (src[3] != 255) { 113 | result[3] = src[3]; 114 | } 115 | else { 116 | int alpha = 255 - (int)Math.round((src[0] + src[1] + src[2]) / 3.0); 117 | result[3] = Math.max(alpha, 0); 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/PageDrawable.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Point; 7 | import java.awt.image.BufferedImage; 8 | import java.io.IOException; 9 | import java.io.Writer; 10 | 11 | /** 12 | * The interface for objects which can be drawn by PageBuilders. 13 | * Every PageDrawable must be able to render itself as a bitmap. 14 | * Optionally, it can also be able to create an SVG element displaying its contents. 15 | */ 16 | public interface PageDrawable { 17 | 18 | /** 19 | * Indicates if this object supports rendering as an SVG element. This would 20 | * enable vector based PageBuilders to achieve better quality in 21 | * the output results. 22 | * 23 | * @return true if a call to renderAsSvgElement() is 24 | * valid, false otherwise. 25 | * 26 | * @see #renderAsSvgElement(Writer, PageRenderContext) 27 | */ 28 | public boolean isVectorGraphic(); 29 | 30 | /** 31 | * Renders this drawble as an SVG element. A typical implementation would create 32 | * a <g> element with a z-index and left-top position 33 | * calculated as "pixel position" (using the given Page Render Context), 34 | * and optionally a transformation to size the contents according to the 35 | * parameters of the underlying MCF element (e.g. scaling a clipart).
    36 | * If isVectorGraphic() for this object returns false, 37 | * this method is free to (and should) throw an UnsupportedOperationException. 38 | * 39 | * @param writer Writer to write the SVG element and content to. 40 | * @param context Current Page Render Context. 41 | * @throws IOException If any I/O related problem occurs, e.g. reading a 42 | * clipart file. 43 | */ 44 | public void renderAsSvgElement(Writer writer, PageRenderContext context) throws IOException; 45 | 46 | /** 47 | * Renders this drawable as a bitmap according to the settings of the given 48 | * Page Render Context. If attributions (border, shadow...) require a pixel-based 49 | * drawing starting on another point than the point given by getLeftMM() 50 | * and getRightMM(), the parameter drawOffsetPixels 51 | * must be filled with the required drawing offset (in pixels). 52 | * 53 | * @param context Current Page Render Context. 54 | * @param drawOffsetPixels Receives the required drawing offset, relative to 55 | * the position indicated by getLeftMM() and getRightMM(), 56 | * translated in pixels (using the Page Render Context). 57 | * 58 | * @return The rendered bitmap. 59 | * 60 | * @throws IOException If any I/O related problem occurs, e.g. reading an 61 | * image file. 62 | */ 63 | public BufferedImage renderAsBitmap(PageRenderContext context, Point drawOffsetPixels) throws IOException; 64 | 65 | /** 66 | * Returns the Z position of this drawable. This is mostly indicated by the 67 | * underlying MCF elements (by their area).
    68 | * This value is only used for bitmap based rendering; SVG elements rendered 69 | * by renderAsSvgElement() must provide their own z-index attribute. 70 | * 71 | * @return The Z Position of this drawable. The higher the value, the later 72 | * will this drawable be drawn when the page is rendered. 73 | */ 74 | public int getZPosition(); 75 | 76 | /** 77 | * Returns the x-position of this drawable, relative to the left border of the 78 | * current double page. This is mostly indicated by the underlying MCF elements (by their area).
    79 | * This value is only used for bitmap based rendering; SVG elements rendered 80 | * by renderAsSvgElement() must provide their own position attributes. 81 | * 82 | * @return The x-Position of this drawable, in millimeters. 83 | */ 84 | public float getLeftMM(); 85 | 86 | /** 87 | * Returns the y-position of this drawable, relative to the top border of the 88 | * current double page. This is mostly indicated by the underlying MCF elements (by their area).
    89 | * This value is only used for bitmap based rendering; SVG elements rendered 90 | * by renderAsSvgElement() must provide their own position attributes. 91 | * 92 | * @return The y-Position of this drawable, in millimeters. 93 | */ 94 | public float getTopMM(); 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfelements/impl/McfAreaImpl.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfelements.impl; 5 | 6 | import java.awt.Color; 7 | 8 | import net.sf.mcf2pdf.mcfelements.McfArea; 9 | import net.sf.mcf2pdf.mcfelements.McfAreaContent; 10 | import net.sf.mcf2pdf.mcfelements.McfBorder; 11 | import net.sf.mcf2pdf.mcfelements.McfPage; 12 | 13 | 14 | public class McfAreaImpl implements McfArea { 15 | 16 | private McfPage page; 17 | 18 | private float left; 19 | 20 | private float top; 21 | 22 | private float width; 23 | 24 | private float height; 25 | 26 | private float rotation; 27 | 28 | private int zPosition; 29 | 30 | private String areaType; 31 | 32 | private boolean borderEnabled; 33 | 34 | private float borderSize; 35 | 36 | private Color borderColor; 37 | 38 | private boolean shadowEnabled; 39 | 40 | private int shadowAngle; 41 | 42 | private int shadowIntensity; 43 | 44 | private float shadowDistance; 45 | 46 | private Color backgroundColor; 47 | 48 | private McfAreaContent content; 49 | 50 | private McfBorder border; 51 | 52 | @Override 53 | public McfPage getPage() { 54 | return page; 55 | } 56 | 57 | public void setPage(McfPage page) { 58 | this.page = page; 59 | } 60 | 61 | @Override 62 | public float getLeft() { 63 | return left; 64 | } 65 | 66 | public void setLeft(float left) { 67 | this.left = left; 68 | } 69 | 70 | @Override 71 | public float getTop() { 72 | return top; 73 | } 74 | 75 | public void setTop(float top) { 76 | this.top = top; 77 | } 78 | 79 | @Override 80 | public float getWidth() { 81 | return width; 82 | } 83 | 84 | public void setWidth(float width) { 85 | this.width = width; 86 | } 87 | 88 | @Override 89 | public float getHeight() { 90 | return height; 91 | } 92 | 93 | public void setHeight(float height) { 94 | this.height = height; 95 | } 96 | 97 | @Override 98 | public float getRotation() { 99 | return rotation; 100 | } 101 | 102 | public void setRotation(float rotation) { 103 | this.rotation = rotation; 104 | } 105 | 106 | @Override 107 | public int getZPosition() { 108 | return zPosition; 109 | } 110 | 111 | public void setZPosition(int zPosition) { 112 | this.zPosition = zPosition; 113 | } 114 | 115 | @Override 116 | public String getAreaType() { 117 | return areaType; 118 | } 119 | 120 | public void setAreaType(String areaType) { 121 | this.areaType = areaType; 122 | } 123 | 124 | @Override 125 | public boolean isBorderEnabled() { 126 | return borderEnabled; 127 | } 128 | 129 | public void setBorderEnabled(boolean borderEnabled) { 130 | this.borderEnabled = borderEnabled; 131 | } 132 | 133 | @Override 134 | public float getBorderSize() { 135 | return borderSize; 136 | } 137 | 138 | public void setBorderSize(float borderSize) { 139 | this.borderSize = borderSize; 140 | } 141 | 142 | @Override 143 | public Color getBorderColor() { 144 | return borderColor; 145 | } 146 | 147 | public void setBorderColor(Color borderColor) { 148 | this.borderColor = borderColor; 149 | } 150 | 151 | @Override 152 | public boolean isShadowEnabled() { 153 | return shadowEnabled; 154 | } 155 | 156 | public void setShadowEnabled(boolean shadowEnabled) { 157 | this.shadowEnabled = shadowEnabled; 158 | } 159 | 160 | @Override 161 | public int getShadowAngle() { 162 | return shadowAngle; 163 | } 164 | 165 | public void setShadowAngle(int shadowAngle) { 166 | this.shadowAngle = shadowAngle; 167 | } 168 | 169 | @Override 170 | public int getShadowIntensity() { 171 | return shadowIntensity; 172 | } 173 | 174 | public void setShadowIntensity(int shadowIntensity) { 175 | this.shadowIntensity = shadowIntensity; 176 | } 177 | 178 | @Override 179 | public float getShadowDistance() { 180 | return shadowDistance; 181 | } 182 | 183 | public void setShadowDistance(float shadowDistance) { 184 | this.shadowDistance = shadowDistance; 185 | } 186 | 187 | @Override 188 | public Color getBackgroundColor() { 189 | return backgroundColor; 190 | } 191 | 192 | public void setBackgroundColor(Color backgroundColor) { 193 | this.backgroundColor = backgroundColor; 194 | } 195 | 196 | @Override 197 | public McfAreaContent getContent() { 198 | return content; 199 | } 200 | 201 | public void setContent(McfAreaContent content) { 202 | this.content = content; 203 | } 204 | 205 | public McfBorder getBorder() { 206 | return border; 207 | } 208 | 209 | public void setBorder(McfBorder border) { 210 | this.border = border; 211 | } 212 | 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/FormattedTextParagraph.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Font; 7 | import java.awt.FontMetrics; 8 | import java.awt.Graphics2D; 9 | import java.awt.GraphicsEnvironment; 10 | import java.awt.font.TextAttribute; 11 | import java.text.AttributedCharacterIterator; 12 | import java.text.AttributedString; 13 | import java.util.Collections; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Vector; 18 | 19 | public class FormattedTextParagraph { 20 | 21 | public static enum Alignment { 22 | LEFT, CENTER, RIGHT, JUSTIFY 23 | } 24 | 25 | private Alignment alignment = Alignment.LEFT; 26 | 27 | private List texts = new Vector(); 28 | 29 | public FormattedTextParagraph() { 30 | } 31 | 32 | public FormattedTextParagraph createEmptyCopy() { 33 | FormattedTextParagraph result = new FormattedTextParagraph(); 34 | result.alignment = alignment; 35 | return result; 36 | } 37 | 38 | public void addText(FormattedText text) { 39 | // if we contain an empty start text, remove that now! 40 | if (texts.size() == 1 && texts.get(0).getText().length() == 0) 41 | texts.remove(0); 42 | texts.add(text); 43 | } 44 | 45 | public List getTexts() { 46 | return Collections.unmodifiableList(texts); 47 | } 48 | 49 | public void setAlignment(Alignment alignment) { 50 | this.alignment = alignment; 51 | } 52 | 53 | public Alignment getAlignment() { 54 | return alignment; 55 | } 56 | 57 | public AttributedCharacterIterator getCharacterIterator(PageRenderContext context) { 58 | // build whole string 59 | StringBuilder sb = new StringBuilder(); 60 | for (FormattedText text : texts) { 61 | sb.append(text.getText()); 62 | } 63 | AttributedString string = new AttributedString(sb.toString()); 64 | 65 | // apply formats 66 | int start = 0; 67 | for (FormattedText text : texts) { 68 | Map map = new HashMap(); 69 | 70 | // use font created by text (could be a loaded font!) 71 | Font font = createFont(text, context); 72 | 73 | // default attributes (could also be applied to the whole string) 74 | map.put(TextAttribute.KERNING, TextAttribute.KERNING_ON); 75 | 76 | map.put(TextAttribute.WEIGHT, text.isBold() ? 77 | TextAttribute.WEIGHT_BOLD : TextAttribute.WEIGHT_REGULAR); 78 | map.put(TextAttribute.POSTURE, text.isItalic() ? 79 | TextAttribute.POSTURE_OBLIQUE : TextAttribute.POSTURE_REGULAR); 80 | map.put(TextAttribute.UNDERLINE, text.isUnderline() ? 81 | TextAttribute.UNDERLINE_ON : Integer.valueOf(-1)); 82 | 83 | map.put(TextAttribute.FOREGROUND, text.getTextColor()); 84 | 85 | float fontSizeInch = text.getFontSize() / 72.0f; 86 | 87 | map.put(TextAttribute.SIZE, fontSizeInch * context.getTargetDpi()); 88 | font = font.deriveFont(map); 89 | map.put(TextAttribute.FONT, font); 90 | 91 | if (text.getText().length() > 0) { 92 | string.addAttributes(map, start, start + text.getText().length()); 93 | } 94 | start += text.getText().length(); 95 | } 96 | 97 | return string.getIterator(); 98 | } 99 | 100 | public boolean isEmpty() { 101 | if (texts.isEmpty()) 102 | return true; 103 | 104 | for (FormattedText t : texts) { 105 | if (t.getText().length() > 0) 106 | return false; 107 | } 108 | 109 | return true; 110 | } 111 | 112 | public int getEmptyHeight(Graphics2D graphics, PageRenderContext context) { 113 | if (texts.isEmpty()) 114 | return 0; 115 | 116 | FormattedText ft = texts.get(0); 117 | float fontSizeInch = ft.getFontSize() / 72.0f; 118 | Font font = createFont(ft, context).deriveFont(fontSizeInch * context.getTargetDpi()); 119 | 120 | FontMetrics fm = graphics.getFontMetrics(font); 121 | return fm.getHeight(); 122 | } 123 | 124 | private Font createFont(FormattedText text, PageRenderContext context) { 125 | Font font = null; 126 | for (Font f : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) { 127 | if (f.getFamily().equals(text.getFontFamily())) { 128 | // we just assume that first match to family is best match 129 | font = f; 130 | break; 131 | } 132 | } 133 | 134 | if (font == null) { 135 | font = context.getFont(text.getFontFamily()); 136 | if (font == null) 137 | return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()[0]; 138 | } 139 | 140 | return font; 141 | } 142 | 143 | 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/pagebuild/PageBackground.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.pagebuild; 5 | 6 | import java.awt.Graphics2D; 7 | import java.awt.Point; 8 | import java.awt.RenderingHints; 9 | import java.awt.image.BufferedImage; 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.io.Writer; 13 | import java.util.List; 14 | 15 | import net.sf.mcf2pdf.mcfelements.McfBackground; 16 | import net.sf.mcf2pdf.mcfelements.util.ImageUtil; 17 | import net.sf.mcf2pdf.mcfglobals.McfAlbumType; 18 | 19 | 20 | public class PageBackground implements PageDrawable { 21 | 22 | private List leftBg; 23 | 24 | private List rightBg; 25 | 26 | public PageBackground(List leftBg, 27 | List rightBg) { 28 | this.leftBg = leftBg; 29 | this.rightBg = rightBg; 30 | } 31 | 32 | @Override 33 | public boolean isVectorGraphic() { 34 | return false; 35 | } 36 | 37 | @Override 38 | public void renderAsSvgElement(Writer writer, PageRenderContext context) throws IOException { 39 | throw new UnsupportedOperationException(); 40 | } 41 | 42 | @Override 43 | public BufferedImage renderAsBitmap(PageRenderContext context, 44 | Point drawOffsetPixels) throws IOException { 45 | File fLeft = extractBackground(leftBg, context); 46 | File fRight = extractBackground(rightBg, context); 47 | 48 | McfAlbumType albumType = context.getAlbumType(); 49 | 50 | float widthMM = (albumType.getUsableWidth() + albumType.getBleedMargin()) / 10.0f * 2; 51 | float heightMM = (albumType.getUsableHeight() + albumType.getBleedMargin() * 2) / 10.0f; 52 | 53 | BufferedImage img = new BufferedImage(context.toPixel(widthMM), 54 | context.toPixel(heightMM), BufferedImage.TYPE_INT_ARGB); 55 | Graphics2D g2d = img.createGraphics(); 56 | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 57 | g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 58 | 59 | if (fLeft != null && fLeft.equals(fRight)) { 60 | // draw the background image on whole page 61 | drawBackground(fLeft, g2d, 0, 0, img.getWidth(), img.getHeight()); 62 | } 63 | else { 64 | // process background parts separate 65 | if (fLeft != null) 66 | drawBackground(fLeft, g2d, 0, 0, img.getWidth() / 2, img.getHeight()); 67 | if (fRight != null) 68 | drawBackground(fRight, g2d, img.getWidth() / 2, 0, img.getWidth() / 2, img.getHeight()); 69 | } 70 | 71 | g2d.dispose(); 72 | return img; 73 | } 74 | 75 | private void drawBackground(File f, Graphics2D g2d, int x, int y, int width, int height) throws IOException { 76 | BufferedImage img = ImageUtil.readImage(f); 77 | if (img == null) { 78 | throw new IOException("Could not read image file: " + f.getAbsolutePath()); 79 | } 80 | 81 | float tgtRatio = width / (float)height; 82 | 83 | float imgRatio = img.getWidth() / (float)img.getHeight(); 84 | float scale; 85 | boolean xVar; 86 | 87 | if (imgRatio > tgtRatio) { 88 | // scale image Y to target Y 89 | scale = height / (float)img.getHeight(); 90 | xVar = true; 91 | } 92 | else { 93 | // scale image X to target X 94 | scale = width / (float)img.getWidth(); 95 | xVar = false; 96 | } 97 | 98 | int sx = (int)(xVar ? ((img.getWidth() - (width / scale)) / 2) : 0); 99 | int sy = (int)(xVar ? 0 : ((img.getHeight() - (height / scale)) / 2)); 100 | 101 | int sw = (int)(width / scale); 102 | int sh = (int)(height / scale); 103 | 104 | g2d.drawImage(img, x, y, x + width, y + height, sx, sy, sx + sw, sy + sh, null); 105 | } 106 | 107 | private File extractBackground(List bgs, 108 | PageRenderContext context) throws IOException { 109 | for (McfBackground bg : bgs) { 110 | String tn = bg.getTemplateName(); 111 | if (tn == null || !tn.matches("[a-zA-Z0-9_]+,normal(,.*)?")) 112 | continue; 113 | 114 | tn = tn.substring(0, tn.indexOf(",")); 115 | 116 | File f = context.getBackgroundImage(tn); 117 | if (f == null) { 118 | f = context.getBackgroundColor(tn); 119 | } 120 | if (f == null) 121 | context.getLog().warn("Background not found for page " + bg.getPage().getPageNr() + ": " + tn); 122 | else 123 | return f; 124 | } 125 | 126 | return null; 127 | } 128 | 129 | @Override 130 | public int getZPosition() { 131 | return 0; 132 | } 133 | 134 | @Override 135 | public float getLeftMM() { 136 | return 0; 137 | } 138 | 139 | @Override 140 | public float getTopMM() { 141 | return 0; 142 | } 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/net/sf/mcf2pdf/mcfglobals/McfResourceScanner.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * ${licenseText} 3 | *******************************************************************************/ 4 | package net.sf.mcf2pdf.mcfglobals; 5 | 6 | import java.awt.Font; 7 | import java.awt.FontFormatException; 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Locale; 16 | import java.util.Map; 17 | 18 | import org.apache.commons.digester3.Digester; 19 | import org.apache.commons.io.IOUtils; 20 | import org.apache.commons.logging.Log; 21 | import org.apache.commons.logging.LogFactory; 22 | 23 | import net.sf.mcf2pdf.mcfconfig.Decoration; 24 | import net.sf.mcf2pdf.mcfconfig.Fading; 25 | import net.sf.mcf2pdf.mcfconfig.Template; 26 | import net.sf.mcf2pdf.mcfelements.impl.DigesterConfiguratorImpl; 27 | 28 | /** 29 | * "Dirty little helper" which scans installation directory and temporary 30 | * directory of fotobook software for background images, cliparts, fonts, 31 | * and masks (fadings). As there is no (known) usable TOC for these, we just 32 | * take what we find. 33 | */ 34 | public class McfResourceScanner { 35 | 36 | private final static Log log = LogFactory.getLog(McfResourceScanner.class); 37 | 38 | private List scanDirs = new ArrayList(); 39 | 40 | private Map foundImages = new HashMap(); 41 | 42 | private Map foundClips = new HashMap(); 43 | 44 | private Map foundFonts = new HashMap(); 45 | 46 | private Map foundColors = new HashMap(); 47 | 48 | private Map foundDecorations = new HashMap(); 49 | 50 | private File foundBinding; 51 | 52 | public McfResourceScanner(List scanDirs) { 53 | this.scanDirs.addAll(scanDirs); 54 | } 55 | 56 | public void scan() throws IOException { 57 | for (File f : scanDirs) { 58 | scanDirectory(f); 59 | } 60 | } 61 | 62 | private void scanDirectory(File dir) throws IOException { 63 | if (!dir.isDirectory()) 64 | return; 65 | 66 | for (File f : dir.listFiles()) { 67 | if (f.isDirectory()) 68 | scanDirectory(f); 69 | else { 70 | String nm = f.getName().toLowerCase(Locale.US); 71 | String path = f.getAbsolutePath(); 72 | if (nm.matches(".+\\.(jp(e?)g|webp|bmp)")) { 73 | String id = nm.substring(0, nm.indexOf(".")); 74 | foundImages.put(id, f); 75 | } 76 | else if (nm.matches(".+\\.(clp|svg)")) { 77 | String id = f.getName().substring(0, nm.lastIndexOf(".")); 78 | foundClips.put(id, f); 79 | } 80 | else if (nm.equals("1_color_backgrounds.xml")) { 81 | log.debug("Processing 1-color backgrounds " + f.getAbsolutePath()); 82 | List