Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

支持使用一个占位符批量渲染多个图像 #1164

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions poi-tl/src/main/java/com/deepoove/poi/config/Configure.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,12 @@
import java.util.Map;
import java.util.Set;

import com.deepoove.poi.policy.*;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xwpf.usermodel.XWPFRun;

import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.DocxRenderPolicy;
import com.deepoove.poi.policy.NumberingRenderPolicy;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import com.deepoove.poi.policy.TextRenderPolicy;
import com.deepoove.poi.policy.reference.DefaultChartTemplateRenderPolicy;
import com.deepoove.poi.policy.reference.DefaultPictImageTemplateRenderPolicy;
import com.deepoove.poi.policy.reference.DefaultPictureTemplateRenderPolicy;
Expand All @@ -55,7 +50,7 @@

/**
* The config of template
*
*
* @author Sayi
*/
public class Configure implements Cloneable {
Expand Down Expand Up @@ -138,7 +133,8 @@ public class Configure implements Cloneable {
Configure() {
plugin(GramerSymbol.TEXT, new TextRenderPolicy());
plugin(GramerSymbol.TEXT_ALIAS, new TextRenderPolicy());
plugin(GramerSymbol.IMAGE, new PictureRenderPolicy());
// plugin(GramerSymbol.IMAGE, new PictureRenderPolicy());
plugin(GramerSymbol.IMAGE, new PicturesRenderPolicy());
plugin(GramerSymbol.TABLE, new TableRenderPolicy());
plugin(GramerSymbol.NUMBERING, new NumberingRenderPolicy());
plugin(GramerSymbol.DOCX_TEMPLATE, new DocxRenderPolicy());
Expand All @@ -165,7 +161,7 @@ public class Configure implements Cloneable {

/**
* create default config
*
*
* @return
*/
public static Configure createDefault() {
Expand All @@ -174,7 +170,7 @@ public static Configure createDefault() {

/**
* Builder to build {@link Configure}
*
*
* @return
*/
public static ConfigureBuilder builder() {
Expand All @@ -183,7 +179,7 @@ public static ConfigureBuilder builder() {

/**
* add grammar plugin
*
*
* @param c grammar char
* @param policy render function
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
import com.deepoove.poi.data.Numberings.NumberingBuilder;

/**
* Convert Object to NumberingRenderData
*
* Convert Object to Numbering Render Data
*
* @author Sayi
*
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2014-2024 Sayi
*
* Licensed 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.
*/
package com.deepoove.poi.converter;

import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;

import java.util.ArrayList;
import java.util.List;

/**
* Convert Object to PictureRenderData
*
* @author sayi
*
*/
public class ObjectToPicturesRenderDataConverter {

public List<PictureRenderData> convert(Object source) throws Exception {
// if (null == source || source instanceof List) return (List<PictureRenderData>) source;
List<PictureRenderData> pictureRenderDataList = new ArrayList<>();

if (source instanceof List) {
for (Object o : ((List) source)) {
pictureRenderDataList.add(Pictures.of((String) o).fitSize().create());
}
}
return pictureRenderDataList;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

import com.deepoove.poi.data.style.PictureStyle;

import java.util.List;

/**
* Picture structure
*
*
* @author Sayi
*/
public abstract class PictureRenderData implements RenderData {
Expand Down Expand Up @@ -58,5 +60,4 @@ public PictureType getPictureType() {
public void setPictureType(PictureType pictureType) {
this.pictureType = pictureType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;

import java.util.List;

/**
* General logic for data verification, rendering, clearing template tags, and
* exception handling
*
*
* @author Sayi
*/
public abstract class AbstractRenderPolicy<T> implements RenderPolicy {
Expand All @@ -46,31 +48,50 @@ protected T cast(Object source) throws Exception {

@Override
public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
T model = null;
try {
model = cast(data);
} catch (Exception e) {
throw new RenderException("Error Render Data format for template: " + eleTemplate.getSource(), e);
}

RenderContext<T> context = new RenderContext<T>(eleTemplate, model, template);
try {
// validate
if (!validate(model)) {
postValidError(context);
return;
// 多图片
if (data instanceof List) {
T model = null;
try {
model = cast(data);
} catch (Exception e) {
throw new RenderException("Error Render Data format for template: " + eleTemplate.getSource(), e);
}

RenderContext<T> context = new RenderContext<T>(eleTemplate, model, template);
// do render
beforeRender(context);
doRender(context);
try {
doRender(context);
} catch (Exception e) {
reThrowException(context, e);
}
afterRender(context);
} catch (Exception e) {
reThrowException(context, e);
} else {
T model = null;
try {
model = cast(data);
} catch (Exception e) {
throw new RenderException("Error Render Data format for template: " + eleTemplate.getSource(), e);
}

RenderContext<T> context = new RenderContext<T>(eleTemplate, model, template);
try {
// validate
if (!validate(model)) {
postValidError(context);
return;
}

// do render
beforeRender(context);
doRender(context);
afterRender(context);
} catch (Exception e) {
reThrowException(context, e);
}
}

}



public abstract void doRender(RenderContext<T> context) throws Exception;

protected boolean validate(T data) {
Expand All @@ -97,10 +118,10 @@ protected void postValidError(RenderContext<T> context) {
/**
* For operations that are not in the current tag position, the tag needs to be
* cleared
*
*
* @param context
* @param clearParagraph if clear paragraph
*
*
*/
protected void clearPlaceholder(RenderContext<?> context, boolean clearParagraph) {
XWPFRun run = context.getRun();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
*/
public class PictureRenderPolicy extends AbstractRenderPolicy<PictureRenderData> {

private static ToRenderDataConverter<Object, PictureRenderData> converter = new ObjectToPictureRenderDataConverter();
private static final ToRenderDataConverter<Object, PictureRenderData> converter = new ObjectToPictureRenderDataConverter();

@Override
public PictureRenderData cast(Object source) throws Exception {
Expand Down Expand Up @@ -129,4 +129,4 @@ private static boolean isSetSize(PictureStyle style) {
&& style.getScalePattern() == WidthScalePattern.NONE;
}
}
}
}
134 changes: 134 additions & 0 deletions poi-tl/src/main/java/com/deepoove/poi/policy/PicturesRenderPolicy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright 2014-2024 Sayi
*
* Licensed 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.
*/
package com.deepoove.poi.policy;

import com.deepoove.poi.converter.ObjectToPictureRenderDataConverter;
import com.deepoove.poi.converter.ObjectToPicturesRenderDataConverter;
import com.deepoove.poi.converter.ToRenderDataConverter;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.style.PictureStyle;
import com.deepoove.poi.data.style.PictureStyle.PictureAlign;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.BufferedImageUtils;
import com.deepoove.poi.util.SVGConvertor;
import com.deepoove.poi.util.UnitUtils;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.WidthScalePattern;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
* picture render
*
* @author Sayi
*/
public class PicturesRenderPolicy extends AbstractRenderPolicy<List<PictureRenderData>> {
private static final ObjectToPicturesRenderDataConverter converter = new ObjectToPicturesRenderDataConverter();

@Override
public List<PictureRenderData> cast(Object source) throws Exception {
// 转换开始
List<PictureRenderData> convert = converter.convert(source);
return convert;
}

@Override
public void doRender(RenderContext<List<PictureRenderData>> context) throws Exception {
Helper.renderPicture(context.getRun(), context.getData());
}

@Override
protected void afterRender(RenderContext<List<PictureRenderData>> context) {
clearPlaceholder(context, false);
}

@Override
protected void reThrowException(RenderContext<List<PictureRenderData>> context, Exception e) {
logger.info("Render picture " + context.getEleTemplate() + " error: {}", e.getMessage());
// String alt = context.getData().getAltMeta();
context.getRun().setText("atl", 0);
}

public static class Helper {
public static void renderPicture(XWPFRun run, List<PictureRenderData> pictures) throws Exception {
for (PictureRenderData picture : pictures) {
byte[] imageBytes = picture.readPictureData();
if (null == imageBytes) {
throw new IllegalStateException("Can't read picture byte arrays!");
}
PictureType pictureType = picture.getPictureType();
if (null == pictureType) {
pictureType = PictureType.suggestFileType(imageBytes);
}
if (null == pictureType) {
throw new RenderException("PictureRenderData must set picture type!");
}

PictureStyle style = picture.getPictureStyle();
if (null == style) style = new PictureStyle();
int width = style.getWidth();
int height = style.getHeight();
int svgScale = style.getSvgScale();

if (pictureType == PictureType.SVG) {
imageBytes = SVGConvertor.toPng(imageBytes, (float) width, (float) height, svgScale);
pictureType = PictureType.PNG;
}
if (!isSetSize(style)) {
BufferedImage original = BufferedImageUtils.readBufferedImage(imageBytes);
width = original.getWidth();
height = original.getHeight();
if (style.getScalePattern() == WidthScalePattern.FIT) {
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
int pageWidth = UnitUtils
.twips2Pixel(bodyContainer.elementPageWidth((IBodyElement) run.getParent()));
if (width > pageWidth) {
double ratio = pageWidth / (double) width;
width = pageWidth;
height = (int) (height * ratio);
}
}
}
try (InputStream stream = new ByteArrayInputStream(imageBytes)) {
PictureAlign align = style.getAlign();
if (null != align && run.getParent() instanceof XWPFParagraph) {
((XWPFParagraph) run.getParent()).setAlignment(ParagraphAlignment.valueOf(align.ordinal() + 1));
}
run.addPicture(stream, pictureType.type(), "Generated", Units.pixelToEMU(width),
Units.pixelToEMU(height));
}
}
}

private static boolean isSetSize(PictureStyle style) {
return (style.getWidth() != 0 || style.getHeight() != 0)
&& style.getScalePattern() == WidthScalePattern.NONE;
}
}
}
Loading