Commit 9a899c4e by xmh

添加注释

1 parent 9c339ec7
package com.viontech.storage.entity; package com.viontech.storage.entity;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Pair; import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.XmlUtil; import cn.hutool.core.util.XmlUtil;
...@@ -16,9 +14,9 @@ import com.viontech.storage.service.StorageConfigService; ...@@ -16,9 +14,9 @@ import com.viontech.storage.service.StorageConfigService;
import com.viontech.storage.vo.CaptionVo; import com.viontech.storage.vo.CaptionVo;
import com.viontech.storage.vo.PicConfigVo; import com.viontech.storage.vo.PicConfigVo;
import com.viontech.storage.vo.StorageConfigVo; import com.viontech.storage.vo.StorageConfigVo;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.Accessors;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
...@@ -38,8 +36,8 @@ public class Generator { ...@@ -38,8 +36,8 @@ public class Generator {
private static final String ROOT_ELEMENT_NAME = "StorageConfig"; private static final String ROOT_ELEMENT_NAME = "StorageConfig";
private static final String FILE_VERSION = "001-012-000-000"; private static final String FILE_VERSION = "001-012-000-000";
private static final TimedCache<Long, String> STORAGE_CONFIG_ID_RESULT_CACHE = CacheUtil.newTimedCache(20 * 1000); private final Document document = XmlUtil.createXml(ROOT_ELEMENT_NAME);
private final Document document = XmlUtil.createXml("StorageConfig"); /** 来自 StorageConfig, 对应 Solution */
private final List<Context> contexts; private final List<Context> contexts;
/** key: picConfigVoId */ /** key: picConfigVoId */
private final Map<Long, PicConfigVo> picConfigMap; private final Map<Long, PicConfigVo> picConfigMap;
...@@ -68,14 +66,13 @@ public class Generator { ...@@ -68,14 +66,13 @@ public class Generator {
captionSetIds.add(copy.getCaptionSetId()); captionSetIds.add(copy.getCaptionSetId());
} }
List<Caption> captions = captionService.list( List<Caption> captions = captionService.list(captionService.query().in("caption_set_id", captionSetIds).getWrapper());
captionService.query().in("caption_set_id", captionSetIds).getWrapper()
);
this.captionSetMap = captions.stream().map(CaptionVo::copy).collect(Collectors.groupingBy(CaptionVo::getCaptionSetId, Collectors.toList())); this.captionSetMap = captions.stream().map(CaptionVo::copy).collect(Collectors.groupingBy(CaptionVo::getCaptionSetId, Collectors.toList()));
} }
public String build() { public String build() {
// 基本上算是固定写法
Node rootNode = document.getFirstChild(); Node rootNode = document.getFirstChild();
rootNode.appendChild(createTextNode("FileVersion", FILE_VERSION)); rootNode.appendChild(createTextNode("FileVersion", FILE_VERSION));
Element standard = document.createElement("Standard"); Element standard = document.createElement("Standard");
...@@ -88,6 +85,7 @@ public class Generator { ...@@ -88,6 +85,7 @@ public class Generator {
switchPathConfig.appendChild(createTextNode("CountThreshold", "64")); switchPathConfig.appendChild(createTextNode("CountThreshold", "64"));
standard.appendChild(switchPathConfig); standard.appendChild(switchPathConfig);
// 开始组装 Solution
for (Context context : contexts) { for (Context context : contexts) {
Node solution = buildSolution(context); Node solution = buildSolution(context);
if (solution != null) { if (solution != null) {
...@@ -107,6 +105,7 @@ public class Generator { ...@@ -107,6 +105,7 @@ public class Generator {
return null; return null;
} }
// 基本上算是固定写法
Element solution = document.createElement("Solution" + order); Element solution = document.createElement("Solution" + order);
solution.appendChild(createTextNode("SolutionName", picConfig.getName())); solution.appendChild(createTextNode("SolutionName", picConfig.getName()));
solution.appendChild(createTextNode("Conditions", conditions)); solution.appendChild(createTextNode("Conditions", conditions));
...@@ -121,12 +120,15 @@ public class Generator { ...@@ -121,12 +120,15 @@ public class Generator {
pathConfig.appendChild(document.createTextNode("VideoRelativePath")); pathConfig.appendChild(document.createTextNode("VideoRelativePath"));
pathConfig.appendChild(createTextNode("VideoRootPath", "/kk/video;;;;;")); pathConfig.appendChild(createTextNode("VideoRootPath", "/kk/video;;;;;"));
solution.appendChild(pathConfig); solution.appendChild(pathConfig);
// 组装图片属性和字幕
Node picConfigNode = buildPicConfig(picConfig); Node picConfigNode = buildPicConfig(picConfig);
solution.appendChild(picConfigNode); solution.appendChild(picConfigNode);
return solution; return solution;
} }
private Node buildPicConfig(PicConfigVo picConfig) { private Node buildPicConfig(PicConfigVo picConfig) {
// 没有自定义的地方,先固定写死
Element configNode = document.createElement("PicConfig"); Element configNode = document.createElement("PicConfig");
configNode.appendChild(createTextNode("PicCount", "1")); configNode.appendChild(createTextNode("PicCount", "1"));
configNode.appendChild(createTextNode("DigPicFlag", "1")); configNode.appendChild(createTextNode("DigPicFlag", "1"));
...@@ -144,7 +146,6 @@ public class Generator { ...@@ -144,7 +146,6 @@ public class Generator {
denoiser.appendChild(createTextNode("Param2", "3")); denoiser.appendChild(createTextNode("Param2", "3"));
denoiser.appendChild(createTextNode("Param3", "0.000000")); denoiser.appendChild(createTextNode("Param3", "0.000000"));
denoiser.appendChild(createTextNode("Param4", "0.000000")); denoiser.appendChild(createTextNode("Param4", "0.000000"));
Element fixedSizeQuality = XmlUtil.appendChild(picQuality, "FixedSizeQuality"); Element fixedSizeQuality = XmlUtil.appendChild(picQuality, "FixedSizeQuality");
Element st200wImageQuality = XmlUtil.appendChild(picQuality, "st200WImageQuality"); Element st200wImageQuality = XmlUtil.appendChild(picQuality, "st200WImageQuality");
Element st500wImageQuality = XmlUtil.appendChild(picQuality, "st500WImageQuality"); Element st500wImageQuality = XmlUtil.appendChild(picQuality, "st500WImageQuality");
...@@ -160,69 +161,81 @@ public class Generator { ...@@ -160,69 +161,81 @@ public class Generator {
Element pic1 = XmlUtil.appendChild(configNode, "Pic1"); Element pic1 = XmlUtil.appendChild(configNode, "Pic1");
pic1.appendChild(createTextNode("OriPicCount", String.valueOf(picConfig.calPicCount()))); pic1.appendChild(createTextNode("OriPicCount", String.valueOf(picConfig.calPicCount())));
pic1.appendChild(createTextNode("DirectSaveFlag", "0")); pic1.appendChild(createTextNode("DirectSaveFlag", "0"));
PicConfigCalculator calculator = new PicConfigCalculator(picConfig);
Coordinate[] coordinates = calculator.coordinates; PicConfigGenerator picConfigGenerator = new PicConfigGenerator(picConfig, captionSetMap.get(picConfig.getCaptionSetId()));
HashMap<Integer, Coordinate> coordinateMap = calculator.coordinateMap; PicNode[] picNodes = picConfigGenerator.getPicNodes();
for (int i = 0; i < coordinates.length; i++) { Element captionsElement = XmlUtil.appendChild(pic1, "Captions");
Coordinate item = coordinates[i]; int captionCount = 0;
for (int i = 0; i < picNodes.length; i++) {
PicNode item = picNodes[i];
Element oriPic = XmlUtil.appendChild(pic1, "OriPic" + (i + 1)); Element oriPic = XmlUtil.appendChild(pic1, "OriPic" + (i + 1));
XmlUtil.appendChild(oriPic, "Content").setTextContent(item.getName()); XmlUtil.appendChild(oriPic, "Content").setTextContent(item.getPicTypeName());
XmlUtil.appendChild(oriPic, "Type").setTextContent("0"); XmlUtil.appendChild(oriPic, "Type").setTextContent("0");
Element srcCoordinate = XmlUtil.appendChild(oriPic, "SrcCoordinate"); Element srcCoordinate = XmlUtil.appendChild(oriPic, "SrcCoordinate");
Element desCoordinate = XmlUtil.appendChild(oriPic, "DesCoordinate"); Element desCoordinate = XmlUtil.appendChild(oriPic, "DesCoordinate");
XmlUtil.appendChild(srcCoordinate, "left").setTextContent("0"); XmlUtil.appendChild(srcCoordinate, "left").setTextContent("0");
XmlUtil.appendChild(srcCoordinate, "top").setTextContent("0"); XmlUtil.appendChild(srcCoordinate, "top").setTextContent("0");
XmlUtil.appendChild(srcCoordinate, "width").setTextContent(item.getName() + "宽"); XmlUtil.appendChild(srcCoordinate, "width").setTextContent(item.getPicTypeName() + "宽");
XmlUtil.appendChild(srcCoordinate, "height").setTextContent(item.getName() + "高"); XmlUtil.appendChild(srcCoordinate, "height").setTextContent(item.getPicTypeName() + "高");
XmlUtil.appendChild(desCoordinate, "left").setTextContent(item.getX()); XmlUtil.appendChild(desCoordinate, "left").setTextContent(item.getX());
XmlUtil.appendChild(desCoordinate, "top").setTextContent(item.getY()); XmlUtil.appendChild(desCoordinate, "top").setTextContent(item.getY());
XmlUtil.appendChild(desCoordinate, "width").setTextContent("全景1宽"); XmlUtil.appendChild(desCoordinate, "width").setTextContent("全景1宽");
XmlUtil.appendChild(desCoordinate, "height").setTextContent("全景1高"); XmlUtil.appendChild(desCoordinate, "height").setTextContent("全景1高");
}
// 字幕
Long captionSetId = picConfig.getCaptionSetId();
List<CaptionVo> captionVos = captionSetMap.get(captionSetId);
Element captionsElement = XmlUtil.appendChild(pic1, "Captions");
int captionCount = 0;
for (int i = 0; i < captionVos.size(); i++) {
CaptionVo caption = captionVos.get(i);
Integer picType = caption.getPicType();
Coordinate coordinate = coordinateMap.get(picType);
if (coordinate == null) {
continue;
}
List<Context> contexts = caption.getContexts(); // 字幕
String dateFormat = (caption.getMillisecond() != null && caption.getMillisecond()) ? caption.getDateFormat() + ".xxx" : caption.getDateFormat(); CaptionNode captionNode = item.getCaptionNode();
Pair<String, Integer> combine = combineCaptionContent(picType, contexts, dateFormat); for (int j = 0; j < 4; j++) {
String content = combine.getKey(); CaptionVo caption;
Integer wrapCount = combine.getValue(); String content;
Element ele = XmlUtil.appendChild(captionsElement, "Caption" + (i + 1)); String height;
XmlUtil.appendChild(ele, "Content").setTextContent(content); if (j == 0 && captionNode.getTop() != null) {
XmlUtil.appendChild(ele, "bgColor").setTextContent(caption.getBgColor().toString()); caption = captionNode.getTop();
XmlUtil.appendChild(ele, "Font").setTextContent(caption.getFont().toString()); content = captionNode.getTopContent();
XmlUtil.appendChild(ele, "FontSize").setTextContent(caption.getFontSize().toString()); height = String.valueOf(captionNode.getTopHeight());
XmlUtil.appendChild(ele, "fgColor").setTextContent(caption.getFgColor().toString()); } else if (j == 1 && captionNode.getBottom() != null) {
XmlUtil.appendChild(ele, "ShadowColor").setTextContent("4"); caption = captionNode.getBottom();
XmlUtil.appendChild(ele, "ShadowSize").setTextContent("0"); content = captionNode.getBottomContent();
XmlUtil.appendChild(ele, "bgTransparency").setTextContent(caption.getBgTransparency().toString()); height = String.valueOf(captionNode.getBottomHeight());
Element coordinateElement = XmlUtil.appendChild(ele, "Coordinate"); } else if (j == 2 && captionNode.getSecond() != null) {
// 坐标需要根据positionType来搞 caption = captionNode.getSecond();
Integer positionType = caption.getPositionType(); content = captionNode.getSecondContent();
String y = coordinate.getY(); height = String.valueOf(captionNode.getSecondHeight());
if (positionType == 1) { } else if (j == 3 && captionNode.getThird() != null) {
y = y + "+全景1高"; caption = captionNode.getThird();
} else if (positionType == 0) { content = captionNode.getThirdContent();
y = y + "-80"; height = String.valueOf(captionNode.getThirdHeight());
} else if (positionType == 3) { } else {
y = y + "+全景1高-80"; continue;
}
captionCount++;
Element ele = XmlUtil.appendChild(captionsElement, "Caption" + captionCount);
XmlUtil.appendChild(ele, "Content").setTextContent(content);
XmlUtil.appendChild(ele, "bgColor").setTextContent(caption.getBgColor().toString());
XmlUtil.appendChild(ele, "Font").setTextContent(caption.getFont().toString());
XmlUtil.appendChild(ele, "FontSize").setTextContent(caption.getFontSize().toString());
XmlUtil.appendChild(ele, "fgColor").setTextContent(caption.getFgColor().toString());
XmlUtil.appendChild(ele, "ShadowColor").setTextContent("4");
XmlUtil.appendChild(ele, "ShadowSize").setTextContent("0");
XmlUtil.appendChild(ele, "bgTransparency").setTextContent(caption.getBgTransparency().toString());
Element coordinateElement = XmlUtil.appendChild(ele, "Coordinate");
// 坐标需要根据 positionType 来算
Integer positionType = caption.getPositionType();
String y = item.getY();
if (positionType == 1) {
y = y + "+全景1高";
} else if (positionType == 0) {
y = y + "-" + height;
} else if (positionType == 3) {
y = y + "+全景1高-" + height;
}
XmlUtil.appendChild(coordinateElement, "left").setTextContent(item.getX());
XmlUtil.appendChild(coordinateElement, "top").setTextContent(y);
XmlUtil.appendChild(coordinateElement, "width").setTextContent("全景1宽");
XmlUtil.appendChild(coordinateElement, "height").setTextContent(height);
} }
XmlUtil.appendChild(coordinateElement, "left").setTextContent(coordinate.getX());
XmlUtil.appendChild(coordinateElement, "top").setTextContent(y);
XmlUtil.appendChild(coordinateElement, "width").setTextContent("全景1宽");
int height = wrapCount == 0 ? 80 : caption.getFontSize() * wrapCount;
XmlUtil.appendChild(coordinateElement, "height").setTextContent(String.valueOf(height));
captionCount++;
} }
XmlUtil.appendChild(captionsElement, "Count").setTextContent(String.valueOf(captionCount)); XmlUtil.appendChild(captionsElement, "Count").setTextContent(String.valueOf(captionCount));
return configNode; return configNode;
...@@ -238,153 +251,440 @@ public class Generator { ...@@ -238,153 +251,440 @@ public class Generator {
return dataTypes.stream().map(x -> "数据类型=" + x).collect(Collectors.joining("+")); return dataTypes.stream().map(x -> "数据类型=" + x).collect(Collectors.joining("+"));
} }
private Pair<String, Integer> combineCaptionContent(Integer picType, List<Context> contexts, String dateFormat) { /**
if (CollectionUtil.isEmpty(contexts)) { * 一个图片属性会有多个图片节点
return Pair.of(null, null); * 按照类型不同排列
} */
String picTypeName = Dict.INSTANCE.picType.get(picType); public @Getter
StringBuilder sb = new StringBuilder(); @Setter
int wrapCount = 0; @Accessors(chain = true)
for (Context context : contexts) { static class PicNode {
Integer type = context.getType(); private final PicConfigGenerator generator;
sb.append(Dict.INSTANCE.captionType.get(type)).append(":+"); /** 图片类型代码 */
switch (type) { private final int picType;
case 1: /** 图片类型名称 */
if (picTypeName.contains("特写")) { private final String picTypeName;
picTypeName = "特写图"; private final int index;
} private CaptionNode captionNode = new CaptionNode();
sb.append("(").append(picTypeName).append("时间:").append(dateFormat).append(")"); private String x;
break; private String y;
case 9:
sb.append("(用户车辆类型1)");
break;
case 10:
sb.append("(用户车身颜色1)");
break;
case 11:
sb.append("(车辆子品牌)");
break;
case 15:
sb.append("(合成图1防伪码)");
break;
case 16:
sb.append(context.getContent());
break;
case 17:
sb.append("(违法类型代码)");
break;
default:
sb.append("(").append(Dict.INSTANCE.captionType.get(type)).append(")");
}
if (context.getWrap()) { public PicNode(PicConfigGenerator generator, int picType, int index) {
wrapCount++; this.generator = generator;
sb.append("+(换行分隔符)"); this.picTypeName = Dict.INSTANCE.picType.get(picType);
} this.picType = picType;
sb.append("+"); this.index = index;
} }
sb.setLength(sb.length() - 1);
return Pair.of(sb.toString(), wrapCount);
}
private static class PicConfigCalculator {
public final Coordinate[] coordinates;
/** key : picType */
public final HashMap<Integer, Coordinate> coordinateMap = new HashMap<>();
private final int layoutType;
public PicConfigCalculator(PicConfigVo picConfigVo) { /**
List<Context> contexts = picConfigVo.getContexts().stream().sorted(Comparator.comparingInt(Context::getOrder)).collect(Collectors.toList()); * 计算该图片在合成图上的 X 坐标
layoutType = picConfigVo.getType(); */
this.coordinates = new Coordinate[contexts.size()]; public String getX() {
for (int i = 0; i < contexts.size(); i++) { if (this.x != null) {
Context context = contexts.get(i); return this.x;
Integer picType = context.getType();
calCoordinate(i, picType);
} }
} this.x = "0";
PicNode left = getLeft();
private void calCoordinate(Integer index, Integer picType) {
String x = "0";
String y = "80";
if (index != 0) { if (index != 0) {
Coordinate pre = coordinates[index - 1]; switch (generator.getLayoutType()) {
switch (layoutType) {
case 21: case 21:
case 31: case 31:
case 41: case 41:
case 51: case 51:
case 61: case 61:
x = pre.x + "+" + "全景1宽"; this.x = left.x + "+" + "全景1宽";
y = "80";
break; break;
case 12: case 12:
case 13: case 13:
case 14: case 14:
case 15: case 15:
case 16: case 16:
x = "0"; this.x = "0";
y = pre.y + "+" + "全景1高";
break; break;
case 22: case 22:
case 23: case 23:
if (index == 1) { if (index % 2 == 0) {
x = "全景1宽"; this.x = "0";
y = "80"; } else {
} else if (index == 2) { this.x = "全景1宽";
x = "0";
y = "80" + "+" + "全景1高";
} else if (index == 3) {
x = "全景1宽";
y = "80" + "+" + "全景1高";
} else if (index == 4) {
x = "0";
y = coordinates[2].y + "+" + "全景1高";
} else if (index == 5) {
x = "全景1宽";
y = coordinates[3].y + "+" + "全景1高";
} }
break; break;
case 32: case 32:
if (index == 1) { if (index % 3 == 0) {
x = "全景1宽"; this.x = "0";
y = "80"; } else {
} else if (index == 2) { this.x = left.getX() + "+" + "全景1宽";
x = "全景1宽" + "+" + "全景1宽";
y = "80";
} else if (index == 3) {
x = "0";
y = "80" + "+" + "全景1高";
} else if (index == 4) {
x = "全景1宽";
y = "80" + "+" + "全景1高";
} else if (index == 5) {
x = "全景1宽 + 全景1宽";
y = "80" + "+" + "全景1高";
} }
break; break;
default: default:
throw new RuntimeException("no such type"); throw new RuntimeException("no such type");
} }
} }
Coordinate coordinate = new Coordinate(picType, Dict.INSTANCE.picType.get(picType), x, y); return this.x;
coordinates[index] = coordinate;
coordinateMap.put(picType, coordinate);
} }
}
/**
* 计算该图片在合成图上的 Y 坐标
*/
public String getY() {
if (this.y != null) {
return this.y;
}
PicNode upside = this.getUpside();
String paddingTop = paddingTop();
switch (generator.getLayoutType()) {
case 11:
case 21:
case 31:
case 41:
case 51:
case 61:
this.y = paddingTop;
break;
case 12:
case 13:
case 14:
case 15:
case 16:
if (index == 0) {
this.y = paddingTop;
} else {
this.y = upside.y + "+" + "全景1高" + "+" + paddingTop;
}
break;
case 22:
case 23:
if (index < 2) {
this.y = paddingTop;
} else {
this.y = upside.y + "+" + "全景1高" + "+" + paddingTop;
}
break;
case 32:
if (index < 3) {
this.y = paddingTop;
} else {
this.y = upside.y + "+" + "全景1高" + "+" + paddingTop;
}
break;
default:
throw new RuntimeException("no such type");
}
return this.y;
}
/**
* 计算 Y 坐标时需要的填充值
* 一行内每个图片节点的外上边缘字幕的高度加上该节点上层节点的外下边缘字母的高度的最大值作为结果
* 例如
* <ul>
* <li>A B C</li>
* <li>D E F</li>
* </ul>
* D,E,F 的 paddingTop = {@code max(A外下字幕高度 + D外上字幕高度, B外下字幕高度 + E外上字幕高度, C外下字幕高度 + F外上字幕高度)}
*/
private String paddingTop() {
PicNode node = this;
int maxPaddingTop = Integer.MIN_VALUE;
while (node != null) {
PicNode upside = node.getUpside();
int bottomHeight = Optional.ofNullable(upside).map(x -> x.captionNode).map(CaptionNode::getBottomHeight).orElse(0);
int topHeight = node.getCaptionNode().getTopHeight() == null ? 0 : node.getCaptionNode().getTopHeight();
maxPaddingTop = Math.max(maxPaddingTop, bottomHeight + topHeight);
node = node.getLeft();
}
node = this;
while (node != null) {
PicNode upside = node.getUpside();
int bottomHeight = Optional.ofNullable(upside).map(x -> x.captionNode).map(CaptionNode::getBottomHeight).orElse(0);
int topHeight = node.getCaptionNode().getTopHeight() == null ? 0 : node.getCaptionNode().getTopHeight();
maxPaddingTop = Math.max(maxPaddingTop, bottomHeight + topHeight);
node = node.getRight();
}
return String.valueOf(maxPaddingTop);
}
/**
* 获取一个图片节点的左侧图片节点
*/
public PicNode getLeft() {
if (index == 0) {
return null;
}
switch (generator.getLayoutType()) {
case 21:
case 31:
case 41:
case 51:
case 61:
return generator.getPicNodes()[index - 1];
case 22:
case 23:
if (index % 2 == 0) {
return null;
} else {
return generator.picNodes[index - 1];
}
case 32:
if (index % 3 == 0) {
return null;
} else {
return generator.picNodes[index - 1];
}
case 12:
case 13:
case 14:
case 15:
case 16:
default:
return null;
}
}
/**
* 获取一个图片节点的右侧图片节点
*/
public PicNode getRight() {
if (index == generator.picNodes.length - 1) {
return null;
}
switch (generator.getLayoutType()) {
case 21:
case 31:
case 41:
case 51:
case 61:
return generator.getPicNodes()[index + 1];
case 22:
case 23:
if (index % 2 == 1) {
return null;
} else {
return generator.picNodes[index + 1];
}
case 32:
if (index % 3 == 2) {
return null;
} else {
return generator.picNodes[index + 1];
}
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
default:
return null;
}
}
/**
* 获取一个图片节点的上层图片节点
*/
public PicNode getUpside() {
if (index == 0) {
return null;
}
switch (generator.getLayoutType()) {
case 12:
case 13:
case 14:
case 15:
case 16:
return generator.picNodes[index - 1];
case 22:
case 23:
if (index < 2) {
return null;
} else {
return generator.picNodes[index - 2];
}
case 32:
if (index < 3) {
return null;
} else {
return generator.picNodes[index - 3];
}
case 11:
case 21:
case 31:
case 41:
case 51:
case 61:
default:
return null;
}
}
}
/**
* 字幕属性和图片属性的生成器
* 用来生成图片的坐标,字幕的高度,字幕的内容
*/
public @Getter public @Getter
@Setter @Setter
@AllArgsConstructor @Accessors(chain = true)
static class Coordinate { static class PicConfigGenerator {
private Integer type;
private String name; private final PicNode[] picNodes;
private String x; /** 图片排列方式类型 */
private String y; private final int layoutType;
/**
* @param picConfigVo 图片属性
* @param captionVos 图片属性对应的所有字幕
*/
public PicConfigGenerator(PicConfigVo picConfigVo, List<CaptionVo> captionVos) {
List<Context> contexts = picConfigVo.getContexts();
layoutType = picConfigVo.getType();
picNodes = new PicNode[contexts.size()];
for (int i = 0; i < picNodes.length; i++) {
Context context = contexts.get(i);
picNodes[i] = new PicNode(this, context.getType(), i);
}
for (CaptionVo captionVo : captionVos) {
for (PicNode picNode : picNodes) {
if (picNode.getPicType() == captionVo.getPicType()) {
picNode.getCaptionNode().add(captionVo);
}
}
}
}
} }
/**
* 字幕节点
* 每个图片节点对应一个字幕节点
*/
public @Getter
@Setter
static final class CaptionNode {
/** 图片外上边缘字幕的配置 */
private CaptionVo top;
/** 图片内上边缘字幕的配置 */
private CaptionVo second;
/** 图片内下边缘字幕的配置 */
private CaptionVo third;
/** 图片外下边缘字幕的配置 */
private CaptionVo bottom;
/** 图片外上边缘字幕的内容 */
private String topContent;
/** 图片内上边缘字幕的内容 */
private String secondContent;
/** 图片内下边缘字幕的内容 */
private String thirdContent;
/** 图片外下边缘字幕的内容 */
private String bottomContent;
/** 图片外上边缘字幕的高度 */
private Integer topHeight;
/** 图片内上边缘字幕的高度 */
private Integer secondHeight;
/** 图片内下边缘字幕的高度 */
private Integer thirdHeight;
/** 图片外下边缘字幕的高度 */
private Integer bottomHeight;
/**
* 根据坐标位置类型复制不同的字段,如果是同一类就会覆盖
* 目前没写坐标类型为 自定义 的逻辑,相信自定义坐标也不会用上,如果有的话实现也很简单
*/
public void add(CaptionVo vo) {
Integer positionType = vo.getPositionType();
Integer fontSize = vo.getFontSize();
String dateFormat = (vo.getMillisecond() != null && vo.getMillisecond()) ? vo.getDateFormat() + ".xxx" : vo.getDateFormat();
Pair<String, Integer> pair = combineCaptionContent(vo.getPicType(), vo.getContexts(), dateFormat);
Integer wrapCount = pair.getValue();
int height = wrapCount == 0 ? fontSize + 10 : (wrapCount + 1) * (fontSize + 10);
switch (positionType) {
case 0:
this.top = vo;
this.topContent = pair.getKey();
this.topHeight = height;
break;
case 1:
this.bottom = vo;
this.bottomContent = pair.getKey();
this.bottomHeight = height;
break;
case 2:
this.second = vo;
this.secondContent = pair.getKey();
this.secondHeight = height;
break;
case 3:
this.third = vo;
this.thirdContent = pair.getKey();
this.secondHeight = height;
break;
default:
break;
}
}
/**
* 组合字幕内容
*
* @param picType 图片类型
* @param contexts 内容列表
* @param dateFormat 时间格式
*
* @return key: 字幕内容, value: 换行了多少次,用来计算字幕所占的高度
*/
private Pair<String, Integer> combineCaptionContent(Integer picType, List<Context> contexts, String dateFormat) {
if (CollectionUtil.isEmpty(contexts)) {
return Pair.of(null, null);
}
String picTypeName = Dict.INSTANCE.picType.get(picType);
StringBuilder sb = new StringBuilder();
int wrapCount = 0;
for (Context context : contexts) {
Integer type = context.getType();
sb.append(Dict.INSTANCE.captionType.get(type)).append(":+");
switch (type) {
case 1:
if (picTypeName.contains("特写")) {
picTypeName = "特写图";
}
sb.append("(").append(picTypeName).append("时间:").append(dateFormat).append(")");
break;
case 9:
sb.append("(用户车辆类型1)");
break;
case 10:
sb.append("(用户车身颜色1)");
break;
case 11:
sb.append("(车辆子品牌)");
break;
case 15:
sb.append("(合成图1防伪码)");
break;
case 16:
sb.append(context.getContent());
break;
case 17:
sb.append("(违法类型代码)");
break;
default:
sb.append("(").append(Dict.INSTANCE.captionType.get(type)).append(")");
}
if (context.getWrap()) {
wrapCount++;
sb.append("+(换行分隔符)");
}
sb.append("+");
}
sb.setLength(sb.length() - 1);
return Pair.of(sb.toString(), wrapCount);
}
}
} }
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!