|
1
|
|
package pro.verron.officestamper.preset; |
|
2
|
|
|
|
3
|
|
import org.docx4j.wml.R; |
|
4
|
|
import org.jspecify.annotations.Nullable; |
|
5
|
|
import pro.verron.officestamper.api.DocxPart; |
|
6
|
|
import pro.verron.officestamper.api.OfficeStamperException; |
|
7
|
|
import pro.verron.officestamper.utils.wml.WmlFactory; |
|
8
|
|
|
|
9
|
|
import java.io.ByteArrayInputStream; |
|
10
|
|
import java.io.IOException; |
|
11
|
|
import java.io.InputStream; |
|
12
|
|
|
|
13
|
|
import static pro.verron.officestamper.utils.openpackaging.OpenpackagingFactory.newImgPart; |
|
14
|
|
import static pro.verron.officestamper.utils.openpackaging.OpenpackagingUtils.findImgPart; |
|
15
|
|
|
|
16
|
|
/// This class describes an image, which will be inserted into a document. |
|
17
|
|
/// |
|
18
|
|
/// @author Joseph Verron |
|
19
|
|
/// @author Romster |
|
20
|
|
/// @version ${version} |
|
21
|
|
/// @since 1.0.0 |
|
22
|
|
public final class Image { |
|
23
|
|
private final InputStream source; |
|
24
|
|
private final @Nullable Integer maxWidth; |
|
25
|
|
private final String filenameHint; |
|
26
|
|
private final String altText; |
|
27
|
|
private byte @Nullable [] bytes = null; |
|
28
|
|
|
|
29
|
|
/// Constructor for Image. |
|
30
|
|
/// |
|
31
|
|
/// @param source - content of the image as InputStream |
|
32
|
|
/// |
|
33
|
|
/// @throws IOException if any. |
|
34
|
|
public Image(InputStream source) |
|
35
|
|
throws IOException { |
|
36
|
|
this(source, null); |
|
37
|
|
} |
|
38
|
|
|
|
39
|
|
/// Constructor for Image. |
|
40
|
|
/// |
|
41
|
|
/// @param source content of the image as InputStream |
|
42
|
|
/// @param maxWidth max width of the image in twip |
|
43
|
|
public Image(InputStream source, @Nullable Integer maxWidth) { |
|
44
|
|
this(source, maxWidth, "dummyFileName", "dummyAltText"); |
|
45
|
|
} |
|
46
|
|
|
|
47
|
|
/// Constructor for Image. |
|
48
|
|
/// |
|
49
|
|
/// @param source content of the image as InputStream |
|
50
|
|
/// @param maxWidth max width of the image in twip |
|
51
|
|
/// @param filenameHint filename hint for the image. |
|
52
|
|
/// @param altText alternative text for the image. |
|
53
|
|
public Image(InputStream source, @Nullable Integer maxWidth, String filenameHint, String altText) { |
|
54
|
|
this.source = source; |
|
55
|
|
this.maxWidth = maxWidth; |
|
56
|
|
this.filenameHint = filenameHint; |
|
57
|
|
this.altText = altText; |
|
58
|
|
} |
|
59
|
|
|
|
60
|
|
/// Constructor for Image. |
|
61
|
|
/// |
|
62
|
|
/// @param imageBytes - content of the image as an array of the bytes |
|
63
|
|
public Image(byte[] imageBytes) { |
|
64
|
|
this(new ByteArrayInputStream(imageBytes), null); |
|
65
|
|
} |
|
66
|
|
|
|
67
|
|
/// Constructor for Image. |
|
68
|
|
/// |
|
69
|
|
/// @param imageBytes - content of the image as an array of the bytes |
|
70
|
|
/// @param maxWidth - max width of the image in twip |
|
71
|
|
public Image(byte[] imageBytes, @Nullable Integer maxWidth) { |
|
72
|
|
this(imageBytes, maxWidth, "dummyFileName", "dummyAltText"); |
|
73
|
|
} |
|
74
|
|
|
|
75
|
|
/// Constructor for Image. |
|
76
|
|
/// |
|
77
|
|
/// @param imageBytes content of the image as an array of the bytes |
|
78
|
|
/// @param maxWidth max width of the image in twip |
|
79
|
|
/// @param filenameHint filename hint for the image. |
|
80
|
|
/// @param altText alternative text for the image. |
|
81
|
|
public Image(byte[] imageBytes, @Nullable Integer maxWidth, String filenameHint, String altText) { |
|
82
|
|
var inputStream = new ByteArrayInputStream(imageBytes); |
|
83
|
|
this(inputStream, maxWidth, filenameHint, altText); |
|
84
|
|
} |
|
85
|
|
|
|
86
|
|
/// Creates a new run with the provided image and associated metadata. |
|
87
|
|
/// |
|
88
|
|
/// TODO: adding the same image twice will put the image twice into the docx-zip file. |
|
89
|
|
/// We should make the second addition of the same image a reference instead. |
|
90
|
|
/// |
|
91
|
|
/// @param part The document part where the image will be inserted. |
|
92
|
|
/// |
|
93
|
|
/// @return The created run containing the image. |
|
94
|
|
/// |
|
95
|
|
/// @throws OfficeStamperException If there is an error creating the image part |
|
96
|
|
public R newRun(DocxPart part) { |
|
97
|
|
var mlPackage = part.document(); |
|
98
|
|
try { |
|
99
|
|
var parts = part.part(); |
|
100
|
|
var document = part.document(); |
|
101
|
|
var documentModel = document.getDocumentModel(); |
|
102
|
|
var sections = documentModel.getSections(); |
|
103
|
|
var lastSection = sections.getLast(); |
|
104
|
|
var pageDimension = lastSection.getPageDimensions(); |
|
105
|
1
1. lambda$newRun$0 : replaced return value with null for pro/verron/officestamper/preset/Image::lambda$newRun$0 → KILLED
|
var imgPart = findImgPart(mlPackage, parts, bytes()).orElseGet(() -> newImgPart(mlPackage, parts, bytes())); |
|
106
|
|
var relationship = imgPart.relationship(); |
|
107
|
|
var imgFormat = imgPart.format(); |
|
108
|
|
var dimension = imgFormat.dimension(); |
|
109
|
|
var format = imgFormat.name(); |
|
110
|
1
1. newRun : negated conditional → KILLED
|
var scale = WmlFactory.computeScale(pageDimension, maxWidth == null ? -1 : maxWidth, dimension); |
|
111
|
1
1. newRun : negated conditional → SURVIVED
|
var inline = format.equals("svg") |
|
112
|
|
? WmlFactory.newSVGInline(relationship, filenameHint, altText, scale) |
|
113
|
|
: WmlFactory.newImgInline(relationship, filenameHint, altText, scale); |
|
114
|
|
var drawing = WmlFactory.newDrawing(inline); |
|
115
|
1
1. newRun : replaced return value with null for pro/verron/officestamper/preset/Image::newRun → KILLED
|
return WmlFactory.newRun(drawing); |
|
116
|
|
} catch (Exception e) { |
|
117
|
|
throw new OfficeStamperException("Failed to create an ImagePart", e); |
|
118
|
|
} |
|
119
|
|
} |
|
120
|
|
|
|
121
|
|
private synchronized byte[] bytes() { |
|
122
|
1
1. bytes : negated conditional → KILLED
|
if (bytes == null) try (InputStream source = this.source) { |
|
123
|
|
bytes = source.readAllBytes(); |
|
124
|
|
} catch (IOException e) { |
|
125
|
|
throw new OfficeStamperException("Failed to cache the image bytes", e); |
|
126
|
|
} |
|
127
|
1
1. bytes : replaced return value with null for pro/verron/officestamper/preset/Image::bytes → KILLED
|
return bytes; |
|
128
|
|
} |
|
129
|
|
|
|
130
|
|
} |
| | Mutations |
| 105 |
|
1.1 Location : lambda$newRun$0 Killed by : pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2] replaced return value with null for pro/verron/officestamper/preset/Image::lambda$newRun$0 → KILLED
|
| 110 |
|
1.1 Location : newRun Killed by : pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2] negated conditional → KILLED
|
| 111 |
|
1.1 Location : newRun Killed by : none negated conditional → SURVIVED
Covering tests
Covered by tests:
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:jpgImageReplacementInGlobalParagraphsTest(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:jpgImageReplacementInGlobalParagraphsTest(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:jpgImageReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:bmpReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:tiffImageReplacementInGlobalParagraphsTest(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:wmfReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:wmfReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:jpgImageReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:svgReplacementInGlobalParagraphsTest(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:svgReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:svgReplacementInGlobalParagraphsTest(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:bmpReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:emfReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:emfReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:tiffImageReplacementInGlobalParagraphsTest(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.HeaderAndFooterTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.HeaderAndFooterTest]/[test-template:placeholders(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:svgReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ProcessorRepeatDocPartTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ProcessorRepeatDocPartTest]/[test-template:shouldImportImageDataInTheMainDocument(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2]
- pro.verron.officestamper.test.ProcessorRepeatDocPartTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ProcessorRepeatDocPartTest]/[test-template:shouldImportImageDataInTheMainDocument(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ProcessorRepeatDocPartTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ProcessorRepeatDocPartTest]/[test-template:shouldImportImageDataWithThisInTheMainDocument()]/[test-template-invocation:#1]
- pro.verron.officestamper.test.ProcessorRepeatDocPartTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ProcessorRepeatDocPartTest]/[test-template:shouldImportImageDataWithThisInTheMainDocument()]/[test-template-invocation:#2]
- pro.verron.officestamper.test.HeaderAndFooterTest.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.HeaderAndFooterTest]/[test-template:placeholders(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#1]
|
| 115 |
|
1.1 Location : newRun Killed by : pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2] replaced return value with null for pro/verron/officestamper/preset/Image::newRun → KILLED
|
| 122 |
|
1.1 Location : bytes Killed by : pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2] negated conditional → KILLED
|
| 127 |
|
1.1 Location : bytes Killed by : pro.verron.officestamper.test.ImageTests.[engine:junit-jupiter]/[class:pro.verron.officestamper.test.ImageTests]/[test-template:gifReplacementInGlobalParagraphsTestWithMaxWidth(pro.verron.officestamper.test.utils.ContextFactory)]/[test-template-invocation:#2] replaced return value with null for pro/verron/officestamper/preset/Image::bytes → KILLED
|