Skip to content

Commit

Permalink
FOP-3184: Allow change of resource level for SVG in AFP
Browse files Browse the repository at this point in the history
  • Loading branch information
simonsteiner1984 committed Jun 6, 2024
1 parent d8645e1 commit 742784c
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
public class AFPResourceLevelDefaults {

private static final Map RESOURCE_TYPE_NAMES = new java.util.HashMap();
public static final byte TYPE_SVG = Byte.MAX_VALUE;

static {
//Map to be extended as need arises:
registerResourceTypeName("goca", ResourceObject.TYPE_GRAPHIC);
registerResourceTypeName("bitmap", ResourceObject.TYPE_IMAGE);
registerResourceTypeName("svg", TYPE_SVG);
}

private static void registerResourceTypeName(String name, byte type) {
Expand All @@ -59,6 +61,7 @@ public AFPResourceLevelDefaults() {
// (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07), hard copy works just fine)
setDefaultResourceLevel(ResourceObject.TYPE_GRAPHIC,
new AFPResourceLevel(ResourceType.INLINE));
setDefaultResourceLevel(TYPE_SVG, new AFPResourceLevel(ResourceType.INLINE));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPResourceLevel;
import org.apache.fop.afp.AFPResourceLevel.ResourceType;
import org.apache.fop.afp.AFPResourceLevelDefaults;
import org.apache.fop.afp.AFPResourceManager;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.image.loader.batik.BatikImageFlavors;
Expand Down Expand Up @@ -81,8 +80,10 @@ public void handleImage(RenderingContext context, Image image, Rectangle pos)
AFPDataObjectInfo info = createDataObjectInfo();
assert (info instanceof AFPGraphicsObjectInfo);
AFPGraphicsObjectInfo graphicsObjectInfo = (AFPGraphicsObjectInfo) info;
graphicsObjectInfo.setCreatePageSegment(afpContext.getPaintingState().getWrapGocaPSeg());
AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
setDefaultToInlineResourceLevel(graphicsObjectInfo);
resourceInfo.setUri(imageSVG.getInfo().getOriginalURI());
setDefaultToInlineResourceLevel(graphicsObjectInfo, afpContext.getResourceManager());

// Create a new AFPGraphics2D
AFPPaintingState paintingState = afpContext.getPaintingState();
Expand Down Expand Up @@ -140,12 +141,12 @@ public void handleImage(RenderingContext context, Image image, Rectangle pos)
paintingState.restore(); // resume
}

private void setDefaultToInlineResourceLevel(AFPGraphicsObjectInfo graphicsObjectInfo) {
private void setDefaultToInlineResourceLevel(AFPGraphicsObjectInfo graphicsObjectInfo,
AFPResourceManager resourceManager) {
AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
//level not explicitly set/changed so default to inline for GOCA graphic objects
// (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07), hard copy works just fine)
if (!resourceInfo.levelChanged()) {
resourceInfo.setLevel(new AFPResourceLevel(ResourceType.INLINE));
resourceInfo.setLevel(resourceManager.getResourceLevelDefaults()
.getDefaultResourceLevel(AFPResourceLevelDefaults.TYPE_SVG));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Base64;
import java.util.HashMap;

import org.junit.Assert;
import org.junit.Test;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import org.apache.commons.io.IOUtils;

import org.apache.batik.anim.dom.SVGDOMImplementation;

import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;

import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceLevel;
import org.apache.fop.afp.AFPResourceManager;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.io.InternalResourceResolver;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.image.loader.batik.BatikImageFlavors;

public class AFPImageHandlerSVGTestCase {

private Document createSVGDocument(float width, float height) throws IOException {
DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
Document doc = impl.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
Element svgRoot = doc.getDocumentElement();
svgRoot.setAttributeNS(null, "width", "" + width);
svgRoot.setAttributeNS(null, "height", "" + height);
Element e = doc.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg:image");
String img = Base64.getEncoder().encodeToString(IOUtils.toByteArray(
new FileInputStream("test/resources/images/cmyk.jpg")));
e.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "data:image/jpeg;base64," + img);
e.setAttribute("width", "1px");
e.setAttribute("height", "1px");
svgRoot.appendChild(e);
return doc;
}

@Test
public void testAFPImageHandlerSVG() throws Exception {
String out = drawSVG(false);
Assert.assertEquals(out, "BEGIN RESOURCE_GROUP RG000001\n"
+ "BEGIN NAME_RESOURCE RES00001 Triplets: OBJECT_FUNCTION_SET_SPECIFICATION,\n"
+ "BEGIN IMAGE IMG00001\n"
+ "BEGIN OBJECT_ENVIRONMENT_GROUP OEG00002\n"
+ "DESCRIPTOR OBJECT_AREA Triplets: DESCRIPTOR_POSITION,MEASUREMENT_UNITS,OBJECT_AREA_SIZE,\n"
+ "POSITION OBJECT_AREA\n"
+ "MAP IMAGE Triplets: MAPPING_OPTION,\n"
+ "DESCRIPTOR IMAGE\n"
+ "END OBJECT_ENVIRONMENT_GROUP OEG00002\n"
+ "DATA IMAGE\n"
+ "END IMAGE IMG00001\n"
+ "END NAME_RESOURCE RES00001\n");
}

private String drawSVG(boolean svgPrintFileLevel) throws Exception {
AFPImageHandlerSVG handler = new AFPImageHandlerSVG();
FOUserAgent agent = FopFactory.newInstance(new URI(".")).newFOUserAgent();
InternalResourceResolver resourceResolver =
ResourceResolverFactory.createDefaultInternalResourceResolver(new URI("."));
AFPResourceManager manager = new AFPResourceManager(resourceResolver);
manager.getResourceLevelDefaults().setDefaultResourceLevel(ResourceObject.TYPE_GRAPHIC,
new AFPResourceLevel(AFPResourceLevel.ResourceType.PRINT_FILE));
if (svgPrintFileLevel) {
manager.getResourceLevelDefaults().setDefaultResourceLevel("svg",
new AFPResourceLevel(AFPResourceLevel.ResourceType.PRINT_FILE));
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
manager.createDataStream(null, stream).startPage(1, 1, 0, 1, 1);
AFPRenderingContext context =
new AFPRenderingContext(agent, manager, new AFPPaintingState(), null, new HashMap());
context.getPaintingState().setWrapGocaPSeg(true);
Document doc = createSVGDocument(1, 2);
ImageInfo info = new ImageInfo("", "");
info.setSize(new ImageSize());
ImageXMLDOM img = new ImageXMLDOM(info, doc, BatikImageFlavors.SVG_DOM);
handler.handleImage(context, img, new Rectangle());
StringBuilder sb = new StringBuilder();
InputStream bis = new ByteArrayInputStream(stream.toByteArray());
new AFPParser(false).read(bis, sb);
return sb.toString();
}

@Test
public void testAFPImageHandlerSVGResourceLevel() throws Exception {
String out = drawSVG(true);
Assert.assertEquals(out, "BEGIN RESOURCE_GROUP RG000001\n"
+ "BEGIN NAME_RESOURCE RES00001 Triplets: OBJECT_FUNCTION_SET_SPECIFICATION,\n"
+ "BEGIN IMAGE IMG00001\n"
+ "BEGIN OBJECT_ENVIRONMENT_GROUP OEG00002\n"
+ "DESCRIPTOR OBJECT_AREA Triplets: DESCRIPTOR_POSITION,MEASUREMENT_UNITS,OBJECT_AREA_SIZE,\n"
+ "POSITION OBJECT_AREA\n"
+ "MAP IMAGE Triplets: MAPPING_OPTION,\n"
+ "DESCRIPTOR IMAGE\n"
+ "END OBJECT_ENVIRONMENT_GROUP OEG00002\n"
+ "DATA IMAGE\n"
+ "END IMAGE IMG00001\n"
+ "END NAME_RESOURCE RES00001\n"
+ "BEGIN NAME_RESOURCE RES00002 Triplets: OBJECT_FUNCTION_SET_SPECIFICATION,\n"
+ "BEGIN PAGE_SEGMENT S1000001\n"
+ "BEGIN GRAPHICS S1000001\n"
+ "BEGIN OBJECT_ENVIRONMENT_GROUP OEG00001\n"
+ "DESCRIPTOR OBJECT_AREA Triplets: DESCRIPTOR_POSITION,MEASUREMENT_UNITS,OBJECT_AREA_SIZE,\n"
+ "POSITION OBJECT_AREA\n"
+ "DESCRIPTOR GRAPHICS\n"
+ "END OBJECT_ENVIRONMENT_GROUP OEG00001\n"
+ "END GRAPHICS S1000001\n"
+ "END PAGE_SEGMENT S1000001\n"
+ "END NAME_RESOURCE RES00002\n");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.Map;

import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

Expand Down Expand Up @@ -189,6 +190,19 @@ public void testPrintFileResourceDefault() throws Exception {
testResourceLevelDefault(ResourceType.PRINT_FILE);
}

@Test
public void testSVGResourceLevel() throws Exception {
Map<String, String> resourceLevels = new HashMap<>();
resourceLevels.put("svg", ResourceType.PRINT_FILE.getName());
parseConfig(createBuilder().setDefaultResourceLevels(resourceLevels));
ArgumentCaptor<AFPResourceLevelDefaults> argument = ArgumentCaptor.forClass(AFPResourceLevelDefaults.class);
verify(getDocHandler()).setResourceLevelDefaults(argument.capture());
assertEquals(new AFPResourceLevel(ResourceType.PRINT_FILE),
argument.getValue().getDefaultResourceLevel(AFPResourceLevelDefaults.TYPE_SVG));
Assert.assertTrue(
new AFPResourceLevelDefaults().getDefaultResourceLevel(AFPResourceLevelDefaults.TYPE_SVG).isInline());
}

@Test
public void testBitmapEncodeQuality() throws Exception {
parseConfig(createBuilder().startImages()
Expand Down

0 comments on commit 742784c

Please sign in to comment.