diff options
7 files changed, 55 insertions, 29 deletions
diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java index 6bc470d775..609b3efcbb 100644 --- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java +++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java @@ -28,9 +28,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; +import java.util.Arrays; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.apache.poi.common.usermodel.GenericRecord; import org.apache.poi.poifs.filesystem.FileMagic; @@ -77,7 +80,8 @@ public final class PPTX2PNG { " -emfHeaderBounds force the usage of the emf header bounds to calculate the bounding box\n" + " -fontdir <dir> (PDF only) font directories separated by \";\" - use $HOME for current users home dir\n" + " defaults to the usual plattform directories\n" + - " -fontTtf <regex> (PDF only) regex to match the .ttf filenames"; + " -fontTtf <regex> (PDF only) regex to match the .ttf filenames\n" + + " -fontMap <map> \";\"-separated list of font mappings <typeface from>:<typeface to>"; System.out.println(msg); // no System.exit here, as we also run in junit tests! @@ -109,6 +113,7 @@ public final class PPTX2PNG { private boolean emfHeaderBounds = false; private String fontDir = null; private String fontTtf = null; + private String fontMap = null; private PPTX2PNG() { } @@ -213,6 +218,14 @@ public final class PPTX2PNG { fontTtf = null; } break; + case "-fontmap": + if (opt != null) { + fontMap = opt; + i++; + } else { + fontMap = null; + } + break; default: file = new File(args[i]); break; @@ -303,6 +316,12 @@ public final class PPTX2PNG { graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); graphics.setRenderingHint(Drawable.DEFAULT_CHARSET, getDefaultCharset()); graphics.setRenderingHint(Drawable.EMF_FORCE_HEADER_BOUNDS, emfHeaderBounds); + if (fontMap != null) { + Map<String,String> fmap = Arrays.stream(fontMap.split(";")) + .map(s -> s.split(":")) + .collect(Collectors.toMap(s -> s[0], s -> s[1])); + graphics.setRenderingHint(Drawable.FONT_MAP, fmap); + } graphics.scale(scale / lenSide, scale / lenSide); diff --git a/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusDraw.java b/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusDraw.java index 9f45de5e8a..b52053bec4 100644 --- a/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusDraw.java +++ b/src/scratchpad/src/org/apache/poi/hemf/record/emfplus/HemfPlusDraw.java @@ -450,13 +450,13 @@ public final class HemfPlusDraw { AffineTransform txSaved = ctx.getTransform(); AffineTransform tx = (AffineTransform)txSaved.clone(); - HwmfTernaryRasterOp oldOp = prop.getRasterOp(); + HwmfTernaryRasterOp oldOp = prop.getRasterOp3(); HwmfBkMode oldBk = prop.getBkMode(); try { tx.concatenate(trans); ctx.setTransform(tx); - prop.setRasterOp(HwmfTernaryRasterOp.SRCCOPY); + prop.setRasterOp3(HwmfTernaryRasterOp.SRCCOPY); prop.setBkMode(HwmfBkMode.TRANSPARENT); // transformation from srcRect to destRect was already applied, @@ -464,7 +464,7 @@ public final class HemfPlusDraw { ctx.drawImage(ir, srcRect, srcRect); } finally { prop.setBkMode(oldBk); - prop.setRasterOp(oldOp); + prop.setRasterOp3(oldOp); ctx.setTransform(txSaved); } } @@ -539,7 +539,7 @@ public final class HemfPlusDraw { ctx.applyPlusObjectTableEntry(getObjectId()); HemfDrawProperties prop = ctx.getProperties(); - prop.setRasterOp(HwmfTernaryRasterOp.SRCCOPY); + prop.setRasterOp3(HwmfTernaryRasterOp.SRCCOPY); prop.setBkMode(HwmfBkMode.TRANSPARENT); ctx.drawImage(prop.getEmfPlusImage(), srcRect, rectData); diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java index dd57be2c88..f37bf79784 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfDrawProperties.java @@ -68,7 +68,7 @@ public class HwmfDrawProperties { private HwmfTextVerticalAlignment textVAlignLatin; private HwmfTextAlignment textAlignAsian; private HwmfTextVerticalAlignment textVAlignAsian; - private HwmfTernaryRasterOp rasterOp; + private HwmfTernaryRasterOp rasterOp3; protected Shape clip; protected final AffineTransform transform = new AffineTransform(); @@ -92,7 +92,7 @@ public class HwmfDrawProperties { textVAlignLatin = HwmfTextVerticalAlignment.TOP; textAlignAsian = HwmfTextAlignment.RIGHT; textVAlignAsian = HwmfTextVerticalAlignment.TOP; - rasterOp = HwmfTernaryRasterOp.PATCOPY; + rasterOp3 = HwmfTernaryRasterOp.PATCOPY; clip = null; font = new HwmfFont(); font.initDefaults(); @@ -128,7 +128,7 @@ public class HwmfDrawProperties { this.textVAlignLatin = other.textVAlignLatin; this.textAlignAsian = other.textAlignAsian; this.textVAlignAsian = other.textVAlignAsian; - this.rasterOp = other.rasterOp; + this.rasterOp3 = other.rasterOp3; this.transform.setTransform(other.transform); this.clip = other.clip; } @@ -388,12 +388,12 @@ public class HwmfDrawProperties { return getPolyfillMode().awtFlag; } - public HwmfTernaryRasterOp getRasterOp() { - return rasterOp; + public HwmfTernaryRasterOp getRasterOp3() { + return rasterOp3; } - public void setRasterOp(HwmfTernaryRasterOp rasterOp) { - this.rasterOp = rasterOp; + public void setRasterOp3(HwmfTernaryRasterOp rasterOp3) { + this.rasterOp3 = rasterOp3; } public AffineTransform getTransform() { diff --git a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java index dbca6ef9cf..8e888313f9 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/draw/HwmfGraphics.java @@ -48,6 +48,7 @@ import java.util.BitSet; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; @@ -461,7 +462,8 @@ public class HwmfGraphics implements HwmfCharsetAware { return; } - String textString = trimText(font, isUnicode, text, length); + final Charset charset = getCharset(font, isUnicode); + String textString = trimText(charset, text, length); if (textString.isEmpty()) { return; } @@ -481,7 +483,12 @@ public class HwmfGraphics implements HwmfCharsetAware { final double angle = Math.toRadians(-font.getEscapement()/10.); - final Point2D dst = getRotatedOffset(angle, frc, as); + // TODO: find out when to use asian align + boolean useAsianAlign = (opts == null) && + textString.codePoints().anyMatch(Character::isIdeographic) && + charset.displayName(Locale.ROOT). startsWith("GB"); + + final Point2D dst = getRotatedOffset(angle, frc, as, useAsianAlign); final Shape clipShape = graphicsCtx.getClip(); try { @@ -640,8 +647,7 @@ public class HwmfGraphics implements HwmfCharsetAware { charsetProvider = provider; } - private String trimText(HwmfFont font, boolean isUnicode, byte[] text, int length) { - final Charset charset = getCharset(font, isUnicode); + private String trimText(Charset charset, byte[] text, int length) { int trimLen; for (trimLen=0; trimLen<text.length; trimLen+=2) { @@ -660,7 +666,8 @@ public class HwmfGraphics implements HwmfCharsetAware { return textString.substring(0, Math.min(textString.length(), length)); } - private void updateHorizontalAlign(AffineTransform tx, TextLayout layout) { + private void updateHorizontalAlign(AffineTransform tx, TextLayout layout, boolean useAsianAlign) { + // TODO: using prop.getTextAlignAsian doesn't look good ... switch (prop.getTextAlignLatin()) { default: case LEFT: @@ -674,9 +681,9 @@ public class HwmfGraphics implements HwmfCharsetAware { } } - private void updateVerticalAlign(AffineTransform tx, TextLayout layout) { + private void updateVerticalAlign(AffineTransform tx, TextLayout layout, boolean useAsianAlign) { // TODO: check min/max orientation - switch (prop.getTextVAlignLatin()) { + switch (useAsianAlign ? prop.getTextVAlignAsian() : prop.getTextVAlignLatin()) { case TOP: tx.translate(0, layout.getAscent()); break; @@ -710,11 +717,11 @@ public class HwmfGraphics implements HwmfCharsetAware { graphicsCtx.setTransform(at); } - private Point2D getRotatedOffset(double angle, FontRenderContext frc, AttributedString as) { + private Point2D getRotatedOffset(double angle, FontRenderContext frc, AttributedString as, boolean useAsianAlign) { final TextLayout layout = new TextLayout(as.getIterator(), frc); final AffineTransform tx = new AffineTransform(); - updateHorizontalAlign(tx, layout); - updateVerticalAlign(tx, layout); + updateHorizontalAlign(tx, layout, useAsianAlign); + updateVerticalAlign(tx, layout, useAsianAlign); tx.rotate(angle); Point2D src = new Point2D.Double(); @@ -736,7 +743,7 @@ public class HwmfGraphics implements HwmfCharsetAware { // are not supported, as we would need to extract the destination image area from the underlying buffered image // and therefore would make it mandatory that the graphics context must be from a buffered image // furthermore I doubt the purpose of bitwise image operations on non-black/white images - switch (prop.getRasterOp()) { + switch (prop.getRasterOp3()) { case D: // keep destination, i.e. do nothing break; @@ -785,7 +792,7 @@ public class HwmfGraphics implements HwmfCharsetAware { // of the referenced image and can be also negative Composite old = graphicsCtx.getComposite(); int newComp; - switch (prop.getRasterOp()) { + switch (prop.getRasterOp3()) { default: case SRCCOPY: newComp = AlphaComposite.SRC_OVER; diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java index 19dee4e871..12eb580f93 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfDraw.java @@ -476,7 +476,7 @@ public final class HwmfDraw { @Override public HwmfRecordType getWmfRecordType() { - return HwmfRecordType.frameRegion; + return HwmfRecordType.rectangle; } @Override diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java index a92c3da981..90fe33881e 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfFill.java @@ -611,7 +611,7 @@ public class HwmfFill { @Override public void draw(HwmfGraphics ctx) { HwmfDrawProperties prop = ctx.getProperties(); - prop.setRasterOp(rasterOperation); + prop.setRasterOp3(rasterOperation); if (bitmap.isValid()) { BufferedImage bi = bitmap.getImage(prop.getPenColor().getColor(), prop.getBackgroundColor().getColor(), prop.getBkMode() == HwmfBkMode.TRANSPARENT); @@ -912,7 +912,7 @@ public class HwmfFill { @Override public void draw(HwmfGraphics ctx) { HwmfDrawProperties prop = ctx.getProperties(); - prop.setRasterOp(rasterOperation); + prop.setRasterOp3(rasterOperation); // TODO: implement second operation based on playback device context if (target != null) { HwmfBkMode oldMode = prop.getBkMode(); diff --git a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java index 07c7636a29..910c9ac88b 100644 --- a/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java +++ b/src/scratchpad/src/org/apache/poi/hwmf/record/HwmfText.java @@ -146,7 +146,7 @@ public class HwmfText { @Override public HwmfRecordType getWmfRecordType() { - return HwmfRecordType.setBkColor; + return HwmfRecordType.setTextJustification; } @Override @@ -236,7 +236,7 @@ public class HwmfText { @Override public Map<String, Supplier<?>> getGenericProperties() { return GenericRecordUtil.getGenericProperties( - "text", () -> getText(StandardCharsets.US_ASCII), + "text", () -> getText(charsetProvider.get()), "reference", () -> reference ); } |