mirror of https://github.com/apache/poi.git
#63745 - Add traversing and debugging interface
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1866808 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f31281f18f
commit
1d4b05ff60
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.common.usermodel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface GenericRecord {
|
||||
default Enum getGenericRecordType() { return null; }
|
||||
|
||||
Map<String, Supplier<?>> getGenericProperties();
|
||||
|
||||
default List<? extends GenericRecord> getGenericChildren() { return null; }
|
||||
}
|
|
@ -17,10 +17,18 @@
|
|||
|
||||
package org.apache.poi.common.usermodel.fonts;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
import static org.apache.poi.util.GenericRecordUtil.safeEnum;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
|
@ -34,8 +42,76 @@ import org.apache.poi.util.LittleEndianInputStream;
|
|||
*
|
||||
* @see <a href="http://www.w3.org/Submission/EOT">Embedded OpenType (EOT) File Format</a>
|
||||
*/
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused", "Duplicates"})
|
||||
public class FontHeader implements FontInfo {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused", "Duplicates", "WeakerAccess"})
|
||||
public class FontHeader implements FontInfo, GenericRecord {
|
||||
|
||||
public enum PanoseFamily {
|
||||
ANY, NO_FIT, TEXT_DISPLAY, SCRIPT, DECORATIVE, PICTORIAL
|
||||
}
|
||||
|
||||
public enum PanoseSerif {
|
||||
ANY, NO_FIT, COVE, OBTUSE_COVE, SQUARE_COVE, OBTUSE_SQUARE_COVE, SQUARE, THIN, BONE,
|
||||
EXAGGERATED, TRIANGLE, NORMAL_SANS, OBTUSE_SANS, PERP_SANS, FLARED, ROUNDED
|
||||
}
|
||||
|
||||
public enum PanoseWeight {
|
||||
ANY, NO_FIT, VERY_LIGHT, LIGHT, THIN, BOOK, MEDIUM, DEMI, BOLD, HEAVY, BLACK, NORD
|
||||
}
|
||||
|
||||
public enum PanoseProportion {
|
||||
ANY, NO_FIT, OLD_STYLE, MODERN, EVEN_WIDTH, EXPANDED, CONDENSED, VERY_EXPANDED, VERY_CONDENSED, MONOSPACED
|
||||
}
|
||||
|
||||
public enum PanoseContrast {
|
||||
ANY, NO_FIT, NONE, VERY_LOW, LOW, MEDIUM_LOW, MEDIUM, MEDIUM_HIGH, HIGH, VERY_HIGH
|
||||
}
|
||||
|
||||
public enum PanoseStroke {
|
||||
ANY, NO_FIT, GRADUAL_DIAG, GRADUAL_TRAN, GRADUAL_VERT, GRADUAL_HORZ, RAPID_VERT, RAPID_HORZ, INSTANT_VERT
|
||||
}
|
||||
|
||||
public enum PanoseArmStyle {
|
||||
ANY, NO_FIT, STRAIGHT_ARMS_HORZ, STRAIGHT_ARMS_WEDGE, STRAIGHT_ARMS_VERT, STRAIGHT_ARMS_SINGLE_SERIF,
|
||||
STRAIGHT_ARMS_DOUBLE_SERIF, BENT_ARMS_HORZ, BENT_ARMS_WEDGE, BENT_ARMS_VERT, BENT_ARMS_SINGLE_SERIF,
|
||||
BENT_ARMS_DOUBLE_SERIF,
|
||||
}
|
||||
|
||||
public enum PanoseLetterForm {
|
||||
ANY, NO_FIT, NORMAL_CONTACT, NORMAL_WEIGHTED, NORMAL_BOXED, NORMAL_FLATTENED, NORMAL_ROUNDED,
|
||||
NORMAL_OFF_CENTER, NORMAL_SQUARE, OBLIQUE_CONTACT, OBLIQUE_WEIGHTED, OBLIQUE_BOXED, OBLIQUE_FLATTENED,
|
||||
OBLIQUE_ROUNDED, OBLIQUE_OFF_CENTER, OBLIQUE_SQUARE
|
||||
}
|
||||
|
||||
public enum PanoseMidLine {
|
||||
ANY, NO_FIT, STANDARD_TRIMMED, STANDARD_POINTED, STANDARD_SERIFED, HIGH_TRIMMED, HIGH_POINTED, HIGH_SERIFED,
|
||||
CONSTANT_TRIMMED, CONSTANT_POINTED, CONSTANT_SERIFED, LOW_TRIMMED, LOW_POINTED, LOW_SERIFED
|
||||
}
|
||||
|
||||
public enum PanoseXHeight {
|
||||
ANY, NO_FIT, CONSTANT_SMALL, CONSTANT_STD, CONSTANT_LARGE, DUCKING_SMALL, DUCKING_STD, DUCKING_LARGE
|
||||
}
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
0x00000001, 0x00000004, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x10000000
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"SUBSET", "TTCOMPRESSED", "FAILIFVARIATIONSIMULATED", "EMBEDEUDC", "VALIDATIONTESTS", "WEBOBJECT", "XORENCRYPTDATA"
|
||||
};
|
||||
|
||||
private static final int[] FSTYPE_MASKS = {
|
||||
0x0000, 0x0002, 0x0004, 0x0008, 0x0100, 0x0200
|
||||
};
|
||||
|
||||
private static final String[] FSTYPE_NAMES = {
|
||||
"INSTALLABLE_EMBEDDING",
|
||||
"RESTRICTED_LICENSE_EMBEDDING",
|
||||
"PREVIEW_PRINT_EMBEDDING",
|
||||
"EDITABLE_EMBEDDING",
|
||||
"NO_SUBSETTING",
|
||||
"BITMAP_EMBEDDING_ONLY"
|
||||
};
|
||||
|
||||
/**
|
||||
* Fonts with a font weight of 400 are regarded as regular weighted.
|
||||
* Higher font weights (up to 1000) are bold - lower weights are thin.
|
||||
|
@ -142,53 +218,54 @@ public class FontHeader implements FontInfo {
|
|||
}
|
||||
|
||||
public FontPitch getPitch() {
|
||||
byte familyKind = panose[0];
|
||||
switch (familyKind) {
|
||||
switch (getPanoseFamily()) {
|
||||
default:
|
||||
// Any
|
||||
case 0:
|
||||
// No Fit
|
||||
case 1:
|
||||
case ANY:
|
||||
case NO_FIT:
|
||||
return FontPitch.VARIABLE;
|
||||
|
||||
// Latin Text
|
||||
case 2:
|
||||
// Latin Decorative
|
||||
case 4:
|
||||
byte proportion = panose[3];
|
||||
return proportion == 9 ? FontPitch.FIXED : FontPitch.VARIABLE;
|
||||
case TEXT_DISPLAY:
|
||||
// Latin Decorative
|
||||
case DECORATIVE:
|
||||
return (getPanoseProportion() == PanoseProportion.MONOSPACED) ? FontPitch.FIXED : FontPitch.VARIABLE;
|
||||
|
||||
// Latin Hand Written
|
||||
case 3:
|
||||
// Latin Symbol
|
||||
case 5:
|
||||
byte spacing = panose[3];
|
||||
return spacing == 3 ? FontPitch.FIXED : FontPitch.VARIABLE;
|
||||
case SCRIPT:
|
||||
// Latin Symbol
|
||||
case PICTORIAL:
|
||||
return (getPanoseProportion() == PanoseProportion.MODERN) ? FontPitch.FIXED : FontPitch.VARIABLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public FontFamily getFamily() {
|
||||
switch (panose[0]) {
|
||||
// Any
|
||||
case 0:
|
||||
// No Fit
|
||||
case 1:
|
||||
switch (getPanoseFamily()) {
|
||||
case ANY:
|
||||
case NO_FIT:
|
||||
return FontFamily.FF_DONTCARE;
|
||||
// Latin Text
|
||||
case 2:
|
||||
byte serifStyle = panose[1];
|
||||
return (10 <= serifStyle && serifStyle <= 15)
|
||||
? FontFamily.FF_SWISS : FontFamily.FF_ROMAN;
|
||||
case TEXT_DISPLAY:
|
||||
switch (getPanoseSerif()) {
|
||||
case TRIANGLE:
|
||||
case NORMAL_SANS:
|
||||
case OBTUSE_SANS:
|
||||
case PERP_SANS:
|
||||
case FLARED:
|
||||
case ROUNDED:
|
||||
return FontFamily.FF_SWISS;
|
||||
default:
|
||||
return FontFamily.FF_ROMAN;
|
||||
}
|
||||
// Latin Hand Written
|
||||
case 3:
|
||||
case SCRIPT:
|
||||
return FontFamily.FF_SCRIPT;
|
||||
// Latin Decorative
|
||||
default:
|
||||
case 4:
|
||||
case DECORATIVE:
|
||||
return FontFamily.FF_DECORATIVE;
|
||||
// Latin Symbol
|
||||
case 5:
|
||||
case PICTORIAL:
|
||||
return FontFamily.FF_MODERN;
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +298,79 @@ public class FontHeader implements FontInfo {
|
|||
public int getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("eotSize", () -> eotSize);
|
||||
m.put("fontDataSize", () -> fontDataSize);
|
||||
m.put("version", () -> version);
|
||||
m.put("flags", getBitsAsString(this::getFlags, FLAGS_MASKS, FLAGS_NAMES));
|
||||
m.put("panose.familyType", this::getPanoseFamily);
|
||||
m.put("panose.serifType", this::getPanoseSerif);
|
||||
m.put("panose.weight", this::getPanoseWeight);
|
||||
m.put("panose.proportion", this::getPanoseProportion);
|
||||
m.put("panose.contrast", this::getPanoseContrast);
|
||||
m.put("panose.stroke", this::getPanoseStroke);
|
||||
m.put("panose.armStyle", this::getPanoseArmStyle);
|
||||
m.put("panose.letterForm", this::getPanoseLetterForm);
|
||||
m.put("panose.midLine", this::getPanoseMidLine);
|
||||
m.put("panose.xHeight", this::getPanoseXHeight);
|
||||
m.put("charset", this::getCharset);
|
||||
m.put("italic", this::isItalic);
|
||||
m.put("weight", this::getWeight);
|
||||
m.put("fsType", getBitsAsString(() -> fsType, FSTYPE_MASKS, FSTYPE_NAMES));
|
||||
m.put("unicodeRange1", () -> unicodeRange1);
|
||||
m.put("unicodeRange2", () -> unicodeRange2);
|
||||
m.put("unicodeRange3", () -> unicodeRange3);
|
||||
m.put("unicodeRange4", () -> unicodeRange4);
|
||||
m.put("codePageRange1", () -> codePageRange1);
|
||||
m.put("codePageRange2", () -> codePageRange2);
|
||||
m.put("checkSumAdjustment", () -> checkSumAdjustment);
|
||||
m.put("familyName", this::getFamilyName);
|
||||
m.put("styleName", this::getStyleName);
|
||||
m.put("versionName", this::getVersionName);
|
||||
m.put("fullName", this::getFullName);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
public PanoseFamily getPanoseFamily() {
|
||||
return safeEnum(PanoseFamily.values(), () -> panose[0]).get();
|
||||
}
|
||||
|
||||
public PanoseSerif getPanoseSerif() {
|
||||
return safeEnum(PanoseSerif.values(), () -> panose[1]).get();
|
||||
}
|
||||
|
||||
public PanoseWeight getPanoseWeight() {
|
||||
return safeEnum(PanoseWeight.values(), () -> panose[2]).get();
|
||||
}
|
||||
|
||||
public PanoseProportion getPanoseProportion() {
|
||||
return safeEnum(PanoseProportion.values(), () -> panose[3]).get();
|
||||
}
|
||||
|
||||
public PanoseContrast getPanoseContrast() {
|
||||
return safeEnum(PanoseContrast.values(), () -> panose[4]).get();
|
||||
}
|
||||
|
||||
public PanoseStroke getPanoseStroke() {
|
||||
return safeEnum(PanoseStroke.values(), () -> panose[5]).get();
|
||||
}
|
||||
|
||||
public PanoseArmStyle getPanoseArmStyle() {
|
||||
return safeEnum(PanoseArmStyle.values(), () -> panose[6]).get();
|
||||
}
|
||||
|
||||
public PanoseLetterForm getPanoseLetterForm() {
|
||||
return safeEnum(PanoseLetterForm.values(), () -> panose[7]).get();
|
||||
}
|
||||
|
||||
public PanoseMidLine getPanoseMidLine() {
|
||||
return safeEnum(PanoseMidLine.values(), () -> panose[8]).get();
|
||||
}
|
||||
|
||||
public PanoseXHeight getPanoseXHeight() {
|
||||
return safeEnum(PanoseXHeight.values(), () -> panose[9]).get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -18,9 +18,11 @@ package org.apache.poi.ddf;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
|
@ -29,7 +31,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
*/
|
||||
public abstract class AbstractEscherOptRecord extends EscherRecord
|
||||
{
|
||||
private List<EscherProperty> properties = new ArrayList<>();
|
||||
private final List<EscherProperty> properties = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Add a property to this record.
|
||||
|
@ -50,7 +52,8 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
|
|||
int pos = offset + 8;
|
||||
|
||||
EscherPropertyFactory f = new EscherPropertyFactory();
|
||||
properties = f.createProperties( data, pos, propertiesCount );
|
||||
properties.clear();
|
||||
properties.addAll( f.createProperties( data, pos, propertiesCount ) );
|
||||
return bytesRemaining + 8;
|
||||
}
|
||||
|
||||
|
@ -132,16 +135,8 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
|
|||
/**
|
||||
* Records should be sorted by property number before being stored.
|
||||
*/
|
||||
public void sortProperties()
|
||||
{
|
||||
properties.sort(new Comparator<EscherProperty>() {
|
||||
@Override
|
||||
public int compare(EscherProperty p1, EscherProperty p2) {
|
||||
short s1 = p1.getPropertyNumber();
|
||||
short s2 = p2.getPropertyNumber();
|
||||
return Short.compare(s1, s2);
|
||||
}
|
||||
});
|
||||
public void sortProperties() {
|
||||
properties.sort(Comparator.comparingInt(EscherProperty::getPropertyNumber));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -151,24 +146,13 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
|
|||
* @param value the property to set.
|
||||
*/
|
||||
public void setEscherProperty(EscherProperty value){
|
||||
for ( Iterator<EscherProperty> iterator =
|
||||
properties.iterator(); iterator.hasNext(); ) {
|
||||
EscherProperty prop = iterator.next();
|
||||
if (prop.getId() == value.getId()){
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
properties.removeIf(prop -> prop.getId() == value.getId());
|
||||
properties.add( value );
|
||||
sortProperties();
|
||||
}
|
||||
|
||||
public void removeEscherProperty(int num){
|
||||
for ( Iterator<EscherProperty> iterator = getEscherProperties().iterator(); iterator.hasNext(); ) {
|
||||
EscherProperty prop = iterator.next();
|
||||
if (prop.getPropertyNumber() == num){
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
properties.removeIf(prop -> prop.getPropertyNumber() == num);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -187,4 +171,12 @@ public abstract class AbstractEscherOptRecord extends EscherRecord
|
|||
attrList.toArray()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"isContainer", this::isContainerRecord
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -32,8 +37,7 @@ public final class EscherBSERecord extends EscherRecord {
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
public static final short RECORD_ID = (short) 0xF007;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtBSE";
|
||||
public static final short RECORD_ID = EscherRecordTypes.BSE.typeID;
|
||||
|
||||
public static final byte BT_ERROR = 0;
|
||||
public static final byte BT_UNKNOWN = 1;
|
||||
|
@ -147,7 +151,7 @@ public final class EscherBSERecord extends EscherRecord {
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "BSE";
|
||||
return EscherRecordTypes.BSE.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,4 +405,28 @@ public final class EscherBSERecord extends EscherRecord {
|
|||
{ "Extra Data", _remainingData }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String, Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
|
||||
m.put("blipTypeWin32", this::getBlipTypeWin32);
|
||||
m.put("blipTypeMacOS", this::getBlipTypeMacOS);
|
||||
m.put("suid", this::getUid);
|
||||
m.put("tag", this::getTag);
|
||||
m.put("size", this::getSize);
|
||||
m.put("ref", this::getRef);
|
||||
m.put("offset", this::getOffset);
|
||||
m.put("usage", this::getUsage);
|
||||
m.put("name", this::getName);
|
||||
m.put("unused2", this::getUnused2);
|
||||
m.put("unused3", this::getUnused3);
|
||||
m.put("blipRecord", this::getBlipRecord);
|
||||
m.put("remainingData", this::getRemainingData);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.BSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,17 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
public class EscherBitmapBlip extends EscherBlipRecord {
|
||||
public static final short RECORD_ID_JPEG = (short) 0xF018 + 5;
|
||||
public static final short RECORD_ID_PNG = (short) 0xF018 + 6;
|
||||
public static final short RECORD_ID_DIB = (short) 0xF018 + 7;
|
||||
public static final short RECORD_ID_JPEG = EscherRecordTypes.BLIP_JPEG.typeID;
|
||||
public static final short RECORD_ID_PNG = EscherRecordTypes.BLIP_PNG.typeID;
|
||||
public static final short RECORD_ID_DIB = EscherRecordTypes.BLIP_DIB.typeID;
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
|
@ -115,4 +120,14 @@ public class EscherBitmapBlip extends EscherBlipRecord {
|
|||
{ "Extra Data", getPicturedata() }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String, Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
|
||||
m.put("uid", this::getUID);
|
||||
m.put("marker", this::getMarker);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -25,9 +29,8 @@ public class EscherBlipRecord extends EscherRecord {
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 104_857_600;
|
||||
|
||||
public static final short RECORD_ID_START = (short) 0xF018;
|
||||
public static final short RECORD_ID_END = (short) 0xF117;
|
||||
public static final String RECORD_DESCRIPTION = "msofbtBlip";
|
||||
public static final short RECORD_ID_START = EscherRecordTypes.BLIP_START.typeID;
|
||||
public static final short RECORD_ID_END = EscherRecordTypes.BLIP_END.typeID;
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
|
@ -67,7 +70,8 @@ public class EscherBlipRecord extends EscherRecord {
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "Blip";
|
||||
EscherRecordTypes t = EscherRecordTypes.forTypeID(getRecordId());
|
||||
return (t != EscherRecordTypes.UNKNOWN ? t : EscherRecordTypes.BLIP_START).recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,4 +113,18 @@ public class EscherBlipRecord extends EscherRecord {
|
|||
{ "Extra Data", getPicturedata() }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"pictureData", this::getPicturedata
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
EscherRecordTypes t = EscherRecordTypes.forTypeID(getRecordId());
|
||||
return (t != EscherRecordTypes.UNKNOWN) ? t : EscherRecordTypes.BLIP_START;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
|
@ -26,11 +30,8 @@ import org.apache.poi.util.LittleEndian;
|
|||
*
|
||||
* @see EscherChildAnchorRecord
|
||||
*/
|
||||
public class EscherChildAnchorRecord
|
||||
extends EscherRecord
|
||||
{
|
||||
public static final short RECORD_ID = (short) 0xF00F;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtChildAnchor";
|
||||
public class EscherChildAnchorRecord extends EscherRecord {
|
||||
public static final short RECORD_ID = EscherRecordTypes.CHILD_ANCHOR.typeID;
|
||||
|
||||
private int field_1_dx1;
|
||||
private int field_2_dy1;
|
||||
|
@ -91,7 +92,7 @@ public class EscherChildAnchorRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "ChildAnchor";
|
||||
return EscherRecordTypes.CHILD_ANCHOR.recordName;
|
||||
}
|
||||
|
||||
|
||||
|
@ -184,4 +185,20 @@ public class EscherChildAnchorRecord
|
|||
{ "Y2", field_4_dy2 }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"x1", this::getDx1,
|
||||
"y1", this::getDy1,
|
||||
"x2", this::getDx2,
|
||||
"y2", this::getDy2
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.CHILD_ANCHOR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -28,14 +33,11 @@ import org.apache.poi.util.LittleEndian;
|
|||
*
|
||||
* @see EscherChildAnchorRecord
|
||||
*/
|
||||
public class EscherClientAnchorRecord
|
||||
extends EscherRecord
|
||||
{
|
||||
public class EscherClientAnchorRecord extends EscherRecord {
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
public static final short RECORD_ID = (short) 0xF010;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtClientAnchor";
|
||||
public static final short RECORD_ID = EscherRecordTypes.CLIENT_ANCHOR.typeID;
|
||||
|
||||
/**
|
||||
* bit[0] - fMove (1 bit): A bit that specifies whether the shape will be kept intact when the cells are moved.
|
||||
|
@ -135,7 +137,7 @@ public class EscherClientAnchorRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "ClientAnchor";
|
||||
return EscherRecordTypes.CLIENT_ANCHOR.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -361,4 +363,25 @@ public class EscherClientAnchorRecord
|
|||
{ "Extra Data", remainingData }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
|
||||
m.put("flag", this::getFlag);
|
||||
m.put("col1", this::getCol1);
|
||||
m.put("dx1", this::getDx1);
|
||||
m.put("row1", this::getRow1);
|
||||
m.put("dy1", this::getDy1);
|
||||
m.put("col2", this::getCol2);
|
||||
m.put("dx2", this::getDx2);
|
||||
m.put("row2", this::getRow2);
|
||||
m.put("dy2", this::getDy2);
|
||||
m.put("remainingData", this::getRemainingData);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.CLIENT_ANCHOR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -31,8 +35,7 @@ public class EscherClientDataRecord
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
public static final short RECORD_ID = (short) 0xF011;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtClientData";
|
||||
public static final short RECORD_ID = EscherRecordTypes.CLIENT_DATA.typeID;
|
||||
|
||||
private byte[] remainingData;
|
||||
|
||||
|
@ -75,7 +78,7 @@ public class EscherClientDataRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "ClientData";
|
||||
return EscherRecordTypes.CLIENT_DATA.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,4 +108,17 @@ public class EscherClientDataRecord
|
|||
{ "Extra Data", getRemainingData() }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"remainingData", this::getRemainingData
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.CLIENT_DATA;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,10 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
|
@ -35,12 +38,12 @@ import org.apache.poi.util.POILogger;
|
|||
* used to represent many different types of records.
|
||||
*/
|
||||
public final class EscherContainerRecord extends EscherRecord implements Iterable<EscherRecord> {
|
||||
public static final short DGG_CONTAINER = (short)0xF000;
|
||||
public static final short BSTORE_CONTAINER = (short)0xF001;
|
||||
public static final short DG_CONTAINER = (short)0xF002;
|
||||
public static final short SPGR_CONTAINER = (short)0xF003;
|
||||
public static final short SP_CONTAINER = (short)0xF004;
|
||||
public static final short SOLVER_CONTAINER = (short)0xF005;
|
||||
public static final short DGG_CONTAINER = EscherRecordTypes.DGG_CONTAINER.typeID;
|
||||
public static final short BSTORE_CONTAINER = EscherRecordTypes.BSTORE_CONTAINER.typeID;
|
||||
public static final short DG_CONTAINER = EscherRecordTypes.DG_CONTAINER.typeID;
|
||||
public static final short SPGR_CONTAINER = EscherRecordTypes.SPGR_CONTAINER.typeID;
|
||||
public static final short SP_CONTAINER = EscherRecordTypes.SP_CONTAINER.typeID;
|
||||
public static final short SOLVER_CONTAINER = EscherRecordTypes.SOLVER_CONTAINER.typeID;
|
||||
|
||||
private static final POILogger log = POILogFactory.getLogger(EscherContainerRecord.class);
|
||||
|
||||
|
@ -201,22 +204,9 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
switch (getRecordId()) {
|
||||
case DGG_CONTAINER:
|
||||
return "DggContainer";
|
||||
case BSTORE_CONTAINER:
|
||||
return "BStoreContainer";
|
||||
case DG_CONTAINER:
|
||||
return "DgContainer";
|
||||
case SPGR_CONTAINER:
|
||||
return "SpgrContainer";
|
||||
case SP_CONTAINER:
|
||||
return "SpContainer";
|
||||
case SOLVER_CONTAINER:
|
||||
return "SolverContainer";
|
||||
default:
|
||||
return "Container 0x" + HexDump.toHex(getRecordId());
|
||||
}
|
||||
final short id = getRecordId();
|
||||
EscherRecordTypes t = EscherRecordTypes.forTypeID(id);
|
||||
return (t != EscherRecordTypes.UNKNOWN) ? t.recordName : "Container 0x" + HexDump.toHex(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,4 +288,17 @@ public final class EscherContainerRecord extends EscherRecord implements Iterabl
|
|||
chList.toArray()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"isContainer", this::isContainerRecord
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.forTypeID(getRecordId());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,17 +18,18 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* This record simply holds the number of shapes in the drawing group and the
|
||||
* last shape id used for this drawing group.
|
||||
*/
|
||||
public class EscherDgRecord
|
||||
extends EscherRecord
|
||||
{
|
||||
public static final short RECORD_ID = (short) 0xF008;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtDg";
|
||||
public class EscherDgRecord extends EscherRecord {
|
||||
public static final short RECORD_ID = EscherRecordTypes.DG.typeID;
|
||||
|
||||
private int field_1_numShapes;
|
||||
private int field_2_lastMSOSPID;
|
||||
|
@ -81,7 +82,7 @@ public class EscherDgRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "Dg";
|
||||
return EscherRecordTypes.DG.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,4 +151,19 @@ public class EscherDgRecord
|
|||
{ "LastMSOSPID", field_2_lastMSOSPID }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"numShapes", this::getNumShapes,
|
||||
"lastMSOSPID", this::getLastMSOSPID,
|
||||
"drawingGroupId", this::getDrawingGroupId
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.DG;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,11 @@ import java.util.Arrays;
|
|||
import java.util.BitSet;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
|
||||
|
@ -30,9 +34,8 @@ import org.apache.poi.util.RecordFormatException;
|
|||
* This record defines the drawing groups used for a particular sheet.
|
||||
*/
|
||||
public final class EscherDggRecord extends EscherRecord {
|
||||
public static final short RECORD_ID = (short) 0xF006;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtDgg";
|
||||
|
||||
public static final short RECORD_ID = EscherRecordTypes.DGG.typeID;
|
||||
|
||||
private int field_1_shapeIdMax;
|
||||
// for some reason the number of clusters is actually the real number + 1
|
||||
// private int field_2_numIdClusters;
|
||||
|
@ -41,7 +44,7 @@ public final class EscherDggRecord extends EscherRecord {
|
|||
private final List<FileIdCluster> field_5_fileIdClusters = new ArrayList<>();
|
||||
private int maxDgId;
|
||||
|
||||
public static class FileIdCluster {
|
||||
public static class FileIdCluster implements GenericRecord {
|
||||
private int field_1_drawingGroupId;
|
||||
private int field_2_numShapeIdsUsed;
|
||||
|
||||
|
@ -61,6 +64,14 @@ public final class EscherDggRecord extends EscherRecord {
|
|||
private void incrementUsedShapeId() {
|
||||
field_2_numShapeIdsUsed++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"drawingGroupId", this::getDrawingGroupId,
|
||||
"numShapeIdUsed", this::getNumShapeIdsUsed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -129,7 +140,7 @@ public final class EscherDggRecord extends EscherRecord {
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "Dgg";
|
||||
return EscherRecordTypes.DGG.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -344,4 +355,21 @@ public final class EscherDggRecord extends EscherRecord {
|
|||
fldIds.toArray()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.DGG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"fileIdClusters", () -> field_5_fileIdClusters,
|
||||
"shapeIdMax", this::getShapeIdMax,
|
||||
"numIdClusters", this::getNumIdClusters,
|
||||
"numShapesSaved", this::getNumShapesSaved,
|
||||
"drawingsSaved", this::getDrawingsSaved
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ import java.awt.Rectangle;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
|
@ -36,9 +40,9 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000_000;
|
||||
|
||||
public static final short RECORD_ID_EMF = (short) 0xF018 + 2;
|
||||
public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
|
||||
public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
|
||||
public static final short RECORD_ID_EMF = EscherRecordTypes.BLIP_EMF.typeID;
|
||||
public static final short RECORD_ID_WMF = EscherRecordTypes.BLIP_WMF.typeID;
|
||||
public static final short RECORD_ID_PICT = EscherRecordTypes.BLIP_PICT.typeID;
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
|
@ -348,10 +352,10 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
|
|||
* @return the blip signature
|
||||
*/
|
||||
public short getSignature() {
|
||||
switch (getRecordId()) {
|
||||
case RECORD_ID_EMF: return HSSFPictureData.MSOBI_EMF;
|
||||
case RECORD_ID_WMF: return HSSFPictureData.MSOBI_WMF;
|
||||
case RECORD_ID_PICT: return HSSFPictureData.MSOBI_PICT;
|
||||
switch (EscherRecordTypes.forTypeID(getRecordId())) {
|
||||
case BLIP_EMF: return HSSFPictureData.MSOBI_EMF;
|
||||
case BLIP_WMF: return HSSFPictureData.MSOBI_WMF;
|
||||
case BLIP_PICT: return HSSFPictureData.MSOBI_PICT;
|
||||
}
|
||||
if (log.check(POILogger.WARN)) {
|
||||
log.log(POILogger.WARN, "Unknown metafile: " + getRecordId());
|
||||
|
@ -397,4 +401,17 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
|
|||
{ "Remaining Data", remainingData }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String, Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
|
||||
m.put("uid", this::getUID);
|
||||
m.put("uncompressedSize", this::getUncompressedSize);
|
||||
m.put("bounds", this::getBounds);
|
||||
m.put("sizeInEMU", this::getSizeEMU);
|
||||
m.put("compressedSize", this::getCompressedSize);
|
||||
m.put("isCompressed", this::isCompressed);
|
||||
m.put("filter", this::getFilter);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.apache.poi.util.Internal;
|
|||
*/
|
||||
public class EscherOptRecord extends AbstractEscherOptRecord
|
||||
{
|
||||
public static final String RECORD_DESCRIPTION = "msofbtOPT";
|
||||
public static final short RECORD_ID = (short) 0xF00B;
|
||||
public static final short RECORD_ID = EscherRecordTypes.OPT.typeID;
|
||||
public static final String RECORD_DESCRIPTION = EscherRecordTypes.OPT.description;
|
||||
|
||||
@Override
|
||||
public short getInstance()
|
||||
|
@ -50,9 +50,8 @@ public class EscherOptRecord extends AbstractEscherOptRecord
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getRecordName()
|
||||
{
|
||||
return "Opt";
|
||||
public String getRecordName() {
|
||||
return EscherRecordTypes.OPT.recordName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,4 +71,9 @@ public class EscherOptRecord extends AbstractEscherOptRecord
|
|||
|
||||
super.setVersion( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.OPT;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ import java.awt.Rectangle;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
|
@ -34,9 +38,9 @@ public final class EscherPictBlip extends EscherBlipRecord {
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
public static final short RECORD_ID_EMF = (short) 0xF018 + 2;
|
||||
public static final short RECORD_ID_WMF = (short) 0xF018 + 3;
|
||||
public static final short RECORD_ID_PICT = (short) 0xF018 + 4;
|
||||
public static final short RECORD_ID_EMF = EscherRecordTypes.BLIP_EMF.typeID;
|
||||
public static final short RECORD_ID_WMF = EscherRecordTypes.BLIP_WMF.typeID;
|
||||
public static final short RECORD_ID_PICT = EscherRecordTypes.BLIP_PICT.typeID;
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
|
@ -293,4 +297,17 @@ public final class EscherPictBlip extends EscherBlipRecord {
|
|||
{ "Extra Data", getPicturedata() },
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String, Supplier<?>> m = new LinkedHashMap<>(super.getGenericProperties());
|
||||
m.put("uid", this::getUID);
|
||||
m.put("uncompressedSize", this::getUncompressedSize);
|
||||
m.put("bounds", this::getBounds);
|
||||
m.put("sizeInEMU", this::getSizeEMU);
|
||||
m.put("compressedSize", this::getCompressedSize);
|
||||
m.put("isCompressed", this::isCompressed);
|
||||
m.put("filter", this::getFilter);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,13 @@ package org.apache.poi.ddf;
|
|||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
@ -32,7 +36,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
* The base abstract record from which all escher records are defined. Subclasses will need
|
||||
* to define methods for serialization/deserialization and for determining the record size.
|
||||
*/
|
||||
public abstract class EscherRecord implements Cloneable {
|
||||
public abstract class EscherRecord implements Cloneable, GenericRecord {
|
||||
private static final BitField fInstance = BitFieldFactory.getInstance(0xfff0);
|
||||
private static final BitField fVersion = BitFieldFactory.getInstance(0x000f);
|
||||
|
||||
|
@ -500,4 +504,20 @@ public abstract class EscherRecord implements Cloneable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends GenericRecord> getGenericChildren() {
|
||||
return getChildRecords();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"recordId", this::getRecordId,
|
||||
"version", this::getVersion,
|
||||
"instance", this::getInstance,
|
||||
"options", this::getOptions,
|
||||
"recordSize", this::getRecordSize
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/* ====================================================================
|
||||
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.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum EscherRecordTypes {
|
||||
// records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
|
||||
DGG_CONTAINER(0xF000, "DggContainer", null),
|
||||
BSTORE_CONTAINER(0xf001, "BStoreContainer", null),
|
||||
DG_CONTAINER(0xf002, "DgContainer", null),
|
||||
SPGR_CONTAINER(0xf003, "SpgrContainer", null),
|
||||
SP_CONTAINER(0xf004, "SpContainer", null),
|
||||
SOLVER_CONTAINER(0xf005, "SolverContainer", null),
|
||||
DGG(0xf006, "Dgg", "MsofbtDgg"),
|
||||
BSE(0xf007, "BSE", "MsofbtBSE"),
|
||||
DG(0xf008, "Dg", "MsofbtDg"),
|
||||
SPGR(0xf009, "Spgr", "MsofbtSpgr"),
|
||||
SP(0xf00a, "Sp", "MsofbtSp"),
|
||||
OPT(0xf00b, "Opt", "msofbtOPT"),
|
||||
TEXTBOX(0xf00c, null, null),
|
||||
CLIENT_TEXTBOX(0xf00d, "ClientTextbox", "msofbtClientTextbox"),
|
||||
ANCHOR(0xf00e, null, null),
|
||||
CHILD_ANCHOR(0xf00f, "ChildAnchor", "MsofbtChildAnchor"),
|
||||
CLIENT_ANCHOR(0xf010, "ClientAnchor", "MsofbtClientAnchor"),
|
||||
CLIENT_DATA(0xf011, "ClientData", "MsofbtClientData"),
|
||||
CONNECTOR_RULE(0xf012, null, null),
|
||||
ALIGN_RULE(0xf013, null, null),
|
||||
ARC_RULE(0xf014, null, null),
|
||||
CLIENT_RULE(0xf015, null, null),
|
||||
CLSID(0xf016, null, null),
|
||||
CALLOUT_RULE(0xf017, null, null),
|
||||
BLIP_START(0xf018, "Blip", "msofbtBlip"),
|
||||
BLIP_EMF(0xf018 + 2, "BlipEmf", null),
|
||||
BLIP_WMF(0xf018 + 3, "BlipWmf", null),
|
||||
BLIP_PICT(0xf018 + 4, "BlipPict", null),
|
||||
BLIP_JPEG(0xf018 + 5, "BlipJpeg", null),
|
||||
BLIP_PNG(0xf018 + 6, "BlipPng", null),
|
||||
BLIP_DIB(0xf018 + 7, "BlipDib", null),
|
||||
BLIP_END(0xf117, "Blip", "msofbtBlip"),
|
||||
REGROUP_ITEMS(0xf118, null, null),
|
||||
SELECTION(0xf119, null, null),
|
||||
COLOR_MRU(0xf11a, null, null),
|
||||
DELETED_PSPL(0xf11d, null, null),
|
||||
SPLIT_MENU_COLORS(0xf11e, "SplitMenuColors", "MsofbtSplitMenuColors"),
|
||||
OLE_OBJECT(0xf11f, null, null),
|
||||
COLOR_SCHEME(0xf120, null, null),
|
||||
// same as EscherTertiaryOptRecord.RECORD_ID
|
||||
USER_DEFINED(0xf122, "TertiaryOpt", null),
|
||||
UNKNOWN(0xffff, "unknown", "unknown");
|
||||
|
||||
public final short typeID;
|
||||
public final String recordName;
|
||||
public final String description;
|
||||
|
||||
EscherRecordTypes(int typeID, String recordName, String description) {
|
||||
this.typeID = (short) typeID;
|
||||
this.recordName = recordName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
private Short getTypeId() {
|
||||
return typeID;
|
||||
}
|
||||
|
||||
private static final Map<Short, EscherRecordTypes> LOOKUP =
|
||||
Stream.of(values()).collect(Collectors.toMap(EscherRecordTypes::getTypeId, Function.identity()));
|
||||
|
||||
public static EscherRecordTypes forTypeID(int typeID) {
|
||||
EscherRecordTypes rt = LOOKUP.get((short)typeID);
|
||||
return (rt != null) ? rt : EscherRecordTypes.UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -24,11 +30,8 @@ import org.apache.poi.util.LittleEndian;
|
|||
* Together the the EscherOptRecord this record defines some of the basic
|
||||
* properties of a shape.
|
||||
*/
|
||||
public class EscherSpRecord
|
||||
extends EscherRecord
|
||||
{
|
||||
public static final short RECORD_ID = (short) 0xF00A;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtSp";
|
||||
public class EscherSpRecord extends EscherRecord {
|
||||
public static final short RECORD_ID = EscherRecordTypes.SP.typeID;
|
||||
|
||||
public static final int FLAG_GROUP = 0x0001;
|
||||
public static final int FLAG_CHILD = 0x0002;
|
||||
|
@ -43,6 +46,36 @@ public class EscherSpRecord
|
|||
public static final int FLAG_BACKGROUND = 0x0400;
|
||||
public static final int FLAG_HASSHAPETYPE = 0x0800;
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
FLAG_GROUP,
|
||||
FLAG_CHILD,
|
||||
FLAG_PATRIARCH,
|
||||
FLAG_DELETED,
|
||||
FLAG_OLESHAPE,
|
||||
FLAG_HAVEMASTER,
|
||||
FLAG_FLIPHORIZ,
|
||||
FLAG_FLIPVERT,
|
||||
FLAG_CONNECTOR,
|
||||
FLAG_HAVEANCHOR,
|
||||
FLAG_BACKGROUND,
|
||||
FLAG_HASSHAPETYPE
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"GROUP",
|
||||
"CHILD",
|
||||
"PATRIARCH",
|
||||
"DELETED",
|
||||
"OLESHAPE",
|
||||
"HAVEMASTER",
|
||||
"FLIPHORIZ",
|
||||
"FLIPVERT",
|
||||
"CONNECTOR",
|
||||
"HAVEANCHOR",
|
||||
"BACKGROUND",
|
||||
"HASSHAPETYPE"
|
||||
};
|
||||
|
||||
private int field_1_shapeId;
|
||||
private int field_2_flags;
|
||||
|
||||
|
@ -98,7 +131,7 @@ public class EscherSpRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "Sp";
|
||||
return EscherRecordTypes.SP.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,7 +139,7 @@ public class EscherSpRecord
|
|||
*/
|
||||
private String decodeFlags( int flags )
|
||||
{
|
||||
StringBuffer result = new StringBuffer();
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append( ( flags & FLAG_GROUP ) != 0 ? "|GROUP" : "" );
|
||||
result.append( ( flags & FLAG_CHILD ) != 0 ? "|CHILD" : "" );
|
||||
result.append( ( flags & FLAG_PATRIARCH ) != 0 ? "|PATRIARCH" : "" );
|
||||
|
@ -222,4 +255,19 @@ public class EscherSpRecord
|
|||
{ "Flags", decodeFlags(field_2_flags)+" (0x"+HexDump.toHex(field_2_flags)+")" }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"shapeType", this::getShapeType,
|
||||
"shapeId", this::getShapeId,
|
||||
"flags", getBitsAsString(this::getFlags, FLAGS_MASKS, FLAGS_NAMES)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.SP;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
|
||||
|
@ -24,11 +28,8 @@ import org.apache.poi.util.RecordFormatException;
|
|||
* The spgr record defines information about a shape group. Groups in escher
|
||||
* are simply another form of shape that you can't physically see.
|
||||
*/
|
||||
public class EscherSpgrRecord
|
||||
extends EscherRecord
|
||||
{
|
||||
public static final short RECORD_ID = (short) 0xF009;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtSpgr";
|
||||
public class EscherSpgrRecord extends EscherRecord {
|
||||
public static final short RECORD_ID = EscherRecordTypes.SPGR.typeID;
|
||||
|
||||
private int field_1_rectX1;
|
||||
private int field_2_rectY1;
|
||||
|
@ -84,7 +85,7 @@ public class EscherSpgrRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "Spgr";
|
||||
return EscherRecordTypes.SPGR.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,4 +176,20 @@ public class EscherSpgrRecord
|
|||
{ "RectHeight", field_4_rectY2 }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"rectX1", this::getRectX1,
|
||||
"rectY1", this::getRectY1,
|
||||
"rectX2", this::getRectX2,
|
||||
"rectY2", this::getRectY2
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.SPGR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
|
||||
|
@ -24,11 +28,8 @@ import org.apache.poi.util.RecordFormatException;
|
|||
* A list of the most recently used colours for the drawings contained in
|
||||
* this document.
|
||||
*/
|
||||
public class EscherSplitMenuColorsRecord
|
||||
extends EscherRecord
|
||||
{
|
||||
public static final short RECORD_ID = (short) 0xF11E;
|
||||
public static final String RECORD_DESCRIPTION = "MsofbtSplitMenuColors";
|
||||
public class EscherSplitMenuColorsRecord extends EscherRecord {
|
||||
public static final short RECORD_ID = EscherRecordTypes.SPLIT_MENU_COLORS.typeID;
|
||||
|
||||
private int field_1_color1;
|
||||
private int field_2_color2;
|
||||
|
@ -82,7 +83,7 @@ public class EscherSplitMenuColorsRecord
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "SplitMenuColors";
|
||||
return EscherRecordTypes.SPLIT_MENU_COLORS.recordName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,4 +167,20 @@ public class EscherSplitMenuColorsRecord
|
|||
{ "Color4", field_4_color4 }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"color1", this::getColor1,
|
||||
"color2", this::getColor2,
|
||||
"color3", this::getColor3,
|
||||
"color4", this::getColor4
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.SPLIT_MENU_COLORS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,15 @@ package org.apache.poi.ddf;
|
|||
*/
|
||||
public class EscherTertiaryOptRecord extends AbstractEscherOptRecord
|
||||
{
|
||||
public static final short RECORD_ID = (short) 0xF122;
|
||||
public static final short RECORD_ID = EscherRecordTypes.USER_DEFINED.typeID;
|
||||
|
||||
@Override
|
||||
public String getRecordName()
|
||||
{
|
||||
return "TertiaryOpt";
|
||||
public String getRecordName() {
|
||||
return EscherRecordTypes.USER_DEFINED.recordName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.USER_DEFINED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.ddf;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.RecordFormatException;
|
||||
|
@ -35,8 +38,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
public static final short RECORD_ID = (short)0xF00D;
|
||||
public static final String RECORD_DESCRIPTION = "msofbtClientTextbox";
|
||||
public static final short RECORD_ID = EscherRecordTypes.CLIENT_TEXTBOX.typeID;
|
||||
|
||||
private static final byte[] NO_BYTES = new byte[0];
|
||||
|
||||
|
@ -134,7 +136,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable
|
|||
|
||||
@Override
|
||||
public String getRecordName() {
|
||||
return "ClientTextbox";
|
||||
return EscherRecordTypes.CLIENT_TEXTBOX.recordName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -154,4 +156,18 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable
|
|||
{ "Extra Data", thedata }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.CLIENT_TEXTBOX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"isContainer", this::isContainerRecord,
|
||||
"extraData", this::getData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.ddf;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
@ -158,4 +161,17 @@ public final class UnknownEscherRecord extends EscherRecord implements Cloneable
|
|||
{ "Extra Data", thedata }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"data", this::getData
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EscherRecordTypes.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.apache.poi.ddf.EscherOptRecord;
|
|||
import org.apache.poi.ddf.EscherProperties;
|
||||
import org.apache.poi.ddf.EscherProperty;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherTextboxRecord;
|
||||
import org.apache.poi.ddf.EscherRecordTypes;
|
||||
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
|
||||
import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
|
||||
import org.apache.poi.hssf.record.EscherAggregate;
|
||||
|
@ -71,11 +71,11 @@ public class HSSFShapeFactory {
|
|||
TextObjectRecord txtRecord = null;
|
||||
|
||||
for (EscherRecord record : container) {
|
||||
switch (record.getRecordId()) {
|
||||
case EscherClientDataRecord.RECORD_ID:
|
||||
switch (EscherRecordTypes.forTypeID(record.getRecordId())) {
|
||||
case CLIENT_DATA:
|
||||
objRecord = (ObjRecord) shapeToObj.get(record);
|
||||
break;
|
||||
case EscherTextboxRecord.RECORD_ID:
|
||||
case CLIENT_TEXTBOX:
|
||||
txtRecord = (TextObjectRecord) shapeToObj.get(record);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -17,13 +17,28 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.ddf.*;
|
||||
import org.apache.poi.hssf.record.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.ddf.DefaultEscherRecordFactory;
|
||||
import org.apache.poi.ddf.EscherBoolProperty;
|
||||
import org.apache.poi.ddf.EscherChildAnchorRecord;
|
||||
import org.apache.poi.ddf.EscherClientAnchorRecord;
|
||||
import org.apache.poi.ddf.EscherClientDataRecord;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherOptRecord;
|
||||
import org.apache.poi.ddf.EscherProperties;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherRecordTypes;
|
||||
import org.apache.poi.ddf.EscherSpRecord;
|
||||
import org.apache.poi.ddf.EscherSpgrRecord;
|
||||
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
|
||||
import org.apache.poi.hssf.record.EndSubRecord;
|
||||
import org.apache.poi.hssf.record.EscherAggregate;
|
||||
import org.apache.poi.hssf.record.GroupMarkerSubRecord;
|
||||
import org.apache.poi.hssf.record.ObjRecord;
|
||||
|
||||
/**
|
||||
* A shape group may contain other shapes. It was no actual form on the
|
||||
|
@ -40,13 +55,13 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
|
|||
EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0);
|
||||
_spgrRecord = (EscherSpgrRecord) spContainer.getChild(0);
|
||||
for (EscherRecord ch : spContainer.getChildRecords()) {
|
||||
switch (ch.getRecordId()) {
|
||||
case EscherSpgrRecord.RECORD_ID:
|
||||
switch (EscherRecordTypes.forTypeID(ch.getRecordId())) {
|
||||
case SPGR:
|
||||
break;
|
||||
case EscherClientAnchorRecord.RECORD_ID:
|
||||
case CLIENT_ANCHOR:
|
||||
anchor = new HSSFClientAnchor((EscherClientAnchorRecord) ch);
|
||||
break;
|
||||
case EscherChildAnchorRecord.RECORD_ID:
|
||||
case CHILD_ANCHOR:
|
||||
anchor = new HSSFChildAnchor((EscherChildAnchorRecord) ch);
|
||||
break;
|
||||
default:
|
||||
|
@ -307,8 +322,7 @@ public class HSSFShapeGroup extends HSSFShape implements HSSFShapeContainer {
|
|||
*/
|
||||
public int countOfAllChildren() {
|
||||
int count = shapes.size();
|
||||
for (Iterator<HSSFShape> iterator = shapes.iterator(); iterator.hasNext(); ) {
|
||||
HSSFShape shape = iterator.next();
|
||||
for (HSSFShape shape : shapes) {
|
||||
count += shape.countOfAllChildren();
|
||||
}
|
||||
return count;
|
||||
|
|
|
@ -19,16 +19,20 @@ package org.apache.poi.poifs.crypt;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
public abstract class Decryptor implements Cloneable {
|
||||
public abstract class Decryptor implements Cloneable, GenericRecord {
|
||||
public static final String DEFAULT_PASSWORD="VelvetSweatshop";
|
||||
public static final String DEFAULT_POIFS_ENTRY="EncryptedPackage";
|
||||
|
||||
|
@ -185,4 +189,14 @@ public abstract class Decryptor implements Cloneable {
|
|||
// encryptionInfo is set from outside
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"secretKey", secretKey::getEncoded,
|
||||
"verifier", this::getVerifier,
|
||||
"integrityHmacKey", this::getIntegrityHmacKey,
|
||||
"integrityHmacValue", this::getIntegrityHmacValue
|
||||
);
|
||||
}
|
||||
}
|
|
@ -16,13 +16,19 @@
|
|||
==================================================================== */
|
||||
package org.apache.poi.poifs.crypt;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
|
||||
/**
|
||||
* Reads and processes OOXML Encryption Headers
|
||||
* The constants are largely based on ZIP constants.
|
||||
*/
|
||||
public abstract class EncryptionHeader implements Cloneable {
|
||||
public abstract class EncryptionHeader implements Cloneable, GenericRecord {
|
||||
public static final int ALGORITHM_RC4 = CipherAlgorithm.rc4.ecmaId;
|
||||
public static final int ALGORITHM_AES_128 = CipherAlgorithm.aes128.ecmaId;
|
||||
public static final int ALGORITHM_AES_192 = CipherAlgorithm.aes192.ecmaId;
|
||||
|
@ -156,4 +162,20 @@ public abstract class EncryptionHeader implements Cloneable {
|
|||
other.keySalt = (keySalt == null) ? null : keySalt.clone();
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("flags", this::getFlags);
|
||||
m.put("sizeExtra", this::getSizeExtra);
|
||||
m.put("cipherAlgorithm", this::getCipherAlgorithm);
|
||||
m.put("hashAlgorithm", this::getHashAlgorithm);
|
||||
m.put("keyBits", this::getKeySize);
|
||||
m.put("blockSize", this::getBlockSize);
|
||||
m.put("providerType", this::getCipherProvider);
|
||||
m.put("chainingMode", this::getChainingMode);
|
||||
m.put("keySalt", this::getKeySalt);
|
||||
m.put("cspName", this::getCspName);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,16 @@ import static org.apache.poi.poifs.crypt.EncryptionMode.binaryRC4;
|
|||
import static org.apache.poi.poifs.crypt.EncryptionMode.cryptoAPI;
|
||||
import static org.apache.poi.poifs.crypt.EncryptionMode.standard;
|
||||
import static org.apache.poi.poifs.crypt.EncryptionMode.xor;
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.BitField;
|
||||
|
@ -36,7 +42,7 @@ import org.apache.poi.util.LittleEndianInput;
|
|||
* some {@link EncryptionMode}s.
|
||||
* @see #getBuilder(EncryptionMode)
|
||||
*/
|
||||
public class EncryptionInfo implements Cloneable {
|
||||
public class EncryptionInfo implements Cloneable, GenericRecord {
|
||||
private final EncryptionMode encryptionMode;
|
||||
private final int versionMajor;
|
||||
private final int versionMinor;
|
||||
|
@ -72,8 +78,15 @@ public class EncryptionInfo implements Cloneable {
|
|||
* ECMA-376. If the fAES bit is 1, the fCryptoAPI bit MUST also be 1.
|
||||
*/
|
||||
public static final BitField flagAES = BitFieldFactory.getInstance(0x20);
|
||||
|
||||
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
0x04, 0x08, 0x10, 0x20
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"CRYPTO_API", "DOC_PROPS", "EXTERNAL", "AES"
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens for decryption
|
||||
*/
|
||||
|
@ -277,4 +290,18 @@ public class EncryptionInfo implements Cloneable {
|
|||
other.encryptor.setEncryptionInfo(other);
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("encryptionMode", this::getEncryptionMode);
|
||||
m.put("versionMajor", this::getVersionMajor);
|
||||
m.put("versionMinor", this::getVersionMinor);
|
||||
m.put("encryptionFlags", getBitsAsString(this::getEncryptionFlags, FLAGS_MASKS, FLAGS_NAMES));
|
||||
m.put("header", this::getHeader);
|
||||
m.put("verifier", this::getVerifier);
|
||||
m.put("decryptor", this::getDecryptor);
|
||||
m.put("encryptor", this::getEncryptor);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
|
@ -16,10 +16,17 @@
|
|||
==================================================================== */
|
||||
package org.apache.poi.poifs.crypt;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
|
||||
/**
|
||||
* Used when checking if a key is valid for a document
|
||||
*/
|
||||
public abstract class EncryptionVerifier implements Cloneable {
|
||||
public abstract class EncryptionVerifier implements Cloneable, GenericRecord {
|
||||
private byte[] salt;
|
||||
private byte[] encryptedVerifier;
|
||||
private byte[] encryptedVerifierHash;
|
||||
|
@ -105,4 +112,18 @@ public abstract class EncryptionVerifier implements Cloneable {
|
|||
other.encryptedKey = (encryptedKey == null) ? null : encryptedKey.clone();
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("salt", this::getSalt);
|
||||
m.put("encryptedVerifier", this::getEncryptedVerifier);
|
||||
m.put("encryptedVerifierHash", this::getEncryptedVerifierHash);
|
||||
m.put("encryptedKey", this::getEncryptedKey);
|
||||
m.put("spinCount", this::getSpinCount);
|
||||
m.put("cipherAlgorithm", this::getCipherAlgorithm);
|
||||
m.put("chainingMode", this::getChainingMode);
|
||||
m.put("hashAlgorithm", this::getHashAlgorithm);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,19 @@ package org.apache.poi.poifs.crypt;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
public abstract class Encryptor implements Cloneable {
|
||||
public abstract class Encryptor implements Cloneable, GenericRecord {
|
||||
protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY;
|
||||
private EncryptionInfo encryptionInfo;
|
||||
private SecretKey secretKey;
|
||||
|
@ -93,4 +97,11 @@ public abstract class Encryptor implements Cloneable {
|
|||
// encryptionInfo is set from outside
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"secretKey", secretKey::getEncoded
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,9 +76,9 @@ public class DrawPictureShape extends DrawSimpleShape {
|
|||
* @param graphics the graphics context
|
||||
* @return the image renderer
|
||||
*/
|
||||
@SuppressWarnings({"WeakerAccess", "unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) {
|
||||
final ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER);
|
||||
final ImageRenderer renderer = (graphics != null) ? (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER) : null;
|
||||
if (renderer != null && renderer.canRender(contentType)) {
|
||||
return renderer;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.awt.BasicStroke;
|
|||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
@ -62,6 +62,10 @@ public class DrawSimpleShape extends DrawShape {
|
|||
return;
|
||||
}
|
||||
|
||||
Paint oldPaint = graphics.getPaint();
|
||||
Stroke oldStroke = graphics.getStroke();
|
||||
Color oldColor = graphics.getColor();
|
||||
|
||||
Paint fill = getFillPaint(graphics);
|
||||
Paint line = getLinePaint(graphics);
|
||||
BasicStroke stroke = getStroke(); // the stroke applies both to the shadow and the shape
|
||||
|
@ -115,8 +119,12 @@ public class DrawSimpleShape extends DrawShape {
|
|||
}
|
||||
}
|
||||
|
||||
// draw line decorations
|
||||
// draw line decorations
|
||||
drawDecoration(graphics, line, stroke);
|
||||
|
||||
graphics.setColor(oldColor);
|
||||
graphics.setPaint(oldPaint);
|
||||
graphics.setStroke(oldStroke);
|
||||
}
|
||||
|
||||
private void fillArea(Graphics2D graphics, PaintModifier pm, Path2D area) {
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.awt.image.BufferedImage;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
|
||||
/**
|
||||
* Classes can implement this interfaces to support other formats, for
|
||||
* example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java:
|
||||
|
@ -134,4 +136,7 @@ public interface ImageRenderer {
|
|||
* @return true if the picture data was successfully rendered
|
||||
*/
|
||||
boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip);
|
||||
|
||||
default GenericRecord getGenericRecord() { return null; }
|
||||
|
||||
}
|
|
@ -105,21 +105,38 @@ public interface TextShape<
|
|||
*/
|
||||
enum TextPlaceholder {
|
||||
/** Title placeholder shape text */
|
||||
TITLE,
|
||||
TITLE(0),
|
||||
/** Body placeholder shape text */
|
||||
BODY,
|
||||
BODY(1),
|
||||
/** Center title placeholder shape text */
|
||||
CENTER_TITLE,
|
||||
CENTER_TITLE(6),
|
||||
/** Center body placeholder shape text */
|
||||
CENTER_BODY,
|
||||
CENTER_BODY(5),
|
||||
/** Half-sized body placeholder shape text */
|
||||
HALF_BODY,
|
||||
HALF_BODY(7),
|
||||
/** Quarter-sized body placeholder shape text */
|
||||
QUARTER_BODY,
|
||||
QUARTER_BODY(8),
|
||||
/** Notes placeholder shape text */
|
||||
NOTES,
|
||||
NOTES(2),
|
||||
/** Any other text */
|
||||
OTHER
|
||||
OTHER(4);
|
||||
|
||||
public final int nativeId;
|
||||
|
||||
TextPlaceholder(int nativeId) {
|
||||
this.nativeId = nativeId;
|
||||
}
|
||||
|
||||
public static TextPlaceholder fromNativeId(int nativeId) {
|
||||
for (TextPlaceholder ld : values()) {
|
||||
if (ld.nativeId == nativeId) return ld;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isTitle(int nativeId) {
|
||||
return (nativeId == TITLE.nativeId || nativeId == CENTER_TITLE.nativeId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.util;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.util.GenericRecordUtil.AnnotatedFlag;
|
||||
|
||||
@Beta
|
||||
public class GenericRecordJsonWriter implements Closeable {
|
||||
private static final String TABS;
|
||||
private static final String ZEROS = "0000000000000000";
|
||||
private static final Pattern ESC_CHARS = Pattern.compile("[\"\\p{Cntrl}\\\\]");
|
||||
|
||||
private static final List<Map.Entry<Class,BiConsumer<GenericRecordJsonWriter,Object>>> handler = new ArrayList<>();
|
||||
|
||||
static {
|
||||
char[] t = new char[255];
|
||||
Arrays.fill(t, '\t');
|
||||
TABS = new String(t);
|
||||
handler(String.class, GenericRecordJsonWriter::printObject);
|
||||
handler(Number.class, GenericRecordJsonWriter::printNumber);
|
||||
handler(Boolean.class, GenericRecordJsonWriter::printBoolean);
|
||||
handler(List.class, GenericRecordJsonWriter::printList);
|
||||
handler(GenericRecord.class, GenericRecordJsonWriter::printGenericRecord);
|
||||
handler(AnnotatedFlag.class, GenericRecordJsonWriter::printAnnotatedFlag);
|
||||
handler(byte[].class, GenericRecordJsonWriter::printBytes);
|
||||
handler(Point2D.class, GenericRecordJsonWriter::printPoint);
|
||||
handler(Dimension2D.class, GenericRecordJsonWriter::printDimension);
|
||||
handler(Rectangle2D.class, GenericRecordJsonWriter::printRectangle);
|
||||
handler(Path2D.class, GenericRecordJsonWriter::printPath);
|
||||
handler(AffineTransform.class, GenericRecordJsonWriter::printAffineTransform);
|
||||
handler(Color.class, GenericRecordJsonWriter::printColor);
|
||||
handler(Array.class, GenericRecordJsonWriter::printArray);
|
||||
handler(Object.class, GenericRecordJsonWriter::printObject);
|
||||
}
|
||||
|
||||
private static void handler(Class c, BiConsumer<GenericRecordJsonWriter,Object> printer) {
|
||||
handler.add(new AbstractMap.SimpleEntry<>(c,printer));
|
||||
}
|
||||
|
||||
private final PrintWriter fw;
|
||||
private int indent = 0;
|
||||
private boolean withComments = true;
|
||||
private int childIndex = 0;
|
||||
|
||||
public GenericRecordJsonWriter(File fileName) throws IOException {
|
||||
OutputStream os = ("null".equals(fileName.getName())) ? new NullOutputStream() : new FileOutputStream(fileName);
|
||||
fw = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public GenericRecordJsonWriter(Appendable buffer) {
|
||||
fw = new PrintWriter(new Writer(){
|
||||
@Override
|
||||
public void write(char[] cbuf, int off, int len) throws IOException {
|
||||
buffer.append(String.valueOf(cbuf), off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if (buffer instanceof Flushable) {
|
||||
((Flushable)buffer).flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
if (buffer instanceof Closeable) {
|
||||
((Closeable)buffer).close();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String marshal(GenericRecord record) {
|
||||
return marshal(record, true);
|
||||
}
|
||||
|
||||
public static String marshal(GenericRecord record, boolean withComments) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
try (GenericRecordJsonWriter w = new GenericRecordJsonWriter(sb)) {
|
||||
w.setWithComments(withComments);
|
||||
w.write(record);
|
||||
return sb.toString();
|
||||
} catch (IOException e) {
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
|
||||
public void setWithComments(boolean withComments) {
|
||||
this.withComments = withComments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
fw.close();
|
||||
}
|
||||
|
||||
private String tabs() {
|
||||
return TABS.substring(0, Math.min(indent, TABS.length()));
|
||||
}
|
||||
|
||||
public void write(GenericRecord record) {
|
||||
final String tabs = tabs();
|
||||
Enum type = record.getGenericRecordType();
|
||||
String recordName = (type != null) ? type.name() : record.getClass().getSimpleName();
|
||||
fw.append(tabs);
|
||||
fw.append("{");
|
||||
if (withComments) {
|
||||
fw.append(" /* ");
|
||||
fw.append(recordName);
|
||||
if (childIndex > 0) {
|
||||
fw.append(" - index: ");
|
||||
fw.print(childIndex);
|
||||
}
|
||||
fw.append(" */");
|
||||
}
|
||||
fw.println();
|
||||
|
||||
Map<String, Supplier<?>> prop = record.getGenericProperties();
|
||||
if (prop != null) {
|
||||
final int oldChildIndex = childIndex;
|
||||
childIndex = 0;
|
||||
prop.forEach(this::writeProp);
|
||||
childIndex = oldChildIndex;
|
||||
}
|
||||
|
||||
fw.println();
|
||||
List<? extends GenericRecord> list = record.getGenericChildren();
|
||||
if (list != null && !list.isEmpty()) {
|
||||
indent++;
|
||||
fw.append(tabs());
|
||||
if (prop != null && !prop.isEmpty()) {
|
||||
fw.append(", ");
|
||||
}
|
||||
fw.append("children: [");
|
||||
final int oldChildIndex = childIndex;
|
||||
childIndex = 0;
|
||||
list.forEach(l -> { writeValue(l); childIndex++; });
|
||||
childIndex = oldChildIndex;
|
||||
fw.println();
|
||||
fw.append(tabs());
|
||||
fw.append("]");
|
||||
fw.println();
|
||||
indent--;
|
||||
}
|
||||
|
||||
fw.append(tabs);
|
||||
fw.append("}");
|
||||
}
|
||||
|
||||
public void writeError(String errorMsg) {
|
||||
fw.append("{ error: ");
|
||||
printObject(errorMsg);
|
||||
fw.append(" }");
|
||||
}
|
||||
|
||||
private void writeProp(String k, Supplier<?> v) {
|
||||
final boolean isNext = (childIndex++>0);
|
||||
if (isNext) {
|
||||
fw.println();
|
||||
}
|
||||
fw.write(tabs());
|
||||
fw.write('\t');
|
||||
fw.write(isNext ? ", " : " ");
|
||||
fw.write(k);
|
||||
fw.write(": ");
|
||||
final int oldChildIndex = childIndex;
|
||||
childIndex = 0;
|
||||
writeValue(v.get());
|
||||
childIndex = oldChildIndex;
|
||||
}
|
||||
|
||||
private void writeValue(Object o) {
|
||||
if (childIndex > 0) {
|
||||
fw.println(',');
|
||||
}
|
||||
if (o == null) {
|
||||
fw.write("null");
|
||||
} else {
|
||||
handler.stream().
|
||||
filter(h -> matchInstanceOrArray(h.getKey(), o)).
|
||||
findFirst().
|
||||
ifPresent(h -> h.getValue().accept(this, o));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matchInstanceOrArray(Class key, Object instance) {
|
||||
return key.isInstance(instance) || (Array.class.equals(key) && instance.getClass().isArray());
|
||||
}
|
||||
|
||||
private void printNumber(Object o) {
|
||||
Number n = (Number)o;
|
||||
fw.print(n.toString());
|
||||
|
||||
final int size;
|
||||
if (n instanceof Byte) {
|
||||
size = 2;
|
||||
} else if (n instanceof Short) {
|
||||
size = 4;
|
||||
} else if (n instanceof Integer) {
|
||||
size = 8;
|
||||
} else if (n instanceof Long) {
|
||||
size = 16;
|
||||
} else {
|
||||
size = -1;
|
||||
}
|
||||
|
||||
long l = n.longValue();
|
||||
if (withComments && size > 0 && (l < 0 || l > 9)) {
|
||||
fw.write(" /* 0x");
|
||||
fw.write(trimHex(l, size));
|
||||
fw.write(" */");
|
||||
}
|
||||
}
|
||||
|
||||
private void printBoolean(Object o) {
|
||||
fw.write(((Boolean)o).toString());
|
||||
}
|
||||
|
||||
private void printList(Object o) {
|
||||
fw.println('[');
|
||||
final int[] c = new int[1];
|
||||
//noinspection unchecked
|
||||
int oldChildIndex = childIndex;
|
||||
childIndex = 0;
|
||||
((List)o).forEach(e -> { writeValue(e); childIndex++; });
|
||||
childIndex = oldChildIndex;
|
||||
fw.write(']');
|
||||
}
|
||||
|
||||
private void printGenericRecord(Object o) {
|
||||
fw.println();
|
||||
this.indent++;
|
||||
write((GenericRecord) o);
|
||||
this.indent--;
|
||||
}
|
||||
|
||||
private void printAnnotatedFlag(Object o) {
|
||||
AnnotatedFlag af = (AnnotatedFlag) o;
|
||||
fw.write("0x");
|
||||
fw.write(Long.toHexString(af.getValue().get().longValue()));
|
||||
if (withComments) {
|
||||
fw.write(" /* ");
|
||||
fw.write(af.getDescription());
|
||||
fw.write(" */ ");
|
||||
}
|
||||
}
|
||||
|
||||
private void printBytes(Object o) {
|
||||
fw.write('"');
|
||||
fw.write(DatatypeConverter.printBase64Binary((byte[]) o));
|
||||
fw.write('"');
|
||||
}
|
||||
|
||||
private void printPoint(Object o) {
|
||||
Point2D p = (Point2D)o;
|
||||
fw.write("{ x: "+p.getX()+", y: "+p.getY()+" }");
|
||||
}
|
||||
|
||||
private void printDimension(Object o) {
|
||||
Dimension2D p = (Dimension2D)o;
|
||||
fw.write("{ width: "+p.getWidth()+", height: "+p.getHeight()+" }");
|
||||
}
|
||||
|
||||
private void printRectangle(Object o) {
|
||||
Rectangle2D p = (Rectangle2D)o;
|
||||
fw.write("{ x: "+p.getX()+", y: "+p.getY()+", width: "+p.getWidth()+", height: "+p.getHeight()+" }");
|
||||
}
|
||||
|
||||
private void printPath(Object o) {
|
||||
final PathIterator iter = ((Path2D)o).getPathIterator(null);
|
||||
final double[] pnts = new double[6];
|
||||
fw.print("[");
|
||||
|
||||
indent += 2;
|
||||
String t = tabs();
|
||||
indent -= 2;
|
||||
|
||||
boolean isNext = false;
|
||||
while (!iter.isDone()) {
|
||||
fw.println(isNext ? ", " : "");
|
||||
fw.print(t);
|
||||
isNext = true;
|
||||
final int segType = iter.currentSegment(pnts);
|
||||
fw.append("{ type: ");
|
||||
switch (segType) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
fw.write("'move', x: "+pnts[0]+", y: "+pnts[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
fw.write("'lineto', x: "+pnts[0]+", y: "+pnts[1]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
fw.write("'quad', x1: "+pnts[0]+", y1: "+pnts[1]+", x2: "+pnts[2]+", y2: "+pnts[3]);
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
fw.write("'cubic', x1: "+pnts[0]+", y1: "+pnts[1]+", x2: "+pnts[2]+", y2: "+pnts[3]+", x3: "+pnts[4]+", y3: "+pnts[5]);
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
fw.write("'close'");
|
||||
break;
|
||||
}
|
||||
fw.append(" }");
|
||||
iter.next();
|
||||
}
|
||||
|
||||
fw.write("]");
|
||||
}
|
||||
|
||||
private void printObject(Object o) {
|
||||
fw.write('"');
|
||||
|
||||
final Matcher m = ESC_CHARS.matcher(o.toString());
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
while (m.find()) {
|
||||
String repl;
|
||||
String match = m.group();
|
||||
switch (match) {
|
||||
case "\n":
|
||||
repl = "\\\\n";
|
||||
break;
|
||||
case "\r":
|
||||
repl = "\\\\r";
|
||||
break;
|
||||
case "\t":
|
||||
repl = "\\\\t";
|
||||
break;
|
||||
case "\b":
|
||||
repl = "\\\\b";
|
||||
break;
|
||||
case "\f":
|
||||
repl = "\\\\f";
|
||||
break;
|
||||
case "\\":
|
||||
repl = "\\\\\\\\";
|
||||
break;
|
||||
case "\"":
|
||||
repl = "\\\\\"";
|
||||
break;
|
||||
default:
|
||||
repl = "\\\\u" + trimHex(match.charAt(0), 4);
|
||||
break;
|
||||
}
|
||||
m.appendReplacement(sb, repl);
|
||||
}
|
||||
m.appendTail(sb);
|
||||
fw.write(sb.toString());
|
||||
|
||||
fw.write('"');
|
||||
}
|
||||
|
||||
private void printAffineTransform(Object o) {
|
||||
AffineTransform xForm = (AffineTransform)o;
|
||||
fw.write(
|
||||
"{ scaleX: "+xForm.getScaleX()+
|
||||
", shearX: "+xForm.getShearX()+
|
||||
", transX: "+xForm.getTranslateX()+
|
||||
", scaleY: "+xForm.getScaleY()+
|
||||
", shearY: "+xForm.getShearY()+
|
||||
", transY: "+xForm.getTranslateY()+" }");
|
||||
}
|
||||
|
||||
private void printColor(Object o) {
|
||||
final int rgb = ((Color)o).getRGB();
|
||||
fw.print(rgb);
|
||||
|
||||
if (withComments) {
|
||||
fw.write(" /* 0x");
|
||||
fw.write(trimHex(rgb, 8));
|
||||
fw.write(" */");
|
||||
}
|
||||
}
|
||||
|
||||
private void printArray(Object o) {
|
||||
fw.println('[');
|
||||
int length = Array.getLength(o);
|
||||
final int oldChildIndex = childIndex;
|
||||
for (childIndex=0; childIndex<length; childIndex++) {
|
||||
writeValue(Array.get(o, childIndex));
|
||||
}
|
||||
childIndex = oldChildIndex;
|
||||
fw.write(']');
|
||||
}
|
||||
|
||||
private String trimHex(final long l, final int size) {
|
||||
final String b = Long.toHexString(l);
|
||||
int len = b.length();
|
||||
return ZEROS.substring(0, Math.max(0,size-len)) + b.substring(Math.max(0,len-size), len);
|
||||
}
|
||||
|
||||
private static class NullOutputStream extends OutputStream {
|
||||
private NullOutputStream() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Internal
|
||||
public final class GenericRecordUtil {
|
||||
private GenericRecordUtil() {}
|
||||
|
||||
public static Map<String, Supplier<?>>
|
||||
getGenericProperties(String val1, Supplier<?> sup1) {
|
||||
return Collections.unmodifiableMap(Collections.singletonMap(val1, sup1));
|
||||
}
|
||||
|
||||
public static Map<String, Supplier<?>> getGenericProperties(
|
||||
String val1, Supplier<?> sup1,
|
||||
String val2, Supplier<?> sup2
|
||||
) {
|
||||
return getGenericProperties(val1, sup1, val2, sup2, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static Map<String, Supplier<?>> getGenericProperties(
|
||||
String val1, Supplier<?> sup1,
|
||||
String val2, Supplier<?> sup2,
|
||||
String val3, Supplier<?> sup3
|
||||
) {
|
||||
return getGenericProperties(val1, sup1, val2, sup2, val3, sup3, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static Map<String, Supplier<?>> getGenericProperties(
|
||||
String val1, Supplier<?> sup1,
|
||||
String val2, Supplier<?> sup2,
|
||||
String val3, Supplier<?> sup3,
|
||||
String val4, Supplier<?> sup4
|
||||
) {
|
||||
return getGenericProperties(val1, sup1, val2, sup2, val3, sup3, val4, sup4, null, null, null, null);
|
||||
|
||||
}
|
||||
|
||||
public static Map<String, Supplier<?>> getGenericProperties(
|
||||
String val1, Supplier<?> sup1,
|
||||
String val2, Supplier<?> sup2,
|
||||
String val3, Supplier<?> sup3,
|
||||
String val4, Supplier<?> sup4,
|
||||
String val5, Supplier<?> sup5
|
||||
) {
|
||||
return getGenericProperties(val1, sup1, val2, sup2, val3, sup3, val4, sup4, val5, sup5, null, null);
|
||||
}
|
||||
|
||||
public static Map<String, Supplier<?>> getGenericProperties(
|
||||
String val1, Supplier<?> sup1,
|
||||
String val2, Supplier<?> sup2,
|
||||
String val3, Supplier<?> sup3,
|
||||
String val4, Supplier<?> sup4,
|
||||
String val5, Supplier<?> sup5,
|
||||
String val6, Supplier<?> sup6
|
||||
) {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
|
||||
final String[] vals = { val1, val2, val3, val4, val5, val6 };
|
||||
final Supplier<?>[] sups = { sup1, sup2, sup3, sup4, sup5, sup6 };
|
||||
|
||||
for (int i=0; i<vals.length && vals[i] != null; i++) {
|
||||
assert(sups[i] != null);
|
||||
if ("base".equals(vals[i])) {
|
||||
Object baseMap = sups[i].get();
|
||||
assert(baseMap instanceof Map);
|
||||
//noinspection unchecked
|
||||
m.putAll((Map<String,Supplier<?>>)baseMap);
|
||||
} else {
|
||||
m.put(vals[i], sups[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
public static <T extends Enum> Supplier<T> safeEnum(T[] values, Supplier<Number> ordinal) {
|
||||
return safeEnum(values, ordinal, null);
|
||||
}
|
||||
|
||||
public static <T extends Enum> Supplier<T> safeEnum(T[] values, Supplier<Number> ordinal, T defaultVal) {
|
||||
int ord = ordinal.get().intValue();
|
||||
return () -> (0 <= ord && ord < values.length) ? values[ord] : defaultVal;
|
||||
}
|
||||
|
||||
public static Supplier<AnnotatedFlag> getBitsAsString(Supplier<Number> flags, final int[] masks, final String[] names) {
|
||||
return () -> new AnnotatedFlag(flags, masks, names);
|
||||
}
|
||||
|
||||
public static class AnnotatedFlag {
|
||||
private final Supplier<Number> value;
|
||||
private final Map<Integer,String> masks = new LinkedHashMap<>();
|
||||
|
||||
AnnotatedFlag(Supplier<Number> value, int[] masks, String[] names) {
|
||||
assert(masks.length == names.length);
|
||||
|
||||
this.value = value;
|
||||
for (int i=0; i<masks.length; i++) {
|
||||
this.masks.put(masks[i], names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Supplier<Number> getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
final int val = value.get().intValue();
|
||||
return masks.entrySet().stream().
|
||||
filter(e -> match(val, e.getKey())).
|
||||
map(Map.Entry::getValue).
|
||||
collect(Collectors.joining(" | "));
|
||||
}
|
||||
|
||||
private static boolean match(final int val, int mask) {
|
||||
return (val & mask) == mask;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,16 +16,19 @@
|
|||
==================================================================== */
|
||||
package org.apache.poi.poifs.crypt.agile;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.EncryptionHeader;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
|
||||
import com.microsoft.schemas.office.x2006.encryption.CTKeyData;
|
||||
import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
|
||||
import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.crypt.ChainingMode;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.EncryptionHeader;
|
||||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable {
|
||||
private byte[] encryptedHmacKey;
|
||||
|
@ -132,4 +135,12 @@ public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable
|
|||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"encryptedHmacKey", this::getEncryptedHmacKey,
|
||||
"encryptedHmacValue", this::getEncryptedHmacValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,24 +19,45 @@
|
|||
|
||||
package org.apache.poi.xslf.util;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import static java.util.Spliterator.NONNULL;
|
||||
import static java.util.Spliterator.ORDERED;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators.AbstractSpliterator;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.sl.draw.DrawPictureShape;
|
||||
import org.apache.poi.sl.draw.Drawable;
|
||||
import org.apache.poi.sl.draw.ImageRenderer;
|
||||
import org.apache.poi.sl.usermodel.PictureData;
|
||||
import org.apache.poi.sl.usermodel.Slide;
|
||||
import org.apache.poi.sl.usermodel.SlideShow;
|
||||
import org.apache.poi.sl.usermodel.SlideShowFactory;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
|
||||
/**
|
||||
* An utility to convert slides of a .pptx slide show to a PNG image
|
||||
|
@ -57,12 +78,14 @@ public class PPTX2PNG {
|
|||
(error == null ? "" : ("Error: "+error+"\n")) +
|
||||
"Options:\n" +
|
||||
" -scale <float> scale factor\n" +
|
||||
" -fixSide <side> specify side (long,short,width,height) to fix - use <scale> as amount of pixels\n" +
|
||||
" -slide <integer> 1-based index of a slide to render\n" +
|
||||
" -format <type> png,gif,jpg (,null for testing)\n" +
|
||||
" -outdir <dir> output directory, defaults to origin of the ppt/pptx file\n" +
|
||||
" -outfile <file> output filename, defaults to '"+OUTPUT_PAT_REGEX+"'\n" +
|
||||
" -outpat <pattern> output filename pattern, defaults to '"+OUTPUT_PAT_REGEX+"'\n" +
|
||||
" patterns: basename, slideno, format, ext\n" +
|
||||
" -dump <file> dump the annotated records to a file\n" +
|
||||
" -quiet do not write to console (for normal processing)";
|
||||
|
||||
System.out.println(msg);
|
||||
|
@ -82,7 +105,10 @@ public class PPTX2PNG {
|
|||
File outdir = null;
|
||||
String outfile = null;
|
||||
boolean quiet = false;
|
||||
String outpattern = OUTPUT_PAT_REGEX;
|
||||
String outPattern = OUTPUT_PAT_REGEX;
|
||||
File dumpfile = null;
|
||||
String fixSide = "scale";
|
||||
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String opt = (i+1 < args.length) ? args[i+1] : null;
|
||||
|
@ -108,12 +134,20 @@ public class PPTX2PNG {
|
|||
i++;
|
||||
break;
|
||||
case "-outpat":
|
||||
outpattern = opt;
|
||||
outPattern = opt;
|
||||
i++;
|
||||
break;
|
||||
case "-quiet":
|
||||
quiet = true;
|
||||
break;
|
||||
case "-dump":
|
||||
dumpfile = new File(opt);
|
||||
i++;
|
||||
break;
|
||||
case "-fixside":
|
||||
fixSide = opt.toLowerCase(Locale.ROOT);
|
||||
i++;
|
||||
break;
|
||||
default:
|
||||
file = new File(args[i]);
|
||||
break;
|
||||
|
@ -144,28 +178,64 @@ public class PPTX2PNG {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!"long,short,width,height,scale".contains(fixSide)) {
|
||||
usage("<fixside> must be one of long / short / width / height");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!quiet) {
|
||||
System.out.println("Processing " + file);
|
||||
}
|
||||
try (SlideShow<?, ?> ss = SlideShowFactory.create(file, null, true)) {
|
||||
List<? extends Slide<?, ?>> slides = ss.getSlides();
|
||||
|
||||
Set<Integer> slidenum = slideIndexes(slides.size(), slidenumStr);
|
||||
|
||||
try (MFProxy proxy = initProxy(file)) {
|
||||
final Set<Integer> slidenum = proxy.slideIndexes(slidenumStr);
|
||||
if (slidenum.isEmpty()) {
|
||||
usage("slidenum must be either -1 (for all) or within range: [1.." + slides.size() + "] for " + file);
|
||||
usage("slidenum must be either -1 (for all) or within range: [1.." + proxy.getSlideCount() + "] for " + file);
|
||||
return;
|
||||
}
|
||||
|
||||
Dimension pgsize = ss.getPageSize();
|
||||
int width = (int) (pgsize.width * scale);
|
||||
int height = (int) (pgsize.height * scale);
|
||||
final Dimension2D pgsize = proxy.getSize();
|
||||
final double lenSide;
|
||||
switch (fixSide) {
|
||||
default:
|
||||
case "scale":
|
||||
lenSide = 1;
|
||||
break;
|
||||
case "long":
|
||||
lenSide = Math.max(pgsize.getWidth(), pgsize.getHeight());
|
||||
break;
|
||||
case "short":
|
||||
lenSide = Math.min(pgsize.getWidth(), pgsize.getHeight());
|
||||
break;
|
||||
case "width":
|
||||
lenSide = pgsize.getWidth();
|
||||
break;
|
||||
case "height":
|
||||
lenSide = pgsize.getHeight();
|
||||
break;
|
||||
}
|
||||
|
||||
for (Integer slideNo : slidenum) {
|
||||
Slide<?, ?> slide = slides.get(slideNo);
|
||||
String title = slide.getTitle();
|
||||
final int width = (int) Math.rint(pgsize.getWidth() * scale / lenSide);
|
||||
final int height = (int) Math.rint(pgsize.getHeight() * scale / lenSide);
|
||||
|
||||
|
||||
for (int slideNo : slidenum) {
|
||||
proxy.setSlideNo(slideNo);
|
||||
if (!quiet) {
|
||||
System.out.println("Rendering slide " + (slideNo+1) + (title == null ? "" : ": " + title.trim()));
|
||||
String title = proxy.getTitle();
|
||||
System.out.println("Rendering slide " + (slideNo + 1) + (title == null ? "" : ": " + title.trim()));
|
||||
}
|
||||
|
||||
GenericRecord gr = proxy.getRoot();
|
||||
if (dumpfile != null) {
|
||||
try (GenericRecordJsonWriter fw = new GenericRecordJsonWriter(dumpfile)) {
|
||||
if (gr == null) {
|
||||
fw.writeError(file.getName()+" doesn't support GenericRecord interface and can't be dumped to a file.");
|
||||
} else {
|
||||
fw.write(gr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
|
@ -174,19 +244,25 @@ public class PPTX2PNG {
|
|||
// default rendering options
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||
graphics.setRenderingHint(Drawable.BUFFERED_IMAGE, new WeakReference<>(img));
|
||||
|
||||
graphics.scale(scale, scale);
|
||||
graphics.scale(scale / lenSide, scale / lenSide);
|
||||
|
||||
graphics.setComposite(AlphaComposite.Clear);
|
||||
graphics.fillRect(0, 0, (int)width, (int)height);
|
||||
graphics.setComposite(AlphaComposite.SrcOver);
|
||||
|
||||
// draw stuff
|
||||
slide.draw(graphics);
|
||||
proxy.draw(graphics);
|
||||
|
||||
// save the result
|
||||
if (!"null".equals(format)) {
|
||||
String inname = String.format(Locale.ROOT, "%04d|%s|%s", slideNo+1, format, file.getName());
|
||||
String outname = (outfile != null) ? outfile : INPUT_PATTERN.matcher(inname).replaceAll(outpattern);
|
||||
String inname = String.format(Locale.ROOT, "%04d|%s|%s", slideNo, format, file.getName());
|
||||
String outpat = (proxy.getSlideCount() > 1 ? outPattern : outPattern.replaceAll("-?\\$\\{slideno\\}", ""));
|
||||
String outname = (outfile != null) ? outfile : INPUT_PATTERN.matcher(inname).replaceAll(outpat);
|
||||
ImageIO.write(img, format, new File(outdir, outname));
|
||||
}
|
||||
|
||||
|
@ -200,42 +276,181 @@ public class PPTX2PNG {
|
|||
}
|
||||
}
|
||||
|
||||
private static Set<Integer> slideIndexes(final int slideCount, String range) {
|
||||
Set<Integer> slideIdx = new TreeSet<>();
|
||||
if ("-1".equals(range)) {
|
||||
for (int i=0; i<slideCount; i++) {
|
||||
slideIdx.add(i);
|
||||
private static MFProxy initProxy(File file) throws IOException {
|
||||
MFProxy proxy;
|
||||
final String fileName = file.getName().toLowerCase(Locale.ROOT);
|
||||
switch (fileName.contains(".") ? fileName.substring(fileName.lastIndexOf('.')) : "") {
|
||||
case ".emf":
|
||||
proxy = new EMFHandler();
|
||||
break;
|
||||
case ".wmf":
|
||||
proxy = new WMFHandler();
|
||||
break;
|
||||
default:
|
||||
proxy = new PPTHandler();
|
||||
break;
|
||||
}
|
||||
|
||||
proxy.parse(file);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
private interface MFProxy extends Closeable {
|
||||
void parse(File file) throws IOException;
|
||||
// boolean isEmpty();
|
||||
// void dumpRecords(Writer writer) throws IOException;
|
||||
// Iterable<HwmfEmbedded> getEmbeddings();
|
||||
Dimension2D getSize();
|
||||
|
||||
default void setSlideNo(int slideNo) {}
|
||||
|
||||
String getTitle();
|
||||
void draw(Graphics2D ctx);
|
||||
|
||||
default int getSlideCount() { return 1; }
|
||||
|
||||
default Set<Integer> slideIndexes(String range) {
|
||||
return Collections.singleton(1);
|
||||
}
|
||||
|
||||
GenericRecord getRoot();
|
||||
}
|
||||
|
||||
/** Handler for ppt and pptx files */
|
||||
private static class PPTHandler implements MFProxy {
|
||||
SlideShow<?,?> ppt;
|
||||
Slide<?,?> slide;
|
||||
|
||||
@Override
|
||||
public void parse(File file) throws IOException {
|
||||
ppt = SlideShowFactory.create(file, null, true);
|
||||
slide = ppt.getSlides().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension2D getSize() {
|
||||
return ppt.getPageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlideCount() {
|
||||
return ppt.getSlides().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSlideNo(int slideNo) {
|
||||
slide = ppt.getSlides().get(slideNo-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return slide.getTitle();
|
||||
}
|
||||
|
||||
private static final String RANGE_PATTERN = "(^|,)(?<from>\\d+)?(-(?<to>\\d+))?";
|
||||
|
||||
@Override
|
||||
public Set<Integer> slideIndexes(String range) {
|
||||
final Matcher matcher = Pattern.compile(RANGE_PATTERN).matcher(range);
|
||||
Spliterator<Matcher> sp = new AbstractSpliterator<Matcher>(range.length(), ORDERED|NONNULL){
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Matcher> action) {
|
||||
boolean b = matcher.find();
|
||||
if (b) {
|
||||
action.accept(matcher);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
return StreamSupport.stream(sp, false).
|
||||
flatMap(this::range).
|
||||
collect(Collectors.toCollection(TreeSet::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D ctx) {
|
||||
slide.draw(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (ppt != null) {
|
||||
ppt.close();
|
||||
}
|
||||
} else {
|
||||
for (String subrange : range.split(",")) {
|
||||
String[] idx = subrange.split("-");
|
||||
switch (idx.length) {
|
||||
default:
|
||||
case 0: break;
|
||||
case 1: {
|
||||
int subidx = Integer.parseInt(idx[0]);
|
||||
if (subrange.contains("-")) {
|
||||
int startIdx = subrange.startsWith("-") ? 0 : subidx;
|
||||
int endIdx = subrange.endsWith("-") ? slideCount : Math.min(subidx,slideCount);
|
||||
for (int i=Math.max(startIdx,1); i<endIdx; i++) {
|
||||
slideIdx.add(i-1);
|
||||
}
|
||||
} else {
|
||||
slideIdx.add(Math.max(subidx,1)-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
int startIdx = Math.min(Integer.parseInt(idx[0]), slideCount);
|
||||
int endIdx = Math.min(Integer.parseInt(idx[1]), slideCount);
|
||||
for (int i=Math.max(startIdx,1); i<endIdx; i++) {
|
||||
slideIdx.add(i-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericRecord getRoot() {
|
||||
return (ppt instanceof GenericRecord) ? (GenericRecord)ppt : null;
|
||||
}
|
||||
|
||||
private Stream<Integer> range(Matcher m) {
|
||||
final int slideCount = ppt.getSlides().size();
|
||||
String fromStr = m.group("from");
|
||||
String toStr = m.group("to");
|
||||
int from = (fromStr == null || fromStr.isEmpty() ? 1 : Integer.parseInt(fromStr));
|
||||
int to = (toStr == null) ? from
|
||||
: (toStr.isEmpty() || ((fromStr == null || fromStr.isEmpty()) && "1".equals(toStr))) ? slideCount
|
||||
: Integer.parseInt(toStr);
|
||||
return IntStream.rangeClosed(from, to).filter(i -> i <= slideCount).boxed();
|
||||
}
|
||||
}
|
||||
|
||||
private static class EMFHandler implements MFProxy {
|
||||
private ImageRenderer imgr = null;
|
||||
private InputStream is;
|
||||
|
||||
@Override
|
||||
public void parse(File file) throws IOException {
|
||||
imgr = DrawPictureShape.getImageRenderer(null, getContentType());
|
||||
// stream needs to be kept open
|
||||
is = file.toURI().toURL().openStream();
|
||||
imgr.loadImage(is, getContentType());
|
||||
}
|
||||
|
||||
protected String getContentType() {
|
||||
return PictureData.PictureType.EMF.contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension2D getSize() {
|
||||
return imgr.getDimension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D ctx) {
|
||||
Dimension2D dim = getSize();
|
||||
imgr.drawImage(ctx, new Rectangle2D.Double(0, 0, dim.getWidth(), dim.getHeight()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} finally {
|
||||
is = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return slideIdx;
|
||||
|
||||
@Override
|
||||
public GenericRecord getRoot() {
|
||||
return imgr.getGenericRecord();
|
||||
}
|
||||
}
|
||||
|
||||
private static class WMFHandler extends EMFHandler {
|
||||
@Override
|
||||
protected String getContentType() {
|
||||
return PictureData.PictureType.WMF.contentType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public class TestPPTX2PNG {
|
|||
private static final String files =
|
||||
"53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, " +
|
||||
"backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx, 54880_chinese.ppt, keyframes.pptx," +
|
||||
"customGeo.pptx, customGeo.ppt";
|
||||
"customGeo.pptx, customGeo.ppt, wrench.emf, santa.wmf";
|
||||
|
||||
|
||||
|
||||
|
@ -83,8 +83,12 @@ public class TestPPTX2PNG {
|
|||
"-slide", "-1", // -1 for all
|
||||
"-outdir", new File("build/tmp/").getCanonicalPath(),
|
||||
"-outpat", "${basename}-${slideno}-${ext}.${format}",
|
||||
"-scale", "1.333333333",
|
||||
// "-dump", new File("build/tmp/", pptFile+".dump").getCanonicalPath(),
|
||||
"-dump", "null",
|
||||
"-quiet",
|
||||
"-fixside", "long",
|
||||
"-scale", "800",
|
||||
// "-scale", "1.333333333",
|
||||
(basedir == null ? samples.getFile(pptFile) : new File(basedir, pptFile)).getAbsolutePath()
|
||||
};
|
||||
PPTX2PNG.main(args);
|
||||
|
|
|
@ -24,11 +24,11 @@ import java.awt.RenderingHints;
|
|||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RescaleOp;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.usermodel.HemfPicture;
|
||||
import org.apache.poi.sl.draw.BitmapImageRenderer;
|
||||
import org.apache.poi.sl.draw.ImageRenderer;
|
||||
|
@ -109,4 +109,8 @@ public class HemfImageRenderer implements ImageRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericRecord getGenericRecord() {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,16 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusRecord;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusRecordIterator;
|
||||
import org.apache.poi.hwmf.usermodel.HwmfPicture;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
@ -78,10 +82,15 @@ public class HemfComment {
|
|||
}
|
||||
}
|
||||
|
||||
public interface EmfCommentData {
|
||||
public interface EmfCommentData extends GenericRecord {
|
||||
HemfCommentRecordType getCommentRecordType();
|
||||
|
||||
long init(LittleEndianInputStream leis, long dataSize) throws IOException;
|
||||
|
||||
@Override
|
||||
default Enum getGenericRecordType() {
|
||||
return getCommentRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfComment implements HemfRecord {
|
||||
|
@ -116,7 +125,12 @@ public class HemfComment {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ data: "+data+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("data", this::getCommentData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,7 +255,19 @@ public class HemfComment {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "\""+new String(privateData, LocaleUtil.CHARSET_1252).replaceAll("\\p{Cntrl}", ".")+"\"";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public String getPrivateDataAsString() {
|
||||
return new String(privateData, LocaleUtil.CHARSET_1252);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"privateData", this::getPrivateData,
|
||||
"privateDataAsString", this::getPrivateDataAsString
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,6 +297,16 @@ public class HemfComment {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
records.forEach(ctx::draw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HemfPlusRecord> getGenericChildren() {
|
||||
return getRecords();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfCommentDataBeginGroup implements EmfCommentData {
|
||||
|
@ -301,6 +337,22 @@ public class HemfComment {
|
|||
|
||||
return leis.getReadIndex()-startIdx;
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"bounds", this::getBounds,
|
||||
"description", this::getDescription
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfCommentDataEndGroup implements EmfCommentData {
|
||||
|
@ -319,6 +371,11 @@ public class HemfComment {
|
|||
assert(publicCommentIdentifier == HemfCommentRecordType.emfEndGroup.id);
|
||||
return leis.getReadIndex()-startIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfCommentDataMultiformats implements EmfCommentData {
|
||||
|
@ -369,6 +426,20 @@ public class HemfComment {
|
|||
public List<EmfCommentDataFormat> getFormats() {
|
||||
return Collections.unmodifiableList(formats);
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("bounds", this::getBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EmfCommentDataFormat> getGenericChildren() {
|
||||
return getFormats();
|
||||
}
|
||||
}
|
||||
|
||||
public enum EmfFormatSignature {
|
||||
|
@ -400,7 +471,7 @@ public class HemfComment {
|
|||
|
||||
}
|
||||
|
||||
public static class EmfCommentDataFormat {
|
||||
public static class EmfCommentDataFormat implements GenericRecord {
|
||||
private EmfFormatSignature signature;
|
||||
private int version;
|
||||
private int sizeData;
|
||||
|
@ -439,11 +510,20 @@ public class HemfComment {
|
|||
public EmfFormatSignature getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"signature", this::getSignature,
|
||||
"version", () -> version,
|
||||
"sizeData", () -> sizeData,
|
||||
"offData", () -> offData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfCommentDataWMF implements EmfCommentData {
|
||||
private final Rectangle2D bounds = new Rectangle2D.Double();
|
||||
private final List<EmfCommentDataFormat> formats = new ArrayList<>();
|
||||
private byte[] wmfData;
|
||||
@Override
|
||||
public HemfCommentRecordType getCommentRecordType() {
|
||||
|
@ -485,12 +565,21 @@ public class HemfComment {
|
|||
public byte[] getWMFData() {
|
||||
return wmfData;
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"bounds", this::getBounds,
|
||||
"wmfData", this::getWMFData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfCommentDataUnicode implements EmfCommentData {
|
||||
private final Rectangle2D bounds = new Rectangle2D.Double();
|
||||
private final List<EmfCommentDataFormat> formats = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public HemfCommentRecordType getCommentRecordType() {
|
||||
return HemfCommentRecordType.emfUnicodeString;
|
||||
|
@ -501,5 +590,10 @@ public class HemfComment {
|
|||
throws IOException {
|
||||
throw new RecordFormatException("UNICODE_STRING/UNICODE_END values are reserved in CommentPublic records");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
|
||||
package org.apache.poi.hemf.record.emf;
|
||||
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.normalizeBounds;
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Arc2D;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Path2D;
|
||||
|
@ -29,13 +28,17 @@ import java.awt.geom.PathIterator;
|
|||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics.FillDrawStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfDraw;
|
||||
import org.apache.poi.hwmf.record.HwmfDraw.WmfSelectObject;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
|
@ -47,26 +50,30 @@ public class HemfDraw {
|
|||
*/
|
||||
public static class EmfSelectObject extends WmfSelectObject implements HemfRecord {
|
||||
|
||||
private static final String[] STOCK_IDS = {
|
||||
"0x80000000 /* WHITE_BRUSH */",
|
||||
"0x80000001 /* LTGRAY_BRUSH */",
|
||||
"0x80000002 /* GRAY_BRUSH */",
|
||||
"0x80000003 /* DKGRAY_BRUSH */",
|
||||
"0x80000004 /* BLACK_BRUSH */",
|
||||
"0x80000005 /* NULL_BRUSH */",
|
||||
"0x80000006 /* WHITE_PEN */",
|
||||
"0x80000007 /* BLACK_PEN */",
|
||||
"0x80000008 /* NULL_PEN */",
|
||||
"0x8000000A /* OEM_FIXED_FONT */",
|
||||
"0x8000000B /* ANSI_FIXED_FONT */",
|
||||
"0x8000000C /* ANSI_VAR_FONT */",
|
||||
"0x8000000D /* SYSTEM_FONT */",
|
||||
"0x8000000E /* DEVICE_DEFAULT_FONT */",
|
||||
"0x8000000F /* DEFAULT_PALETTE */",
|
||||
"0x80000010 /* SYSTEM_FIXED_FONT */",
|
||||
"0x80000011 /* DEFAULT_GUI_FONT */",
|
||||
"0x80000012 /* DC_BRUSH */",
|
||||
"0x80000013 /* DC_PEN */"
|
||||
private static final int[] IDX_MASKS = IntStream.rangeClosed(0x80000000,0x80000013).toArray();
|
||||
|
||||
private static final String[] IDX_NAMES = {
|
||||
"WHITE_BRUSH",
|
||||
"LTGRAY_BRUSH",
|
||||
"GRAY_BRUSH",
|
||||
"DKGRAY_BRUSH",
|
||||
"BLACK_BRUSH",
|
||||
"NULL_BRUSH",
|
||||
"WHITE_PEN",
|
||||
"BLACK_PEN",
|
||||
"NULL_PEN",
|
||||
// 0x80000009 is not a valid stock object
|
||||
"INVALID",
|
||||
"OEM_FIXED_FONT",
|
||||
"ANSI_FIXED_FONT",
|
||||
"ANSI_VAR_FONT",
|
||||
"SYSTEM_FONT",
|
||||
"DEVICE_DEFAULT_FONT",
|
||||
"DEFAULT_PALETTE",
|
||||
"SYSTEM_FIXED_FONT",
|
||||
"DEFAULT_GUI_FONT",
|
||||
"DC_BRUSH",
|
||||
"DC_PEN"
|
||||
};
|
||||
|
||||
@Override
|
||||
|
@ -84,12 +91,20 @@ public class HemfDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ index: "+
|
||||
(((objectIndex & 0x80000000) != 0 && (objectIndex & 0x3FFFFFFF) <= 13 )
|
||||
? STOCK_IDS[objectIndex & 0x3FFFFFFF]
|
||||
: objectIndex)+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"objectIndex", getBitsAsString(this::getObjectIndex, IDX_MASKS, IDX_NAMES)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -183,6 +198,23 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(poly, !hasStartPoint()), getFillDrawStyle());
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -267,6 +299,23 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(poly, false), getFillDrawStyle());
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -429,10 +478,8 @@ public class HemfDraw {
|
|||
|
||||
Point2D pnt = new Point2D.Double();
|
||||
for (long nPoints : polygonPointCount) {
|
||||
/**
|
||||
* An array of WMF PointL objects that specifies the points for all polygons in logical units.
|
||||
* The number of points is specified by the Count field value.
|
||||
*/
|
||||
// An array of WMF PointL objects that specifies the points for all polygons in logical units.
|
||||
// The number of points is specified by the Count field value.
|
||||
Path2D poly = new Path2D.Double(Path2D.WIND_EVEN_ODD, (int)nPoints);
|
||||
for (int i=0; i<nPoints; i++) {
|
||||
size += readPoint(leis, pnt);
|
||||
|
@ -460,6 +507,23 @@ public class HemfDraw {
|
|||
|
||||
ctx.draw(path -> path.append(shape, false), getFillDrawStyle());
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -527,6 +591,11 @@ public class HemfDraw {
|
|||
size += colorRef.init(leis);
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -547,6 +616,11 @@ public class HemfDraw {
|
|||
public void draw(final HemfGraphics ctx) {
|
||||
ctx.draw((path) -> path.moveTo(point.getX(), point.getY()), FillDrawStyle.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -571,6 +645,11 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -596,6 +675,11 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -620,6 +704,11 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(getShape(), false), getFillDrawStyle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -642,6 +731,11 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(getShape(), false), FillDrawStyle.FILL_DRAW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -663,6 +757,11 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(normalizeBounds(bounds), false), FillDrawStyle.FILL_DRAW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -680,8 +779,9 @@ public class HemfDraw {
|
|||
long size = readRectL(leis, bounds);
|
||||
|
||||
// A 32-bit unsigned integer that defines the x-coordinate of the point.
|
||||
width = (int)leis.readUInt();
|
||||
height = (int)leis.readUInt();
|
||||
int width = (int)leis.readUInt();
|
||||
int height = (int)leis.readUInt();
|
||||
corners.setSize(width, height);
|
||||
|
||||
return size + 2*LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
@ -690,6 +790,11 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(getShape(), false), FillDrawStyle.FILL_DRAW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -711,6 +816,11 @@ public class HemfDraw {
|
|||
public void draw(final HemfGraphics ctx) {
|
||||
ctx.draw((path) -> path.lineTo(point.getX(), point.getY()), FillDrawStyle.DRAW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -736,6 +846,11 @@ public class HemfDraw {
|
|||
final Arc2D arc = getShape();
|
||||
ctx.draw((path) -> path.append(arc, true), getFillDrawStyle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/** The EMR_POLYDRAW record specifies a set of line segments and Bezier curves. */
|
||||
|
@ -829,6 +944,23 @@ public class HemfDraw {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.draw(path -> path.append(poly, false), getFillDrawStyle());
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPolyDraw16 extends EmfPolyDraw {
|
||||
|
@ -852,7 +984,7 @@ public class HemfDraw {
|
|||
* When an application processes the EMR_BEGINPATH record, all previous paths
|
||||
* MUST be discarded from the playback device context.
|
||||
*/
|
||||
public static class EmfBeginPath implements HemfRecord {
|
||||
public static class EmfBeginPath implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.beginPath;
|
||||
|
@ -880,7 +1012,7 @@ public class HemfDraw {
|
|||
* This record closes a path bracket and selects the path defined by the bracket into
|
||||
* the playback device context.
|
||||
*/
|
||||
public static class EmfEndPath implements HemfRecord {
|
||||
public static class EmfEndPath implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.endPath;
|
||||
|
@ -906,7 +1038,7 @@ public class HemfDraw {
|
|||
/**
|
||||
* This record aborts a path bracket or discards the path from a closed path bracket.
|
||||
*/
|
||||
public static class EmfAbortPath implements HemfRecord {
|
||||
public static class EmfAbortPath implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.abortPath;
|
||||
|
@ -949,7 +1081,7 @@ public class HemfDraw {
|
|||
* After processing the EMR_CLOSEFIGURE record, adding a line or curve to the path
|
||||
* MUST start a new figure.
|
||||
*/
|
||||
public static class EmfCloseFigure implements HemfRecord {
|
||||
public static class EmfCloseFigure implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.closeFigure;
|
||||
|
@ -980,7 +1112,7 @@ public class HemfDraw {
|
|||
* This record transforms any curves in the selected path into the playback device
|
||||
* context; each curve MUST be turned into a sequence of lines.
|
||||
*/
|
||||
public static class EmfFlattenPath implements HemfRecord {
|
||||
public static class EmfFlattenPath implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.flattenPath;
|
||||
|
@ -996,7 +1128,7 @@ public class HemfDraw {
|
|||
* This record redefines the current path as the area that would be painted if the path
|
||||
* were drawn using the pen currently selected into the playback device context.
|
||||
*/
|
||||
public static class EmfWidenPath implements HemfRecord {
|
||||
public static class EmfWidenPath implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.widenPath;
|
||||
|
@ -1040,7 +1172,16 @@ public class HemfDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return boundsToString(bounds);
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("bounds", this::getBounds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1155,16 +1296,4 @@ public class HemfDraw {
|
|||
|
||||
ctx.draw((path) -> path.append(pi, true), fillDrawStyle);
|
||||
}
|
||||
|
||||
|
||||
@Internal
|
||||
public static String xformToString(AffineTransform xForm) {
|
||||
return (xForm == null) ? "null" :
|
||||
"{ scaleX: "+xForm.getScaleX()+
|
||||
", shearX: "+xForm.getShearX()+
|
||||
", transX: "+xForm.getTranslateX()+
|
||||
", scaleY: "+xForm.getScaleY()+
|
||||
", shearY: "+xForm.getShearY()+
|
||||
", transY: "+xForm.getTranslateY()+" }";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,7 @@ package org.apache.poi.hemf.record.emf;
|
|||
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.readPointL;
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.readRectL;
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.xformToString;
|
||||
import static org.apache.poi.hemf.record.emf.HemfRecordIterator.HEADER_SIZE;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.pointToString;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
@ -33,7 +30,11 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
|
@ -45,6 +46,8 @@ import org.apache.poi.hwmf.record.HwmfFill;
|
|||
import org.apache.poi.hwmf.record.HwmfFill.ColorUsage;
|
||||
import org.apache.poi.hwmf.record.HwmfRegionMode;
|
||||
import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
@ -70,6 +73,11 @@ public class HemfFill {
|
|||
polyFillMode = HwmfPolyfillMode.valueOf((int)leis.readUInt());
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfExtFloodFill extends HwmfFill.WmfExtFloodFill implements HemfRecord {
|
||||
|
@ -85,9 +93,14 @@ public class HemfFill {
|
|||
size += colorRef.init(leis);
|
||||
// A 32-bit unsigned integer that specifies how to use the Color value to determine the area for
|
||||
// the flood fill operation. The value MUST be in the FloodFill enumeration
|
||||
mode = (int)leis.readUInt();
|
||||
mode = HwmfFloodFillMode.values()[(int)leis.readUInt()];
|
||||
return size + LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,11 +198,34 @@ public class HemfFill {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ bounds: "+boundsToString(bounds)+
|
||||
", xFormSrc: " + xformToString(xFormSrc) +
|
||||
", bkColorSrc: "+bkColorSrc+
|
||||
","+super.toString().substring(1);
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public AffineTransform getXFormSrc() {
|
||||
return xFormSrc;
|
||||
}
|
||||
|
||||
public HwmfColorRef getBkColorSrc() {
|
||||
return bkColorSrc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds,
|
||||
"xFormSrc", this::getXFormSrc,
|
||||
"bkColorSrc", this::getBkColorSrc
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,6 +295,23 @@ public class HemfFill {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -296,9 +349,10 @@ public class HemfFill {
|
|||
// A 32-bit unsigned integer that specifies the brush EMF Object Table index.
|
||||
brushIndex = (int)leis.readUInt();
|
||||
// A 32-bit signed integer that specifies the width of the vertical brush stroke, in logical units.
|
||||
width = leis.readInt();
|
||||
int width = leis.readInt();
|
||||
// A 32-bit signed integer that specifies the height of the horizontal brush stroke, in logical units.
|
||||
height = leis.readInt();
|
||||
int height = leis.readInt();
|
||||
frame.setSize(width,height);
|
||||
size += 4*LittleEndianConsts.INT_SIZE;
|
||||
size += readRgnData(leis, rgnRects);
|
||||
return size;
|
||||
|
@ -313,6 +367,28 @@ public class HemfFill {
|
|||
protected Shape getShape() {
|
||||
return getRgnShape(rgnRects);
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public List<Rectangle2D> getRgnRects() {
|
||||
return rgnRects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds,
|
||||
"rgnRects", this::getRgnRects
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/** The EMR_INVERTRGN record inverts the colors in the specified region. */
|
||||
|
@ -338,6 +414,22 @@ public class HemfFill {
|
|||
protected Shape getShape() {
|
||||
return getRgnShape(rgnRects);
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public List<Rectangle2D> getRgnRects() {
|
||||
return rgnRects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"bounds", this::getBounds,
|
||||
"rgnRects", this::getRgnRects
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -375,6 +467,28 @@ public class HemfFill {
|
|||
protected Shape getShape() {
|
||||
return getRgnShape(rgnRects);
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public List<Rectangle2D> getRgnRects() {
|
||||
return rgnRects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"bounds", this::getBounds,
|
||||
"rgnRects", this::getRgnRects
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfExtSelectClipRgn implements HemfRecord {
|
||||
|
@ -414,19 +528,23 @@ public class HemfFill {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("{ regionMode: '"+regionMode+"'");
|
||||
sb.append(", regions: [");
|
||||
boolean isFirst = true;
|
||||
for (Rectangle2D r : rgnRects) {
|
||||
if (!isFirst) {
|
||||
sb.append(",");
|
||||
}
|
||||
isFirst = false;
|
||||
sb.append(boundsToString(r));
|
||||
}
|
||||
sb.append("]}");
|
||||
return sb.toString();
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public HwmfRegionMode getRegionMode() {
|
||||
return regionMode;
|
||||
}
|
||||
|
||||
public List<Rectangle2D> getRgnRects() {
|
||||
return rgnRects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"regionMode", this::getRegionMode,
|
||||
"rgnRects", this::getRgnRects
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,6 +657,23 @@ public class HemfFill {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("bounds", () -> bounds);
|
||||
m.put("destRect", () -> destRect);
|
||||
m.put("srcRect", () -> srcRect);
|
||||
m.put("blendOperation", () -> blendOperation);
|
||||
m.put("blendFlags", () -> blendFlags);
|
||||
m.put("srcConstantAlpha", () -> srcConstantAlpha);
|
||||
m.put("alphaFormat", () -> alphaFormat);
|
||||
m.put("xFormSrc", () -> xFormSrc);
|
||||
m.put("bkColorSrc", () -> bkColorSrc);
|
||||
m.put("usageSrc", () -> usageSrc);
|
||||
m.put("bitmap", () -> bitmap);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -591,15 +726,40 @@ public class HemfFill {
|
|||
return size;
|
||||
}
|
||||
|
||||
public Rectangle2D getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public Point2D getDest() {
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Rectangle2D getSrc() {
|
||||
return src;
|
||||
}
|
||||
|
||||
public ColorUsage getUsageSrc() {
|
||||
return usageSrc;
|
||||
}
|
||||
|
||||
public HwmfBitmapDib getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ bounds: " + boundsToString(bounds) +
|
||||
", dest: " + pointToString(dest) +
|
||||
", src: " + boundsToString(src) +
|
||||
", usageSrc: '" + usageSrc + "'" +
|
||||
", bitmap: " + bitmap +
|
||||
"}";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"bounds", this::getBounds,
|
||||
"dest", this::getDest,
|
||||
"src", this::getSrc,
|
||||
"usageSrc", this::getUsageSrc,
|
||||
"bitmap", this::getBitmap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -670,9 +830,7 @@ public class HemfFill {
|
|||
|
||||
|
||||
static int readBounds2(LittleEndianInputStream leis, Rectangle2D bounds) {
|
||||
/**
|
||||
* The 32-bit signed integers that defines the corners of the bounding rectangle.
|
||||
*/
|
||||
// The 32-bit signed integers that defines the corners of the bounding rectangle.
|
||||
int x = leis.readInt();
|
||||
int y = leis.readInt();
|
||||
int w = leis.readInt();
|
||||
|
|
|
@ -19,10 +19,17 @@ package org.apache.poi.hemf.record.emf;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.common.usermodel.fonts.FontCharset;
|
||||
import org.apache.poi.hwmf.record.HwmfFont;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
|
@ -41,7 +48,7 @@ public class HemfFont extends HwmfFont {
|
|||
}
|
||||
}
|
||||
|
||||
protected static class LogFontPanose implements LogFontDetails {
|
||||
protected static class LogFontPanose implements LogFontDetails, GenericRecord {
|
||||
enum FamilyType {
|
||||
PAN_ANY,
|
||||
PAN_NO_FIT,
|
||||
|
@ -201,21 +208,26 @@ public class HemfFont extends HwmfFont {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ styleSize: " + styleSize +
|
||||
", vendorId: " + vendorId +
|
||||
", culture: " + culture +
|
||||
", familyType: '" + familyType + "'" +
|
||||
", serifStyle: '" + serifStyle + "'" +
|
||||
", weight: '" + weight + "'" +
|
||||
", proportion: '" + proportion + "'" +
|
||||
", contrast: '" + contrast + "'" +
|
||||
", strokeVariation: '" + strokeVariation + "'" +
|
||||
", armStyle: '" + armStyle + "'" +
|
||||
", letterform: '" + letterform + "'" +
|
||||
", midLine: '" + midLine + "'" +
|
||||
", xHeight: '" + xHeight + "'" +
|
||||
"}";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("styleSize", () -> styleSize);
|
||||
m.put("vendorId", () -> vendorId);
|
||||
m.put("culture", () -> culture);
|
||||
m.put("familyType", () -> familyType);
|
||||
m.put("serifStyle", () -> serifStyle);
|
||||
m.put("weight", () -> weight);
|
||||
m.put("proportion", () -> proportion);
|
||||
m.put("contrast", () -> contrast);
|
||||
m.put("strokeVariation", () -> strokeVariation);
|
||||
m.put("armStyle", () -> armStyle);
|
||||
m.put("letterform", () -> letterform);
|
||||
m.put("midLine", () -> midLine);
|
||||
m.put("xHeight", () -> xHeight);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,12 +478,18 @@ public class HemfFont extends HwmfFont {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ fullname: '" + (fullname == null ? "" : fullname) + "'" +
|
||||
", style: '" + (style == null ? "" : style) + "'" +
|
||||
", script: '" + (script == null ? "" : script) + "'" +
|
||||
", details: " + details +
|
||||
"," + super.toString().substring(1);
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"fullname", () -> fullname,
|
||||
"style", () -> style,
|
||||
"script", () -> script,
|
||||
"details", () -> details
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,15 +20,18 @@ package org.apache.poi.hemf.record.emf;
|
|||
import static org.apache.poi.hemf.record.emf.HemfDraw.readDimensionInt;
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.readRectL;
|
||||
import static org.apache.poi.hemf.record.emf.HemfRecordIterator.HEADER_SIZE;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.dimToString;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.Dimension2DDouble;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
@ -82,7 +85,7 @@ public class HemfHeader implements HemfRecord {
|
|||
|
||||
public String getDescription() { return description; }
|
||||
|
||||
public long getnPalEntries() {
|
||||
public long getNPalEntries() {
|
||||
return nPalEntries;
|
||||
}
|
||||
|
||||
|
@ -120,23 +123,7 @@ public class HemfHeader implements HemfRecord {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HemfHeader{" +
|
||||
"boundsRectangle: " + boundsToString(boundsRectangle) +
|
||||
", frameRectangle: " + boundsToString(frameRectangle) +
|
||||
", bytes: " + bytes +
|
||||
", records: " + records +
|
||||
", handles: " + handles +
|
||||
", description: '" + (description == null ? "" : description) + "'" +
|
||||
", nPalEntries: " + nPalEntries +
|
||||
", hasExtension1: " + hasExtension1 +
|
||||
", cbPixelFormat: " + cbPixelFormat +
|
||||
", offPixelFormat: " + offPixelFormat +
|
||||
", bOpenGL: " + bOpenGL +
|
||||
", hasExtension2: " + hasExtension2 +
|
||||
", deviceDimension: " + dimToString(deviceDimension) +
|
||||
", microDimension: " + dimToString(microDimension) +
|
||||
", milliDimension: " + dimToString(milliDimension) +
|
||||
'}';
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -204,4 +191,25 @@ public class HemfHeader implements HemfRecord {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("boundsRectangle", this::getBoundsRectangle);
|
||||
m.put("frameRectangle", this::getFrameRectangle);
|
||||
m.put("bytes", this::getBytes);
|
||||
m.put("records", this::getRecords);
|
||||
m.put("handles", this::getHandles);
|
||||
m.put("description", this::getDescription);
|
||||
m.put("nPalEntries", this::getNPalEntries);
|
||||
m.put("hasExtension1", this::isHasExtension1);
|
||||
m.put("cbPixelFormat", this::getCbPixelFormat);
|
||||
m.put("offPixelFormat", this::getOffPixelFormat);
|
||||
m.put("bOpenGL", this::getbOpenGL);
|
||||
m.put("hasExtension2", this::isHasExtension2);
|
||||
m.put("deviceDimension", this::getDeviceDimension);
|
||||
m.put("milliDimension", this::getMilliDimension);
|
||||
m.put("microDimension", this::getMicroDimension);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package org.apache.poi.hemf.record.emf;
|
||||
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.readPointL;
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.xformToString;
|
||||
import static org.apache.poi.hemf.record.emf.HemfFill.readBitmap;
|
||||
import static org.apache.poi.hemf.record.emf.HemfFill.readXForm;
|
||||
import static org.apache.poi.hemf.record.emf.HemfRecordIterator.HEADER_SIZE;
|
||||
|
@ -28,9 +27,10 @@ import java.awt.geom.Point2D;
|
|||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
|
@ -49,9 +49,12 @@ import org.apache.poi.hwmf.record.HwmfObjectTableEntry;
|
|||
import org.apache.poi.hwmf.record.HwmfPalette.PaletteEntry;
|
||||
import org.apache.poi.hwmf.record.HwmfPenStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfPenStyle.HwmfLineDash;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfMisc {
|
||||
|
||||
public enum HemfModifyWorldTransformMode {
|
||||
|
@ -138,12 +141,21 @@ public class HemfMisc {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
public List<PaletteEntry> getPalette() {
|
||||
return palette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("palette", this::getPalette);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The EMF_SAVEDC record saves the playback device context for later retrieval.
|
||||
*/
|
||||
public static class EmfSaveDc extends HwmfMisc.WmfSaveDc implements HemfRecord {
|
||||
public static class EmfSaveDc extends HwmfMisc.WmfSaveDc implements HemfRecordWithoutProperties {
|
||||
@Override
|
||||
public HemfRecordType getEmfRecordType() {
|
||||
return HemfRecordType.saveDc;
|
||||
|
@ -153,6 +165,11 @@ public class HemfMisc {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,6 +191,11 @@ public class HemfMisc {
|
|||
nSavedDC = leis.readInt();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -191,6 +213,11 @@ public class HemfMisc {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return colorRef.init(leis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,6 +240,11 @@ public class HemfMisc {
|
|||
bkMode = HwmfBkMode.valueOf((int) leis.readUInt());
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -228,6 +260,11 @@ public class HemfMisc {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return super.init(leis, recordSize, (int) recordId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,6 +283,11 @@ public class HemfMisc {
|
|||
mapMode = HwmfMapMode.valueOf((int) leis.readUInt());
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,6 +306,11 @@ public class HemfMisc {
|
|||
drawMode = HwmfBinaryRasterOp.valueOf((int) leis.readUInt());
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -284,6 +331,11 @@ public class HemfMisc {
|
|||
stretchBltMode = StretchBltMode.valueOf((int) leis.readUInt());
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -317,14 +369,26 @@ public class HemfMisc {
|
|||
ctx.addObjectTableEntry(this, brushIdx);
|
||||
}
|
||||
|
||||
public int getBrushIdx() {
|
||||
return brushIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ brushIndex: "+brushIdx+
|
||||
", brushStyle: '"+brushStyle+"'"+
|
||||
", colorRef: "+colorRef+
|
||||
", brushHatch: '"+brushHatch+"' }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"brushIdx", this::getBrushIdx
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,6 +443,22 @@ public class HemfMisc {
|
|||
ctx.addObjectTableEntry(this, brushIdx);
|
||||
}
|
||||
|
||||
public int getBrushIdx() {
|
||||
return brushIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"brushIdx", this::getBrushIdx
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -397,6 +477,11 @@ public class HemfMisc {
|
|||
objectIndex = (int) leis.readUInt();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -439,7 +524,24 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString().replaceFirst("\\{", "{ penIndex: "+penIndex+", ");
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public int getPenIndex() {
|
||||
return penIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"penIndex", this::getPenIndex
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,12 +641,34 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO: add style entries + bmp
|
||||
return
|
||||
"{ brushStyle: '"+brushStyle+"'"+
|
||||
", hatchStyle: '"+hatchStyle+"'"+
|
||||
", dashPattern: "+ Arrays.toString(penStyle.getLineDashes())+
|
||||
", "+super.toString().substring(1);
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public HwmfBrushStyle getBrushStyle() {
|
||||
return brushStyle;
|
||||
}
|
||||
|
||||
public HwmfHatchStyle getHatchStyle() {
|
||||
return hatchStyle;
|
||||
}
|
||||
|
||||
public HwmfBitmapDib getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"brushStyle", this::getBrushStyle,
|
||||
"hatchStyle", this::getHatchStyle,
|
||||
"bitmap", this::getBitmap
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -573,7 +697,16 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ miterLimit: "+miterLimit+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public int getMiterLimit() {
|
||||
return miterLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("miterLimit", this::getMiterLimit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,7 +726,16 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ x: "+origin.getX()+", y: "+origin.getY()+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public Point2D getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("origin", this::getOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +762,16 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ xForm: " + xformToString(xForm)+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public AffineTransform getXForm() {
|
||||
return xForm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("xForm", this::getXForm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -687,9 +838,23 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ xForm: " + xformToString(xForm) +
|
||||
", modifyWorldTransformMode: '"+modifyWorldTransformMode+"' }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public AffineTransform getXForm() {
|
||||
return xForm;
|
||||
}
|
||||
|
||||
public HemfModifyWorldTransformMode getModifyWorldTransformMode() {
|
||||
return modifyWorldTransformMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"xForm", this::getXForm,
|
||||
"modifyWorldTransformMode", this::getModifyWorldTransformMode
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -760,11 +925,28 @@ public class HemfMisc {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ penIndex: " + penIndex +
|
||||
", colorUsage: " + colorUsage +
|
||||
", bitmap: " + bitmap +
|
||||
"}";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public int getPenIndex() {
|
||||
return penIndex;
|
||||
}
|
||||
|
||||
public HwmfFill.ColorUsage getColorUsage() {
|
||||
return colorUsage;
|
||||
}
|
||||
|
||||
public HwmfBitmapDib getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"penIndex", this::getPenIndex,
|
||||
"colorUsage", this::getColorUsage,
|
||||
"bitmap", this::getBitmap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,16 @@
|
|||
package org.apache.poi.hemf.record.emf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hwmf.record.HwmfPalette;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfPalette {
|
||||
/** The EMR_SELECTPALETTE record specifies a logical palette for the playback device context. */
|
||||
public static class EmfSelectPalette extends HwmfPalette.WmfSelectPalette implements HemfRecord {
|
||||
|
@ -42,6 +46,11 @@ public class HemfPalette {
|
|||
paletteIndex = (int)leis.readUInt();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/** The EMR_CREATEPALETTE record defines a logical palette for graphics operations. */
|
||||
|
@ -73,6 +82,23 @@ public class HemfPalette {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.addObjectTableEntry(this, paletteIndex);
|
||||
}
|
||||
|
||||
public int getPaletteIndex() {
|
||||
return paletteIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"paletteIndex", this::getPaletteIndex
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,6 +130,23 @@ public class HemfPalette {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.addObjectTableEntry(this, paletteIndex);
|
||||
}
|
||||
|
||||
public int getPaletteIndex() {
|
||||
return paletteIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"paletteIndex", this::getPaletteIndex
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,6 +177,23 @@ public class HemfPalette {
|
|||
public void draw(HemfGraphics ctx) {
|
||||
ctx.addObjectTableEntry(this, paletteIndex);
|
||||
}
|
||||
|
||||
public int getPaletteIndex() {
|
||||
return paletteIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"paletteIndex", this::getPaletteIndex
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,6 +210,11 @@ public class HemfPalette {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -205,5 +270,14 @@ public class HemfPalette {
|
|||
icmMode = ICMMode.valueOf(leis.readInt());
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
public ICMMode getIcmMode() {
|
||||
return icmMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("icmMode", this::getIcmMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,17 @@ package org.apache.poi.hemf.record.emf;
|
|||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hwmf.record.HwmfRecord;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@Internal
|
||||
public interface HemfRecord {
|
||||
public interface HemfRecord extends GenericRecord {
|
||||
|
||||
HemfRecordType getEmfRecordType();
|
||||
|
||||
|
@ -58,4 +61,16 @@ public interface HemfRecord {
|
|||
* @param header the emf header
|
||||
*/
|
||||
default void setHeader(HemfHeader header) {}
|
||||
|
||||
@Override
|
||||
default Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
interface HemfRecordWithoutProperties extends HemfRecord {
|
||||
default Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,12 +27,16 @@ import java.awt.geom.Dimension2D;
|
|||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hwmf.draw.HwmfGraphics;
|
||||
import org.apache.poi.hwmf.record.HwmfText;
|
||||
import org.apache.poi.hwmf.record.HwmfText.WmfSetTextAlign;
|
||||
import org.apache.poi.util.Dimension2DDouble;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
@ -45,6 +49,7 @@ import org.apache.poi.util.RecordFormatException;
|
|||
* implemented at this point!
|
||||
*/
|
||||
@Internal
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfText {
|
||||
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
@ -181,7 +186,7 @@ public class HemfText {
|
|||
*
|
||||
* @param charset the charset to be used to decode the character bytes
|
||||
* @return text from this text element
|
||||
* @throws IOException
|
||||
* @throws IOException if the charset is not compatible to the underlying bytes
|
||||
*/
|
||||
public String getText(Charset charset) throws IOException {
|
||||
return super.getText(charset);
|
||||
|
@ -206,10 +211,21 @@ public class HemfText {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ graphicsMode: '"+graphicsMode+"'"+
|
||||
", scale: { w: "+scale.getWidth()+", h: "+scale.getHeight()+" },"+
|
||||
super.toString().substring(1);
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"boundsIgnored", () -> boundsIgnored,
|
||||
"graphicsMode", this::getGraphicsMode
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,15 +256,18 @@ public class HemfText {
|
|||
|
||||
@Override
|
||||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
/**
|
||||
* A 32-bit unsigned integer that specifies text alignment by using a mask of text alignment flags.
|
||||
* These are either WMF TextAlignmentMode Flags for text with a horizontal baseline,
|
||||
* or WMF VerticalTextAlignmentMode Flags for text with a vertical baseline.
|
||||
* Only one value can be chosen from those that affect horizontal and vertical alignment.
|
||||
*/
|
||||
// A 32-bit unsigned integer that specifies text alignment by using a mask of text alignment flags.
|
||||
// These are either WMF TextAlignmentMode Flags for text with a horizontal baseline,
|
||||
// or WMF VerticalTextAlignmentMode Flags for text with a vertical baseline.
|
||||
// Only one value can be chosen from those that affect horizontal and vertical alignment.
|
||||
textAlignmentMode = (int)leis.readUInt();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,6 +283,11 @@ public class HemfText {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return colorRef.init(leis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -297,7 +321,24 @@ public class HemfText {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ index: "+fontIdx+", font: "+font+" } ";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public int getFontIdx() {
|
||||
return fontIdx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"fontIdx", this::getFontIdx
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,7 +347,7 @@ public class HemfText {
|
|||
public int init(LittleEndianInputStream leis) {
|
||||
// A 32-bit unsigned integer that specifies how to use the rectangle specified in the Rectangle field.
|
||||
// This field can be a combination of more than one ExtTextOutOptions enumeration
|
||||
flag = (int)leis.readUInt();
|
||||
flags = (int)leis.readUInt();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,15 +21,21 @@ import static org.apache.poi.hemf.record.emf.HemfDraw.readDimensionInt;
|
|||
import static org.apache.poi.hemf.record.emf.HemfDraw.readPointL;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.normalizeBounds;
|
||||
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hwmf.record.HwmfRegionMode;
|
||||
import org.apache.poi.hwmf.record.HwmfWindowing;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfWindowing {
|
||||
|
||||
/**
|
||||
|
@ -45,6 +51,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return readDimensionInt(leis, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,6 +71,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return readPointL(leis, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,6 +91,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return readDimensionInt(leis, extents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,6 +111,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return readPointL(leis, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,6 +132,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return readPointL(leis, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,6 +153,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return HemfDraw.readRectL(leis, bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,6 +174,11 @@ public class HemfWindowing {
|
|||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
return HemfDraw.readRectL(leis, normalizeBounds(bounds));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,12 +193,12 @@ public class HemfWindowing {
|
|||
|
||||
@Override
|
||||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
double xNum = leis.readInt();
|
||||
double xDenom = leis.readInt();
|
||||
double yNum = leis.readInt();
|
||||
double yDenom = leis.readInt();
|
||||
scale.setSize(xNum / xDenom, yNum / yDenom);
|
||||
return 4*LittleEndianConsts.INT_SIZE;
|
||||
return readScale(leis, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,14 +214,12 @@ public class HemfWindowing {
|
|||
|
||||
@Override
|
||||
public long init(LittleEndianInputStream leis, long recordSize, long recordId) throws IOException {
|
||||
double xNum = leis.readInt();
|
||||
double xDenom = leis.readInt();
|
||||
double yNum = leis.readInt();
|
||||
double yDenom = leis.readInt();
|
||||
return readScale(leis, scale);
|
||||
}
|
||||
|
||||
scale.setSize(xNum / xDenom, yNum / yDenom);
|
||||
|
||||
return 4*LittleEndianConsts.INT_SIZE;
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return getEmfRecordType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,8 +252,25 @@ public class HemfWindowing {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ regionMode: '"+regionMode+"' }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public HwmfRegionMode getRegionMode() {
|
||||
return regionMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("regionMode", this::getRegionMode);
|
||||
}
|
||||
}
|
||||
|
||||
private static int readScale(LittleEndianInputStream leis, Dimension2D scale) {
|
||||
double xNum = leis.readInt();
|
||||
double xDenom = leis.readInt();
|
||||
double yNum = leis.readInt();
|
||||
double yDenom = leis.readInt();
|
||||
scale.setSize(xNum / xDenom, yNum / yDenom);
|
||||
return 4*LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ import org.apache.poi.util.Internal;
|
|||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@Internal
|
||||
public class UnimplementedHemfRecord implements HemfRecord {
|
||||
public class UnimplementedHemfRecord implements HemfRecordWithoutProperties {
|
||||
|
||||
private HemfRecordType recordType;
|
||||
|
||||
|
|
|
@ -17,26 +17,24 @@
|
|||
|
||||
package org.apache.poi.hemf.record.emfplus;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.xformToString;
|
||||
import static org.apache.poi.hemf.record.emf.HemfFill.readXForm;
|
||||
import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readARGB;
|
||||
import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readPointF;
|
||||
import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readRectF;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.pointToString;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
|
||||
|
@ -47,10 +45,10 @@ import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
|
|||
import org.apache.poi.hemf.record.emfplus.HemfPlusPath.EmfPlusPath;
|
||||
import org.apache.poi.hwmf.record.HwmfBrushStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfColorRef;
|
||||
import org.apache.poi.hwmf.record.HwmfDraw;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
|
@ -243,7 +241,7 @@ public class HemfPlusBrush {
|
|||
|
||||
}
|
||||
|
||||
public interface EmfPlusBrushData {
|
||||
public interface EmfPlusBrushData extends GenericRecord {
|
||||
/**
|
||||
* This flag is meaningful in EmfPlusPathGradientBrushData objects.
|
||||
*
|
||||
|
@ -343,9 +341,24 @@ public class HemfPlusBrush {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ brushType: '"+brushType+"'" +
|
||||
", brushData: "+brushData+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
public EmfPlusBrushData getBrushData() {
|
||||
return brushData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusBrushType getGenericRecordType() {
|
||||
return brushType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"graphicsVersion", this::getGraphicsVersion,
|
||||
"brushData", this::getBrushData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +379,17 @@ public class HemfPlusBrush {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{ solidColor: "+new HwmfColorRef(solidColor)+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EmfPlusBrushType.SOLID_COLOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("solidColor", () -> solidColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,10 +415,21 @@ public class HemfPlusBrush {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ style: '"+style+"'" +
|
||||
", foreColor: "+new HwmfColorRef(foreColor) +
|
||||
", backColor: "+new HwmfColorRef(backColor) + " }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EmfPlusBrushType.HATCH_FILL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"style", () -> style,
|
||||
"foreColor", () -> foreColor,
|
||||
"backColor", () -> backColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,23 +496,31 @@ public class HemfPlusBrush {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+dataFlags+
|
||||
", wrapMode: '"+wrapMode+"'"+
|
||||
", rect: "+boundsToString(rect)+
|
||||
", startColor: "+new HwmfColorRef(startColor)+
|
||||
", endColor: "+new HwmfColorRef(endColor)+
|
||||
", transform: "+xformToString(transform)+
|
||||
", positions: "+ Arrays.toString(positions)+
|
||||
", blendColors: "+ colorsToString(blendColors)+
|
||||
", positionsV: "+ Arrays.toString(positionsV)+
|
||||
", blendFactorsV: "+ Arrays.toString(blendFactorsV)+
|
||||
", positionsH: "+ Arrays.toString(positionsH)+
|
||||
", blendFactorsH: "+ Arrays.toString(blendFactorsH)+
|
||||
"}";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EmfPlusBrushType.LINEAR_GRADIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("flags", () -> dataFlags);
|
||||
m.put("wrapMode", () -> wrapMode);
|
||||
m.put("rect", () -> rect);
|
||||
m.put("startColor", () -> startColor);
|
||||
m.put("endColor", () -> endColor);
|
||||
m.put("transform", () -> transform);
|
||||
m.put("positions", () -> positions);
|
||||
m.put("blendColors", () -> blendColors);
|
||||
m.put("positionsV", () -> positionsV);
|
||||
m.put("blendFactorsV", () -> blendFactorsV);
|
||||
m.put("positionsH", () -> positionsH);
|
||||
m.put("blendFactorsH", () -> blendFactorsH);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
/** The EmfPlusPathGradientBrushData object specifies a path gradient for a graphics brush. */
|
||||
|
@ -593,22 +635,32 @@ public class HemfPlusBrush {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+dataFlags+
|
||||
", wrapMode: '"+wrapMode+"'"+
|
||||
", centerColor: "+new HwmfColorRef(centerColor)+
|
||||
", centerPoint: "+pointToString(centerPoint)+
|
||||
", surroundingColor: "+colorsToString(surroundingColor)+
|
||||
", boundaryPath: "+(boundaryPath == null ? "null" : boundaryPath)+
|
||||
", boundaryPoints: "+pointsToString(boundaryPoints)+
|
||||
", transform: "+xformToString(transform)+
|
||||
", positions: "+Arrays.toString(positions)+
|
||||
", blendColors: "+colorsToString(blendColors)+
|
||||
", blendFactorsH: "+Arrays.toString(blendFactorsH)+
|
||||
", focusScaleX: "+focusScaleX+
|
||||
", focusScaleY: "+focusScaleY+
|
||||
"}"
|
||||
;
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EmfPlusBrushType.PATH_GRADIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("flags", () -> dataFlags);
|
||||
m.put("wrapMode", () -> wrapMode);
|
||||
m.put("centerColor", () -> centerColor);
|
||||
m.put("centerPoint", () -> centerPoint);
|
||||
m.put("surroundingColor", () -> surroundingColor);
|
||||
m.put("boundaryPath", () -> boundaryPath);
|
||||
m.put("boundaryPoints", () -> boundaryPoints);
|
||||
m.put("transform", () -> transform);
|
||||
m.put("positions", () -> positions);
|
||||
m.put("blendColors", () -> blendColors);
|
||||
m.put("blendFactorsH", () -> blendFactorsH);
|
||||
m.put("focusScaleX", () -> focusScaleX);
|
||||
m.put("focusScaleY", () -> focusScaleY);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -652,12 +704,22 @@ public class HemfPlusBrush {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+dataFlags+
|
||||
", wrapMode: '"+wrapMode+"'"+
|
||||
", transform: "+xformToString(transform)+
|
||||
", image: "+image+
|
||||
"]";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return EmfPlusBrushType.TEXTURE_FILL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"dataFlags", () -> dataFlags,
|
||||
"wrapMode", () -> wrapMode,
|
||||
"transform", () -> transform,
|
||||
"image", () -> image
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,18 +758,4 @@ public class HemfPlusBrush {
|
|||
facs.accept(factors);
|
||||
return size + factors.length * LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public static String colorsToString(Color[] colors) {
|
||||
return (colors == null ? "null" :
|
||||
Stream.of(colors).map(HwmfColorRef::new).map(Object::toString).
|
||||
collect(joining(",", "{", "}")));
|
||||
}
|
||||
|
||||
@Internal
|
||||
public static String pointsToString(Point2D[] points) {
|
||||
return (points == null ? "null" :
|
||||
Stream.of(points).map(HwmfDraw::pointToString).
|
||||
collect(joining(",", "{", "}")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,7 @@
|
|||
|
||||
package org.apache.poi.hemf.record.emfplus;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
import static org.apache.poi.hemf.record.emf.HemfDraw.xformToString;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
|
||||
import static org.apache.poi.hwmf.record.HwmfDraw.pointToString;
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
@ -32,8 +29,12 @@ import java.awt.image.BufferedImage;
|
|||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.math3.linear.LUDecomposition;
|
||||
import org.apache.commons.math3.linear.MatrixUtils;
|
||||
|
@ -46,16 +47,18 @@ import org.apache.poi.hemf.record.emfplus.HemfPlusMisc.EmfPlusObjectId;
|
|||
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObject;
|
||||
import org.apache.poi.hwmf.record.HwmfBrushStyle;
|
||||
import org.apache.poi.hwmf.record.HwmfColorRef;
|
||||
import org.apache.poi.hwmf.record.HwmfDraw;
|
||||
import org.apache.poi.hwmf.record.HwmfMisc.WmfSetBkMode.HwmfBkMode;
|
||||
import org.apache.poi.hwmf.record.HwmfTernaryRasterOp;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfPlusDraw {
|
||||
private static final int MAX_OBJECT_SIZE = 1_000_000;
|
||||
|
||||
|
@ -185,6 +188,10 @@ public class HemfPlusDraw {
|
|||
return flags;
|
||||
}
|
||||
|
||||
public int getPenId() {
|
||||
return penId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
|
||||
this.flags = flags;
|
||||
|
@ -213,9 +220,20 @@ public class HemfPlusDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+flags+
|
||||
", penId: "+penId+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HemfPlusRecordType getGenericRecordType() {
|
||||
return getEmfPlusRecordType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"penId", this::getPenId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,11 +296,25 @@ public class HemfPlusDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+flags+
|
||||
", brushId: "+brushId+
|
||||
", rectData: "+rectData.stream().map(HwmfDraw::boundsToString).collect(joining(",", "{", "}"))+
|
||||
"}";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HemfPlusRecordType getGenericRecordType() {
|
||||
return getEmfPlusRecordType();
|
||||
}
|
||||
|
||||
public List<Rectangle2D> getRectData() {
|
||||
return rectData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"brushId", this::getBrushId,
|
||||
"rectData", this::getRectData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,17 +460,21 @@ public class HemfPlusDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+flags+
|
||||
", imageAttributesID: "+imageAttributesID+
|
||||
", srcUnit: '"+srcUnit+"'"+
|
||||
", srcRect: "+boundsToString(srcRect)+
|
||||
", upperLeft: "+pointToString(upperLeft)+
|
||||
", lowerLeft: "+pointToString(lowerLeft)+
|
||||
", lowerRight: "+pointToString(lowerRight)+
|
||||
", transform: "+xformToString(trans)+
|
||||
"}"
|
||||
;
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("flags", this::getFlags);
|
||||
m.put("imageAttributesID", () -> imageAttributesID);
|
||||
m.put("srcUnit", () -> srcUnit);
|
||||
m.put("srcRect", () -> srcRect);
|
||||
m.put("upperLeft", () -> upperLeft);
|
||||
m.put("lowerLeft", () -> lowerLeft);
|
||||
m.put("lowerRight", () -> lowerRight);
|
||||
m.put("transform", () -> trans);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,14 +536,18 @@ public class HemfPlusDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+flags+
|
||||
", imageAttributesID: "+imageAttributesID+
|
||||
", srcUnit: '"+srcUnit+"'"+
|
||||
", srcRect: "+boundsToString(srcRect)+
|
||||
", rectData: "+boundsToString(rectData)+
|
||||
"}"
|
||||
;
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"imageAttributesID", () -> imageAttributesID,
|
||||
"srcUnit", () -> srcUnit,
|
||||
"srcRect", () -> srcRect,
|
||||
"rectData", () -> rectData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,9 +594,15 @@ public class HemfPlusDraw {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return
|
||||
"{ flags: "+flags+
|
||||
", brushId: "+brushId+" }";
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"brushId", () -> brushId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,7 +642,11 @@ public class HemfPlusDraw {
|
|||
*/
|
||||
private static final BitField LIMIT_SUBPIXEL = BitFieldFactory.getInstance(0x0008);
|
||||
|
||||
private static final int[] OPTIONS_MASK = { 0x0001, 0x0002, 0x0004, 0x0008 };
|
||||
|
||||
private static final String[] OPTIONS_NAMES = {
|
||||
"CMAP_LOOKUP", "VERTICAL", "REALIZED_ADVANCE", "LIMIT_SUBPIXEL"
|
||||
};
|
||||
|
||||
private int flags;
|
||||
private int brushId;
|
||||
|
@ -671,6 +721,23 @@ public class HemfPlusDraw {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"brushId", this::getBrushId,
|
||||
"optionsFlags", getBitsAsString(() -> optionsFlags, OPTIONS_MASK, OPTIONS_NAMES),
|
||||
"glyphs", () -> glyphs,
|
||||
"glyphPos", () -> glpyhPos,
|
||||
"transform", () -> transformMatrix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** The EmfPlusDrawRects record specifies drawing a series of rectangles. */
|
||||
|
@ -705,6 +772,19 @@ public class HemfPlusDraw {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"rectData", () -> rectData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,13 +19,18 @@ package org.apache.poi.hemf.record.emfplus;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusDraw.EmfPlusUnitType;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
@ -69,7 +74,7 @@ public class HemfPlusFont {
|
|||
private String family;
|
||||
|
||||
@Override
|
||||
public long init(LittleEndianInputStream leis, long dataSize, HemfPlusObject.EmfPlusObjectType objectType, int flags) throws IOException {
|
||||
public long init(LittleEndianInputStream leis, long dataSize, EmfPlusObjectType objectType, int flags) throws IOException {
|
||||
// An EmfPlusGraphicsVersion object that specifies the version of operating system graphics that was used
|
||||
// to create this object.
|
||||
long size = graphicsVersion.init(leis);
|
||||
|
@ -108,5 +113,26 @@ public class HemfPlusFont {
|
|||
public EmfPlusGraphicsVersion getGraphicsVersion() {
|
||||
return graphicsVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"graphicsVersion", () -> graphicsVersion,
|
||||
"emSize", () -> emSize,
|
||||
"sizeUnit", () -> sizeUnit,
|
||||
"styleFlags", () -> styleFlags,
|
||||
"family", () -> family
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return EmfPlusObjectType.FONT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,12 +18,18 @@
|
|||
package org.apache.poi.hemf.record.emfplus;
|
||||
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics.EmfRenderState;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
@ -53,6 +59,8 @@ public class HemfPlusHeader implements HemfPlusRecord {
|
|||
}
|
||||
}
|
||||
|
||||
private static final int[] FLAGS_MASK = { 0x0001 };
|
||||
private static final String[] FLAGS_NAMES = { "DUAL_MODE" };
|
||||
|
||||
private int flags;
|
||||
private final EmfPlusGraphicsVersion version = new EmfPlusGraphicsVersion();
|
||||
|
@ -121,13 +129,18 @@ public class HemfPlusHeader implements HemfPlusRecord {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HemfPlusHeader{" +
|
||||
"flags=" + flags +
|
||||
", version=" + version +
|
||||
", emfPlusFlags=" + emfPlusFlags +
|
||||
", logicalDpiX=" + logicalDpiX +
|
||||
", logicalDpiY=" + logicalDpiY +
|
||||
'}';
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"version", this::getVersion,
|
||||
"emfPlusFlags", getBitsAsString(this::getEmfPlusFlags, FLAGS_MASK, FLAGS_NAMES),
|
||||
"logicalDpiX", this::getLogicalDpiX,
|
||||
"logicalDpiY", this::getLogicalDpiY
|
||||
);
|
||||
}
|
||||
|
||||
public static class EmfPlusGraphicsVersion {
|
||||
|
|
|
@ -36,8 +36,12 @@ import java.awt.image.WritableRaster;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
@ -50,6 +54,8 @@ import org.apache.poi.hemf.usermodel.HemfPicture;
|
|||
import org.apache.poi.hwmf.usermodel.HwmfPicture;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordJsonWriter;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
@ -280,7 +286,6 @@ public class HemfPlusImage {
|
|||
public static class EmfPlusImage implements EmfPlusObjectData {
|
||||
private static final int MAX_OBJECT_SIZE = 50_000_000;
|
||||
|
||||
|
||||
private final EmfPlusGraphicsVersion graphicsVersion = new EmfPlusGraphicsVersion();
|
||||
private EmfPlusImageDataType imageDataType;
|
||||
private int bitmapWidth;
|
||||
|
@ -595,10 +600,36 @@ public class HemfPlusImage {
|
|||
|
||||
return bufImg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return EmfPlusObjectType.IMAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
|
||||
m.put("graphicsVersion", this::getGraphicsVersion);
|
||||
m.put("imageDataType", this::getImageDataType);
|
||||
m.put("bitmapWidth", this::getBitmapWidth);
|
||||
m.put("bitmapHeight", this::getBitmapHeight);
|
||||
m.put("bitmapStride", this::getBitmapStride);
|
||||
m.put("pixelFormat", this::getPixelFormat);
|
||||
m.put("bitmapType", this::getBitmapType);
|
||||
m.put("imageData", this::getImageData);
|
||||
m.put("metafileType", this::getMetafileType);
|
||||
m.put("metafileDataSize", () -> metafileDataSize);
|
||||
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class EmfPlusImageAttributes implements EmfPlusObjectData {
|
||||
private final EmfPlusGraphicsVersion graphicsVersion = new EmfPlusGraphicsVersion();
|
||||
private EmfPlusWrapMode wrapMode;
|
||||
|
@ -650,6 +681,26 @@ public class HemfPlusImage {
|
|||
@Override
|
||||
public void applyObject(HemfGraphics ctx, List<? extends EmfPlusObjectData> continuedObjectData) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return GenericRecordJsonWriter.marshal(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"graphicsVersion", this::getGraphicsVersion,
|
||||
"wrapMode", this::getWrapMode,
|
||||
"clampColor", this::getClampColor,
|
||||
"objectClamp", this::getObjectClamp
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return EmfPlusObjectType.IMAGE_ATTRIBUTES;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,19 +19,24 @@ package org.apache.poi.hemf.record.emfplus;
|
|||
|
||||
import static org.apache.poi.hemf.record.emf.HemfMisc.adaptXForm;
|
||||
import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readRectF;
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emf.HemfFill;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfPlusMisc {
|
||||
public interface EmfPlusObjectId {
|
||||
BitField OBJECT_ID = BitFieldFactory.getInstance(0x00FF);
|
||||
|
@ -75,6 +80,9 @@ public class HemfPlusMisc {
|
|||
private int flags;
|
||||
private HemfPlusRecordType recordType;
|
||||
|
||||
private static final int[] FLAGS_MASK = { 0x0F00 };
|
||||
private static final String[] FLAGS_NAMES = { "COMBINE_MODE" };
|
||||
|
||||
@Override
|
||||
public int getFlags() {
|
||||
return flags;
|
||||
|
@ -92,6 +100,18 @@ public class HemfPlusMisc {
|
|||
recordType = HemfPlusRecordType.getById(recordId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HemfPlusRecordType getGenericRecordType() {
|
||||
return getEmfPlusRecordType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", getBitsAsString(this::getFlags,FLAGS_MASK,FLAGS_NAMES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPlusEOF extends EmfPlusFlagOnly {
|
||||
|
@ -193,6 +213,14 @@ public class HemfPlusMisc {
|
|||
tx.concatenate(getMatrixData());
|
||||
ctx.setTransform(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"matrixData", this::getMatrixData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,6 +267,18 @@ public class HemfPlusMisc {
|
|||
pageScale = leis.readFloat();
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
public double getPageScale() {
|
||||
return pageScale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"pageScale", this::getPageScale
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,6 +304,9 @@ public class HemfPlusMisc {
|
|||
public static class EmfPlusSetClipRect implements HemfPlusRecord {
|
||||
private static final BitField COMBINE_MODE = BitFieldFactory.getInstance(0x0F00);
|
||||
|
||||
private static final int[] FLAGS_MASK = { 0x0F00 };
|
||||
private static final String[] FLAGS_NAMES = { "COMBINE_MODE" };
|
||||
|
||||
private int flags;
|
||||
private final Rectangle2D clipRect = new Rectangle2D.Double();
|
||||
|
||||
|
@ -288,6 +331,18 @@ public class HemfPlusMisc {
|
|||
// An EmfPlusRectF object that defines the rectangle to use in the CombineMode operation.
|
||||
return readRectF(leis, clipRect);
|
||||
}
|
||||
|
||||
public Rectangle2D getClipRect() {
|
||||
return clipRect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", getBitsAsString(this::getFlags, FLAGS_MASK, FLAGS_NAMES),
|
||||
"clipRect", this::getClipRect
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -314,6 +369,10 @@ public class HemfPlusMisc {
|
|||
return flags;
|
||||
}
|
||||
|
||||
public int getStackIndex() {
|
||||
return stackIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
|
||||
this.flags = flags;
|
||||
|
@ -324,6 +383,14 @@ public class HemfPlusMisc {
|
|||
|
||||
return LittleEndianConsts.INT_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"stackIndex", this::getStackIndex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -369,6 +436,14 @@ public class HemfPlusMisc {
|
|||
|
||||
return LittleEndianConsts.INT_SIZE*2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"origin", this::getOrigin
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,11 +17,15 @@
|
|||
|
||||
package org.apache.poi.hemf.record.emfplus;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusBrush.EmfPlusBrush;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusFont.EmfPlusFont;
|
||||
|
@ -36,6 +40,7 @@ import org.apache.poi.hwmf.draw.HwmfGraphics;
|
|||
import org.apache.poi.hwmf.record.HwmfObjectTableEntry;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
@ -113,8 +118,6 @@ public class HemfPlusObject {
|
|||
* can span multiple records), which is indicated by the value of the Flags field.
|
||||
*/
|
||||
public static class EmfPlusObject implements HemfPlusRecord, EmfPlusObjectId, HwmfObjectTableEntry {
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that the object definition continues on in the next EmfPlusObject
|
||||
* record. This flag is never set in the final record that defines the object.
|
||||
|
@ -127,6 +130,10 @@ public class HemfPlusObject {
|
|||
*/
|
||||
private static final BitField OBJECT_TYPE = BitFieldFactory.getInstance(0x7F00);
|
||||
|
||||
private static final int[] FLAGS_MASKS = { 0x7F00, 0x8000 };
|
||||
|
||||
private static final String[] FLAGS_NAMES = { "OBJECT_TYPE", "CONTINUABLE" };
|
||||
|
||||
private int flags;
|
||||
// for debugging
|
||||
private int objectId;
|
||||
|
@ -211,9 +218,20 @@ public class HemfPlusObject {
|
|||
List<EmfPlusObjectData> getContinuedObject() {
|
||||
return continuedObjectData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", getBitsAsString(this::getFlags, FLAGS_MASKS, FLAGS_NAMES),
|
||||
"objectId", this::getObjectId,
|
||||
"continuedObjectData", this::getContinuedObject,
|
||||
"totalObjectSize", () -> totalObjectSize
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface EmfPlusObjectData {
|
||||
public interface EmfPlusObjectData extends GenericRecord {
|
||||
long init(LittleEndianInputStream leis, long dataSize, EmfPlusObjectType objectType, int flags) throws IOException;
|
||||
|
||||
void applyObject(HemfGraphics ctx, List<? extends EmfPlusObjectData> continuedObjectData);
|
||||
|
@ -251,5 +269,18 @@ public class HemfPlusObject {
|
|||
public EmfPlusGraphicsVersion getGraphicsVersion() {
|
||||
return graphicsVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return objectType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"graphicsVersion", this::getGraphicsVersion,
|
||||
"objectDataBytes", () -> objectDataBytes
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,20 @@
|
|||
|
||||
package org.apache.poi.hemf.record.emfplus;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusDraw.EmfPlusCompressed;
|
||||
|
@ -32,6 +39,7 @@ import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
|
|||
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
|
||||
import org.apache.poi.util.BitField;
|
||||
import org.apache.poi.util.BitFieldFactory;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
|
@ -73,6 +81,12 @@ public class HemfPlusPath {
|
|||
|
||||
private static final BitField POINT_RLE_COUNT = BitFieldFactory.getInstance(0x3F);
|
||||
|
||||
private static final int[] FLAGS_MASKS = { 0x0800, 0x1000, 0x4000 };
|
||||
private static final String[] FLAGS_NAMES = { "RELATIVE_POSITION", "RLE_COMPRESSED", "FORMAT_COMPRESSED" };
|
||||
|
||||
private static final int[] TYPE_MASKS = { 0x10, 0x20, 0x80 };
|
||||
private static final String[] TYPE_NAMES = { "DASHED", "MARKER", "CLOSE" };
|
||||
|
||||
private final HemfPlusHeader.EmfPlusGraphicsVersion graphicsVersion = new HemfPlusHeader.EmfPlusGraphicsVersion();
|
||||
private int pointFlags;
|
||||
private Point2D[] pathPoints;
|
||||
|
@ -154,7 +168,9 @@ public class HemfPlusPath {
|
|||
return pointFlags;
|
||||
}
|
||||
|
||||
|
||||
public Point2D getPoint(int index) {
|
||||
return pathPoints[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyObject(HemfGraphics ctx, List<? extends EmfPlusObjectData> continuedObjectData) {
|
||||
|
@ -184,8 +200,32 @@ public class HemfPlusPath {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return EmfPlusObjectType.PATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"graphicsVersion", this::getGraphicsVersion,
|
||||
"flags", getBitsAsString(this::getFlags, FLAGS_MASKS, FLAGS_NAMES),
|
||||
"points", this::getGenericPoints
|
||||
);
|
||||
}
|
||||
|
||||
private List<GenericRecord> getGenericPoints() {
|
||||
return IntStream.range(0, pathPoints.length).
|
||||
mapToObj(this::getGenericPoint).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private GenericRecord getGenericPoint(final int idx) {
|
||||
return () -> GenericRecordUtil.getGenericProperties(
|
||||
"flags", getBitsAsString(() -> pointTypes[idx], TYPE_MASKS, TYPE_NAMES),
|
||||
"type", () -> getPointType(idx),
|
||||
"point", () -> getPoint(idx)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -19,13 +19,19 @@ package org.apache.poi.hemf.record.emfplus;
|
|||
|
||||
import static org.apache.poi.hemf.record.emf.HemfFill.readXForm;
|
||||
import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readPointF;
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusDraw.EmfPlusUnitType;
|
||||
|
@ -40,6 +46,7 @@ import org.apache.poi.util.Internal;
|
|||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class HemfPlusPen {
|
||||
/**
|
||||
* The LineCapType enumeration defines types of line caps to use at the ends of lines that are drawn
|
||||
|
@ -222,7 +229,7 @@ public class HemfPlusPen {
|
|||
|
||||
|
||||
@Internal
|
||||
public interface EmfPlusCustomLineCap {
|
||||
public interface EmfPlusCustomLineCap extends GenericRecord {
|
||||
long init(LittleEndianInputStream leis) throws IOException;
|
||||
}
|
||||
|
||||
|
@ -290,6 +297,18 @@ public class HemfPlusPen {
|
|||
*/
|
||||
private final static BitField CUSTOM_END_CAP = BitFieldFactory.getInstance(0x00001000);
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010,
|
||||
0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200,
|
||||
0x00000400, 0x00000800, 0x00001000
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"TRANSFORM", "START_CAP", "END_CAP", "JOIN", "MITER_LIMIT",
|
||||
"LINE_STYLE", "DASHED_LINE_CAP", "DASHED_LINE_OFFSET", "DASHED_LINE", "NON_CENTER",
|
||||
"COMPOUND_LINE", "CUSTOM_START_CAP", "CUSTOM_END_CAP"
|
||||
};
|
||||
|
||||
private final EmfPlusGraphicsVersion graphicsVersion = new EmfPlusGraphicsVersion();
|
||||
|
||||
|
||||
|
@ -528,6 +547,34 @@ public class HemfPlusPen {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return EmfPlusObjectType.PEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("type", () -> type);
|
||||
m.put("flags", getBitsAsString(() -> penDataFlags, FLAGS_MASKS, FLAGS_NAMES));
|
||||
m.put("unitType", () -> unitType);
|
||||
m.put("penWidth", () -> penWidth);
|
||||
m.put("trans", () -> trans);
|
||||
m.put("startCap", () -> startCap);
|
||||
m.put("endCap", () -> endCap);
|
||||
m.put("join", () -> join);
|
||||
m.put("miterLimit", () -> miterLimit);
|
||||
m.put("style", () -> style);
|
||||
m.put("dashedLineCapType", () -> dashedLineCapType);
|
||||
m.put("dashOffset", () -> dashOffset);
|
||||
m.put("dashedLineData", () -> dashedLineData);
|
||||
m.put("penAlignment", () -> penAlignment);
|
||||
m.put("compoundLineData", () -> compoundLineData);
|
||||
m.put("customStartCap", () -> customStartCap);
|
||||
m.put("customEndCap", () -> customEndCap);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPlusPathArrowCap implements EmfPlusCustomLineCap {
|
||||
|
@ -542,6 +589,9 @@ public class HemfPlusPen {
|
|||
*/
|
||||
private static final BitField LINE_PATH = BitFieldFactory.getInstance(0x00000002);
|
||||
|
||||
private static final int[] FLAGS_MASKS = { 0x00000001, 0x00000002 };
|
||||
|
||||
private static final String[] FLAGS_NAMES = { "FILL_PATH", "LINE_PATH" };
|
||||
|
||||
private int dataFlags;
|
||||
private EmfPlusLineCapType baseCap;
|
||||
|
@ -549,7 +599,7 @@ public class HemfPlusPen {
|
|||
private EmfPlusLineCapType startCap;
|
||||
private EmfPlusLineCapType endCap;
|
||||
private EmfPlusLineJoin join;
|
||||
private double mitterLimit;
|
||||
private double miterLimit;
|
||||
private double widthScale;
|
||||
private final Point2D fillHotSpot = new Point2D.Double();
|
||||
private final Point2D lineHotSpot = new Point2D.Double();
|
||||
|
@ -582,7 +632,7 @@ public class HemfPlusPen {
|
|||
|
||||
// A 32-bit floating-point value that contains the limit of the thickness of the join on a mitered corner
|
||||
// by setting the maximum allowed ratio of miter length to line width.
|
||||
mitterLimit = leis.readFloat();
|
||||
miterLimit = leis.readFloat();
|
||||
|
||||
// A 32-bit floating-point value that specifies the amount by which to scale the custom line cap with
|
||||
// respect to the width of the EmfPlusPen object that is used to draw the lines.
|
||||
|
@ -606,6 +656,24 @@ public class HemfPlusPen {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("flags", getBitsAsString(() -> dataFlags, FLAGS_MASKS, FLAGS_NAMES));
|
||||
m.put("baseCap", () -> baseCap);
|
||||
m.put("baseInset", () -> baseInset);
|
||||
m.put("startCap", () -> startCap);
|
||||
m.put("endCap", () -> endCap);
|
||||
m.put("join", () -> join);
|
||||
m.put("miterLimit", () -> miterLimit);
|
||||
m.put("widthScale", () -> widthScale);
|
||||
m.put("fillHotSpot", () -> fillHotSpot);
|
||||
m.put("lineHotSpot", () -> lineHotSpot);
|
||||
m.put("fillPath", () -> fillPath);
|
||||
m.put("outlinePath", () -> outlinePath);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPlusAdjustableArrowCap implements EmfPlusCustomLineCap {
|
||||
|
@ -616,7 +684,7 @@ public class HemfPlusPen {
|
|||
private EmfPlusLineCapType startCap;
|
||||
private EmfPlusLineCapType endCap;
|
||||
private EmfPlusLineJoin join;
|
||||
private double mitterLimit;
|
||||
private double miterLimit;
|
||||
private double widthScale;
|
||||
private final Point2D fillHotSpot = new Point2D.Double();
|
||||
private final Point2D lineHotSpot = new Point2D.Double();
|
||||
|
@ -655,7 +723,7 @@ public class HemfPlusPen {
|
|||
|
||||
// A 32-bit floating-point value that specifies the limit of the thickness of the join on a mitered
|
||||
// corner by setting the maximum allowed ratio of miter length to line width.
|
||||
mitterLimit = leis.readFloat();
|
||||
miterLimit = leis.readFloat();
|
||||
|
||||
// A 32-bit floating-point value that specifies the amount by which to scale an EmfPlusCustomLineCap
|
||||
// object with respect to the width of the graphics pen that is used to draw the lines.
|
||||
|
@ -671,5 +739,23 @@ public class HemfPlusPen {
|
|||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("width", () -> width);
|
||||
m.put("height", () -> height);
|
||||
m.put("middleInset", () -> middleInset);
|
||||
m.put("isFilled", () -> isFilled);
|
||||
m.put("startCap", () -> startCap);
|
||||
m.put("endCap", () -> endCap);
|
||||
m.put("join", () -> join);
|
||||
m.put("miterLimit", () -> miterLimit);
|
||||
m.put("widthScale", () -> widthScale);
|
||||
m.put("fillHotSpot", () -> fillHotSpot);
|
||||
m.put("lineHotSpot", () -> lineHotSpot);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,13 @@ package org.apache.poi.hemf.record.emfplus;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
@Internal
|
||||
public interface HemfPlusRecord {
|
||||
public interface HemfPlusRecord extends GenericRecord {
|
||||
|
||||
HemfPlusRecordType getEmfPlusRecordType();
|
||||
|
||||
|
|
|
@ -22,14 +22,17 @@ import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readRectF;
|
|||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusHeader.EmfPlusGraphicsVersion;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectData;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusObject.EmfPlusObjectType;
|
||||
import org.apache.poi.hemf.record.emfplus.HemfPlusPath.EmfPlusPath;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
||||
|
@ -122,10 +125,23 @@ public class HemfPlusRegion {
|
|||
public EmfPlusGraphicsVersion getGraphicsVersion() {
|
||||
return graphicsVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmfPlusObjectType getGenericRecordType() {
|
||||
return EmfPlusObjectType.REGION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"graphicsVersion", this::getGraphicsVersion,
|
||||
"regionNode", () -> regionNode
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface EmfPlusRegionNodeData {
|
||||
public interface EmfPlusRegionNodeData extends GenericRecord {
|
||||
long init(LittleEndianInputStream leis) throws IOException;
|
||||
}
|
||||
|
||||
|
@ -141,6 +157,11 @@ public class HemfPlusRegion {
|
|||
public long init(LittleEndianInputStream leis) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPlusRegionEmpty implements EmfPlusRegionNodeData {
|
||||
|
@ -148,6 +169,11 @@ public class HemfPlusRegion {
|
|||
public long init(LittleEndianInputStream leis) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPlusRegionRect implements EmfPlusRegionNodeData {
|
||||
|
@ -157,6 +183,11 @@ public class HemfPlusRegion {
|
|||
public long init(LittleEndianInputStream leis) {
|
||||
return readRectF(leis, rect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("rect", () -> rect);
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmfPlusRegionNode implements EmfPlusRegionNodeData {
|
||||
|
@ -168,8 +199,15 @@ public class HemfPlusRegion {
|
|||
size += readNode(leis, n -> right = n);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"left", () -> left,
|
||||
"right", () -> right
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static long readNode(LittleEndianInputStream leis, Consumer<EmfPlusRegionNodeData> con) throws IOException {
|
||||
// A 32-bit unsigned integer that specifies the type of data in the RegionNodeData field.
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.hemf.record.emfplus;
|
|||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
@ -56,4 +59,12 @@ public class UnimplementedHemfPlusRecord implements HemfPlusRecord {
|
|||
//should probably defensively return a copy.
|
||||
return recordBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"flags", this::getFlags,
|
||||
"recordBytes", () -> recordBytes
|
||||
);
|
||||
}
|
||||
}
|
|
@ -30,9 +30,12 @@ import java.io.InputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hemf.draw.HemfDrawProperties;
|
||||
import org.apache.poi.hemf.draw.HemfGraphics;
|
||||
import org.apache.poi.hemf.record.emf.HemfHeader;
|
||||
|
@ -49,7 +52,7 @@ import org.apache.poi.util.Units;
|
|||
* Read-only EMF extractor. Lots remain
|
||||
*/
|
||||
@Internal
|
||||
public class HemfPicture implements Iterable<HemfRecord> {
|
||||
public class HemfPicture implements Iterable<HemfRecord>, GenericRecord {
|
||||
private final LittleEndianInputStream stream;
|
||||
private final List<HemfRecord> records = new ArrayList<>();
|
||||
private boolean isParsed = false;
|
||||
|
@ -179,4 +182,14 @@ public class HemfPicture implements Iterable<HemfRecord> {
|
|||
public Iterable<HwmfEmbedded> getEmbeddings() {
|
||||
return () -> new HemfEmbeddedIterator(HemfPicture.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends GenericRecord> getGenericChildren() {
|
||||
return getRecords();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
|
@ -178,5 +184,13 @@ public abstract class BitMaskTextProp extends TextProp implements Cloneable {
|
|||
|
||||
public BitMaskTextProp cloneAll(){
|
||||
return (BitMaskTextProp)super.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"flags", getBitsAsString(this::getValue, subPropMasks, subPropNames)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.sl.usermodel.TextParagraph.FontAlign;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
/**
|
||||
* Definition for the font alignment property.
|
||||
*/
|
||||
|
@ -30,4 +36,27 @@ public class FontAlignmentProp extends TextProp {
|
|||
public FontAlignmentProp() {
|
||||
super(2, 0x10000, NAME);
|
||||
}
|
||||
|
||||
public FontAlign getFontAlign() {
|
||||
switch (getValue()) {
|
||||
default:
|
||||
return FontAlign.AUTO;
|
||||
case BASELINE:
|
||||
return FontAlign.BASELINE;
|
||||
case TOP:
|
||||
return FontAlign.TOP;
|
||||
case CENTER:
|
||||
return FontAlign.CENTER;
|
||||
case BOTTOM:
|
||||
return FontAlign.BOTTOM;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"fontAlign", this::getFontAlign
|
||||
);
|
||||
}
|
||||
}
|
|
@ -17,12 +17,17 @@
|
|||
|
||||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.sl.usermodel.TabStop;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.Units;
|
||||
|
||||
@Internal
|
||||
public class HSLFTabStop implements TabStop, Cloneable {
|
||||
public class HSLFTabStop implements TabStop, Cloneable, GenericRecord {
|
||||
/**
|
||||
* A signed integer that specifies an offset, in master units, of the tab stop.
|
||||
*
|
||||
|
@ -113,4 +118,12 @@ public class HSLFTabStop implements TabStop, Cloneable {
|
|||
public String toString() {
|
||||
return type + " @ " + position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"type", this::getType,
|
||||
"position", this::getPosition
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,11 @@ package org.apache.poi.hslf.model.textproperties;
|
|||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.sl.usermodel.TabStop.TabStopType;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
|
@ -150,5 +153,13 @@ public class HSLFTabStopPropCollection extends TextProp {
|
|||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"tabStops", this::getTabStops
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,12 @@
|
|||
|
||||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hslf.record.TxMasterStyleAtom;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
/**
|
||||
* Definition of the indent level of some text. Defines how many
|
||||
|
@ -25,7 +30,7 @@ import org.apache.poi.hslf.record.TxMasterStyleAtom;
|
|||
*
|
||||
* This is defined by the slightly confusingly named MasterTextPropRun
|
||||
*/
|
||||
public class IndentProp {
|
||||
public class IndentProp implements GenericRecord {
|
||||
private int charactersCovered;
|
||||
private short indentLevel;
|
||||
|
||||
|
@ -62,4 +67,12 @@ public class IndentProp {
|
|||
public void updateTextSize(int textSize) {
|
||||
charactersCovered = textSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"charactersCovered", this::getCharactersCovered,
|
||||
"indentLevel", this::getIndentLevel
|
||||
);
|
||||
}
|
||||
}
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
/**
|
||||
* Definition for the text alignment property.
|
||||
*/
|
||||
|
@ -63,4 +69,30 @@ public class TextAlignmentProp extends TextProp {
|
|||
public TextAlignmentProp() {
|
||||
super(2, 0x800, "alignment");
|
||||
}
|
||||
|
||||
public TextAlign getTextAlign() {
|
||||
switch (getValue()) {
|
||||
default:
|
||||
case LEFT:
|
||||
return TextAlign.LEFT;
|
||||
case CENTER:
|
||||
return TextAlign.CENTER;
|
||||
case RIGHT:
|
||||
return TextAlign.RIGHT;
|
||||
case JUSTIFY:
|
||||
return TextAlign.JUSTIFY;
|
||||
case DISTRIBUTED:
|
||||
return TextAlign.DIST;
|
||||
case THAIDISTRIBUTED:
|
||||
return TextAlign.THAI_DIST;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"textAlign", this::getTextAlign
|
||||
);
|
||||
}
|
||||
}
|
|
@ -21,7 +21,12 @@
|
|||
*/
|
||||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.sl.usermodel.AutoNumberingScheme;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +39,11 @@ import org.apache.poi.util.LittleEndian;
|
|||
* @author Alex Nikiforov [mailto:anikif@gmail.com]
|
||||
*
|
||||
*/
|
||||
public class TextPFException9 {
|
||||
public class TextPFException9 implements GenericRecord {
|
||||
|
||||
private final static AutoNumberingScheme DEFAULT_AUTONUMBER_SCHEME = AutoNumberingScheme.arabicPeriod;
|
||||
private final static Short DEFAULT_START_NUMBER = 1;
|
||||
|
||||
//private final byte mask1;
|
||||
//private final byte mask2;
|
||||
private final byte mask3;
|
||||
|
@ -42,9 +51,7 @@ public class TextPFException9 {
|
|||
private final Short bulletBlipRef;
|
||||
private final Short fBulletHasAutoNumber;
|
||||
private final AutoNumberingScheme autoNumberScheme;
|
||||
private final static AutoNumberingScheme DEFAULT_AUTONUMBER_SHEME = AutoNumberingScheme.arabicPeriod;
|
||||
private final Short autoNumberStartNumber;
|
||||
private final static Short DEFAULT_START_NUMBER = 1;
|
||||
private final int recordLength;
|
||||
public TextPFException9(final byte[] source, final int startIndex) { // NOSONAR
|
||||
//this.mask1 = source[startIndex];
|
||||
|
@ -86,23 +93,24 @@ public class TextPFException9 {
|
|||
return fBulletHasAutoNumber;
|
||||
}
|
||||
public AutoNumberingScheme getAutoNumberScheme() {
|
||||
if (null != this.autoNumberScheme) {
|
||||
return this.autoNumberScheme;
|
||||
if (autoNumberScheme != null) {
|
||||
return autoNumberScheme;
|
||||
}
|
||||
if (null != this.fBulletHasAutoNumber && 1 == this.fBulletHasAutoNumber.shortValue()) {
|
||||
return DEFAULT_AUTONUMBER_SHEME;
|
||||
}
|
||||
return null;
|
||||
return hasBulletAutoNumber() ? DEFAULT_AUTONUMBER_SCHEME : null;
|
||||
}
|
||||
|
||||
public Short getAutoNumberStartNumber() {
|
||||
if (null != this.autoNumberStartNumber) {
|
||||
return this.autoNumberStartNumber;
|
||||
if (autoNumberStartNumber != null) {
|
||||
return autoNumberStartNumber;
|
||||
}
|
||||
if (null != this.fBulletHasAutoNumber && 1 == this.fBulletHasAutoNumber.shortValue()) {
|
||||
return DEFAULT_START_NUMBER;
|
||||
}
|
||||
return null;
|
||||
return hasBulletAutoNumber() ? DEFAULT_START_NUMBER : null;
|
||||
}
|
||||
|
||||
private boolean hasBulletAutoNumber() {
|
||||
final Short one = 1;
|
||||
return one.equals(fBulletHasAutoNumber);
|
||||
}
|
||||
|
||||
public int getRecordLength() {
|
||||
return recordLength;
|
||||
}
|
||||
|
@ -115,4 +123,14 @@ public class TextPFException9 {
|
|||
sb.append("autoNumberStartNumber: ").append(this.autoNumberStartNumber).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"bulletBlipRef", this::getBulletBlipRef,
|
||||
"bulletHasAutoNumber", this::hasBulletAutoNumber,
|
||||
"autoNumberScheme", this::getAutoNumberScheme,
|
||||
"autoNumberStartNumber", this::getAutoNumberStartNumber
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
package org.apache.poi.hslf.model.textproperties;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
/**
|
||||
* Definition of a property of some text, or its paragraph. Defines
|
||||
|
@ -30,7 +35,7 @@ import java.util.Locale;
|
|||
* TxMasterTextProps, the definitions of the standard
|
||||
* TextProps is stored in the different record classes
|
||||
*/
|
||||
public class TextProp implements Cloneable {
|
||||
public class TextProp implements Cloneable, GenericRecord {
|
||||
private int sizeOfDataBlock; // Number of bytes the data part uses
|
||||
private String propName;
|
||||
private int dataValue;
|
||||
|
@ -152,4 +157,14 @@ public class TextProp implements Cloneable {
|
|||
}
|
||||
return String.format(Locale.ROOT, "%s = %d (%0#"+len+"X mask / %d bytes)", getName(), getValue(), getMask(), getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"sizeOfDataBlock", this::getSize,
|
||||
"propName", this::getName,
|
||||
"dataValue", this::getValue,
|
||||
"maskInHeader", this::getMask
|
||||
);
|
||||
}
|
||||
}
|
|
@ -21,10 +21,14 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.GenericRecord;
|
||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||
import org.apache.poi.hslf.record.StyleTextPropAtom;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
@ -38,7 +42,7 @@ import org.apache.poi.util.POILogger;
|
|||
* Used to hold the number of characters affected, the list of active
|
||||
* properties, and the indent level if required.
|
||||
*/
|
||||
public class TextPropCollection {
|
||||
public class TextPropCollection implements GenericRecord {
|
||||
private static final POILogger LOG = POILogFactory.getLogger(TextPropCollection.class);
|
||||
|
||||
/** All the different kinds of paragraph properties we might handle */
|
||||
|
@ -393,4 +397,15 @@ public class TextPropCollection {
|
|||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
Map<String,Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("charactersCovered", this::getCharactersCovered);
|
||||
m.put("indentLevel", this::getIndentLevel);
|
||||
textProps.forEach((s,t) -> m.put(s, () -> t));
|
||||
m.put("maskSpecial", this::getSpecialMask);
|
||||
m.put("textPropType", this::getTextPropType);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,14 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -36,35 +41,57 @@ public final class AnimationInfoAtom extends RecordAtom {
|
|||
/**
|
||||
* whether the animation plays in the reverse direction
|
||||
*/
|
||||
public static final int Reverse = 1;
|
||||
public static final int Reverse = 0x0001;
|
||||
/**
|
||||
* whether the animation starts automatically
|
||||
*/
|
||||
public static final int Automatic = 4;
|
||||
public static final int Automatic = 0x0004;
|
||||
/**
|
||||
* whether the animation has an associated sound
|
||||
*/
|
||||
public static final int Sound = 16;
|
||||
public static final int Sound = 0x0010;
|
||||
/**
|
||||
* whether all playing sounds are stopped when this animation begins
|
||||
*/
|
||||
public static final int StopSound = 64;
|
||||
public static final int StopSound = 0x0040;
|
||||
/**
|
||||
* whether an associated sound, media or action verb is activated when the shape is clicked.
|
||||
*/
|
||||
public static final int Play = 256;
|
||||
public static final int Play = 0x0100;
|
||||
/**
|
||||
* specifies that the animation, while playing, stops other slide show actions.
|
||||
*/
|
||||
public static final int Synchronous = 1024;
|
||||
public static final int Synchronous = 0x0400;
|
||||
/**
|
||||
* whether the shape is hidden while the animation is not playing
|
||||
*/
|
||||
public static final int Hide = 4096;
|
||||
public static final int Hide = 0x1000;
|
||||
/**
|
||||
* whether the background of the shape is animated
|
||||
*/
|
||||
public static final int AnimateBg = 16384;
|
||||
public static final int AnimateBg = 0x4000;
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
Reverse,
|
||||
Automatic,
|
||||
Sound,
|
||||
StopSound,
|
||||
Play,
|
||||
Synchronous,
|
||||
Hide,
|
||||
AnimateBg
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"REVERSE",
|
||||
"AUTOMATIC",
|
||||
"SOUND",
|
||||
"STOP_SOUND",
|
||||
"PLAY",
|
||||
"SYNCHRONOUS",
|
||||
"HIDE",
|
||||
"ANIMATE_BG"
|
||||
};
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
|
@ -275,4 +302,15 @@ public final class AnimationInfoAtom extends RecordAtom {
|
|||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"dimColor", this::getDimColor,
|
||||
"flags", getBitsAsString(this::getMask, FLAGS_MASKS, FLAGS_NAMES),
|
||||
"soundIdRef", this::getSoundIdRef,
|
||||
"delayTime", this::getDelayTime,
|
||||
"orderID", this::getOrderID,
|
||||
"slideCount", this::getSlideCount
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
@ -38,7 +41,6 @@ public final class CString extends RecordAtom {
|
|||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
||||
private byte[] _header;
|
||||
private static long _type = 4026l;
|
||||
|
||||
/** The bytes that make up the text */
|
||||
private byte[] _text;
|
||||
|
@ -104,7 +106,9 @@ public final class CString extends RecordAtom {
|
|||
/**
|
||||
* We are of type 4026
|
||||
*/
|
||||
public long getRecordType() { return _type; }
|
||||
public long getRecordType() {
|
||||
return RecordTypes.CString.typeID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the contents of the record back, so it can be written
|
||||
|
@ -125,4 +129,9 @@ public final class CString extends RecordAtom {
|
|||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("text", this::getText);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ package org.apache.poi.hslf.record;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
@ -217,4 +221,18 @@ public final class ColorSchemeAtom extends RecordAtom {
|
|||
fillsColourRGB, accentColourRGB, accentAndHyperlinkColourRGB, accentAndFollowingHyperlinkColourRGB};
|
||||
return clr[idx];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String, Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("backgroundColourRGB", this::getBackgroundColourRGB);
|
||||
m.put("textAndLinesColourRGB", this::getTextAndLinesColourRGB);
|
||||
m.put("shadowsColourRGB", this::getShadowsColourRGB);
|
||||
m.put("titleTextColourRGB", this::getTitleTextColourRGB);
|
||||
m.put("fillsColourRGB", this::getFillsColourRGB);
|
||||
m.put("accentColourRGB", this::getAccentColourRGB);
|
||||
m.put("accentAndHyperlinkColourRGB", this::getAccentAndHyperlinkColourRGB);
|
||||
m.put("accentAndFollowingHyperlinkColourRGB", this::getAccentAndFollowingHyperlinkColourRGB);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.apache.poi.util.POILogger;
|
|||
*/
|
||||
public final class Comment2000 extends RecordContainer {
|
||||
private byte[] _header;
|
||||
private static long _type = 12000;
|
||||
private static final long _type = RecordTypes.Comment2000.typeID;
|
||||
|
||||
// Links to our more interesting children
|
||||
|
||||
|
@ -172,5 +172,4 @@ public final class Comment2000 extends RecordContainer {
|
|||
public void writeOut(OutputStream out) throws IOException {
|
||||
writeOut(_header[0],_header[1],_type,_children,out);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,8 +20,11 @@ package org.apache.poi.hslf.record;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.hslf.util.SystemTimeUtils;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -158,4 +161,14 @@ public final class Comment2000Atom extends RecordAtom
|
|||
out.write(_header);
|
||||
out.write(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"number", this::getNumber,
|
||||
"date", this::getDate,
|
||||
"xOffset", this::getXOffset,
|
||||
"yOffset", this::getYOffset
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -27,7 +29,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
*/
|
||||
public final class DocInfoListContainer extends RecordContainer {
|
||||
private byte[] _header;
|
||||
private static long _type = RecordTypes.List.typeID;
|
||||
private static final long _type = RecordTypes.List.typeID;
|
||||
|
||||
// Links to our more interesting children
|
||||
|
||||
|
@ -81,4 +83,8 @@ public final class DocInfoListContainer extends RecordContainer {
|
|||
writeOut(_header[0],_header[1],_type,_children,out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,14 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||
import org.apache.poi.util.Removal;
|
||||
|
||||
/**
|
||||
* A Document Atom (type 1001). Holds misc information on the PowerPoint
|
||||
|
@ -29,11 +34,37 @@ import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
|||
*/
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public final class DocumentAtom extends RecordAtom
|
||||
{
|
||||
public final class DocumentAtom extends RecordAtom {
|
||||
|
||||
/**
|
||||
* Holds the different Slide Size values
|
||||
*/
|
||||
public enum SlideSize {
|
||||
/** Slide size ratio is consistent with a computer screen. */
|
||||
ON_SCREEN,
|
||||
/** Slide size ratio is consistent with letter paper. */
|
||||
LETTER_SIZED_PAPER,
|
||||
/** Slide size ratio is consistent with A4 paper. */
|
||||
A4_SIZED_PAPER,
|
||||
/** Slide size ratio is consistent with 35mm photo slides. */
|
||||
ON_35MM,
|
||||
/** Slide size ratio is consistent with overhead projector slides. */
|
||||
OVERHEAD,
|
||||
/** Slide size ratio is consistent with a banner. */
|
||||
BANNER,
|
||||
/**
|
||||
* Slide size ratio that is not consistent with any of the other specified slide sizes in
|
||||
* this enumeration.
|
||||
*/
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
||||
|
||||
|
||||
private final byte[] _header = new byte[8];
|
||||
private static long _type = RecordTypes.DocumentAtom.typeID;
|
||||
|
||||
|
@ -79,9 +110,22 @@ public final class DocumentAtom extends RecordAtom
|
|||
|
||||
public int getFirstSlideNum() { return firstSlideNum; }
|
||||
|
||||
/** The Size of the Document's slides, @see DocumentAtom.SlideSize for values */
|
||||
/**
|
||||
* The Size of the Document's slides, @see DocumentAtom.SlideSize for values
|
||||
* @deprecated to be replaced by enum
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version = "5.0.0")
|
||||
public int getSlideSizeType() { return slideSizeType; }
|
||||
|
||||
public SlideSize getSlideSizeTypeEnum() {
|
||||
return SlideSize.values()[slideSizeType];
|
||||
}
|
||||
|
||||
public void setSlideSize(SlideSize size) {
|
||||
slideSizeType = size.ordinal();
|
||||
}
|
||||
|
||||
/** Was the document saved with True Type fonts embeded? */
|
||||
public boolean getSaveWithFonts() {
|
||||
return saveWithFonts != 0;
|
||||
|
@ -191,16 +235,23 @@ public final class DocumentAtom extends RecordAtom
|
|||
out.write(reserved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds the different Slide Size values
|
||||
*/
|
||||
public static final class SlideSize {
|
||||
public static final int ON_SCREEN = 0;
|
||||
public static final int LETTER_SIZED_PAPER = 1;
|
||||
public static final int A4_SIZED_PAPER = 2;
|
||||
public static final int ON_35MM = 3;
|
||||
public static final int OVERHEAD = 4;
|
||||
public static final int BANNER = 5;
|
||||
public static final int CUSTOM = 6;
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
final Map<String, Supplier<?>> m = new LinkedHashMap<>();
|
||||
m.put("slideSizeX", this::getSlideSizeX);
|
||||
m.put("slideSizeY", this::getSlideSizeY);
|
||||
m.put("notesSizeX", this::getNotesSizeX);
|
||||
m.put("notesSizeY", this::getNotesSizeY);
|
||||
m.put("serverZoomFrom", this::getServerZoomFrom);
|
||||
m.put("serverZoomTo", this::getServerZoomTo);
|
||||
m.put("notesMasterPersist", this::getNotesMasterPersist);
|
||||
m.put("handoutMasterPersist", this::getHandoutMasterPersist);
|
||||
m.put("firstSlideNum", this::getFirstSlideNum);
|
||||
m.put("slideSize", this::getSlideSizeTypeEnum);
|
||||
m.put("saveWithFonts", this::getSaveWithFonts);
|
||||
m.put("omitTitlePlace", this::getOmitTitlePlace);
|
||||
m.put("rightToLeft", this::getRightToLeft);
|
||||
m.put("showComments", this::getShowComments);
|
||||
return Collections.unmodifiableMap(m);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.poifs.crypt.CipherAlgorithm;
|
||||
|
@ -29,6 +30,7 @@ import org.apache.poi.poifs.crypt.EncryptionMode;
|
|||
import org.apache.poi.poifs.crypt.HashAlgorithm;
|
||||
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
|
||||
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionVerifier;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||
import org.apache.poi.util.LittleEndianInputStream;
|
||||
|
@ -40,7 +42,7 @@ import org.apache.poi.util.LittleEndianInputStream;
|
|||
* @author Nick Burch
|
||||
*/
|
||||
public final class DocumentEncryptionAtom extends PositionDependentRecordAtom {
|
||||
private static final long _type = 12052l;
|
||||
private static final long _type = RecordTypes.DocumentEncryptionAtom.typeID;
|
||||
private final byte[] _header;
|
||||
private EncryptionInfo ei;
|
||||
|
||||
|
@ -132,4 +134,11 @@ public final class DocumentEncryptionAtom extends PositionDependentRecordAtom {
|
|||
public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) {
|
||||
// nothing to update
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"encryptionInfo", this::getEncryptionInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.EscherRecordFactory;
|
||||
import org.apache.poi.ddf.EscherSerializationListener;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
|
@ -77,6 +81,18 @@ public class EscherPlaceholder extends EscherRecord {
|
|||
return "ClientTextboxPlaceholder";
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public byte getPlacementId() {
|
||||
return placementId;
|
||||
}
|
||||
|
||||
public byte getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object[][] getAttributeMap() {
|
||||
return new Object[][] {
|
||||
|
@ -86,4 +102,19 @@ public class EscherPlaceholder extends EscherRecord {
|
|||
{ "unused", unused }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"base", super::getGenericProperties,
|
||||
"position", this::getPosition,
|
||||
"placementId", this::getPlacementId,
|
||||
"size", this::getSize
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getGenericRecordType() {
|
||||
return RecordTypes.OEPlaceholderAtom;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import org.apache.poi.ddf.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.ddf.EscherTextboxRecord;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
|
||||
/**
|
||||
* A wrapper around a DDF (Escher) EscherTextbox Record. Causes the DDF
|
||||
|
@ -118,4 +121,12 @@ public final class EscherTextboxWrapper extends RecordContainer {
|
|||
public StyleTextProp9Atom getStyleTextProp9Atom() {
|
||||
return this.styleTextProp9Atom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"shapeId", this::getShapeId,
|
||||
"escherRecord", this::getEscherRecord
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
|
@ -114,4 +117,8 @@ public final class ExControlAtom extends RecordAtom {
|
|||
out.write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("slideId", this::getSlideId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -166,4 +169,25 @@ public class ExEmbedAtom extends RecordAtom {
|
|||
out.write(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"followColorScheme", this::getFollowColorSchemeString,
|
||||
"cantLockServer", this::getCantLockServerB,
|
||||
"noSizeToServer", this::getNoSizeToServerB,
|
||||
"isTable", this::getIsTable
|
||||
);
|
||||
}
|
||||
|
||||
private String getFollowColorSchemeString() {
|
||||
switch (getFollowColorScheme()) {
|
||||
default:
|
||||
case DOES_NOT_FOLLOW_COLOR_SCHEME:
|
||||
return "DOES_NOT_FOLLOW_COLOR_SCHEME";
|
||||
case FOLLOWS_ENTIRE_COLOR_SCHEME:
|
||||
return "FOLLOWS_ENTIRE_COLOR_SCHEME";
|
||||
case FOLLOWS_TEXT_AND_BACKGROUND_SCHEME:
|
||||
return "FOLLOWS_TEXT_AND_BACKGROUND_SCHEME";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,10 @@ import org.apache.poi.util.POILogger;
|
|||
* @author Nick Burch
|
||||
*/
|
||||
public class ExHyperlink extends RecordContainer {
|
||||
private static final long _type = RecordTypes.ExHyperlink.typeID;
|
||||
|
||||
private byte[] _header;
|
||||
private static long _type = 4055;
|
||||
|
||||
|
||||
// Links to our more interesting children
|
||||
private ExHyperlinkAtom linkAtom;
|
||||
private CString linkDetailsA;
|
||||
|
|
|
@ -19,7 +19,10 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -114,4 +117,9 @@ public final class ExHyperlinkAtom extends RecordAtom {
|
|||
out.write(_header);
|
||||
out.write(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("number", this::getNumber);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,14 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -46,6 +51,12 @@ public final class ExMediaAtom extends RecordAtom
|
|||
*/
|
||||
public static final int fNarration = 4;
|
||||
|
||||
|
||||
private static final int[] FLAG_MASKS = { fLoop, fRewind, fNarration };
|
||||
|
||||
private static final String[] FLAG_NAMES = { "LOOP", "REWIND", "NARRATION" };
|
||||
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
|
@ -169,4 +180,11 @@ public final class ExMediaAtom extends RecordAtom
|
|||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"objectId", this::getObjectId,
|
||||
"flags", getBitsAsString(this::getMask, FLAG_MASKS, FLAG_NAMES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
*/
|
||||
public class ExObjList extends RecordContainer {
|
||||
private byte[] _header;
|
||||
private static long _type = 1033;
|
||||
private static final long _type = RecordTypes.ExObjList.typeID;
|
||||
|
||||
// Links to our more interesting children
|
||||
private ExObjListAtom exObjListAtom;
|
||||
|
|
|
@ -20,7 +20,10 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -116,4 +119,11 @@ public class ExObjListAtom extends RecordAtom
|
|||
out.write(_header);
|
||||
out.write(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"objectIDSeed", this::getObjectIDSeed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* ExObjRefAtom (3009).
|
||||
|
@ -91,4 +95,9 @@ public final class ExObjRefAtom extends RecordAtom {
|
|||
|
||||
out.write(recdata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("exObjIdRef", this::getExObjIdRef);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,16 +17,21 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
import static org.apache.poi.util.GenericRecordUtil.safeEnum;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Atom storing information for an OLE object.
|
||||
*
|
||||
* <!--
|
||||
* offset type name description
|
||||
*
|
||||
* 0 uint4 drawAspect Stores whether the object can be completely seen
|
||||
|
@ -60,12 +65,45 @@ import org.apache.poi.util.LittleEndian;
|
|||
*
|
||||
* 20 bool1 isBlank Set if the object's image is blank
|
||||
* (note: KOffice has this as an int.)
|
||||
* -->
|
||||
*
|
||||
* @author Daniel Noll
|
||||
*/
|
||||
public class ExOleObjAtom extends RecordAtom {
|
||||
|
||||
public enum OleType {
|
||||
/** An embedded OLE object; the object is serialized and saved within the file. */
|
||||
EMBEDDED,
|
||||
/** A linked OLE object; the object is saved outside of the file. */
|
||||
LINKED,
|
||||
/** The OLE object is an ActiveX control. */
|
||||
CONTROL
|
||||
}
|
||||
|
||||
public enum Subtype {
|
||||
DEFAULT,
|
||||
CLIPART_GALLERY,
|
||||
WORD_TABLE,
|
||||
EXCEL,
|
||||
GRAPH,
|
||||
ORGANIZATION_CHART,
|
||||
EQUATION,
|
||||
WORDART,
|
||||
SOUND,
|
||||
IMAGE,
|
||||
POWERPOINT_PRESENTATION,
|
||||
POWERPOINT_SLIDE,
|
||||
PROJECT,
|
||||
NOTEIT,
|
||||
EXCEL_CHART,
|
||||
MEDIA_PLAYER
|
||||
}
|
||||
|
||||
private static final int[] DRAWASPECT_MASKS = {
|
||||
0x0001, 0x0002, 0x0004, 0x0008
|
||||
};
|
||||
|
||||
private static final String[] DRAWASPECT_NAMES = {
|
||||
"CONTENT", "THUMBNAIL", "ICON", "DOCPRINT"
|
||||
};
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 10_485_760;
|
||||
|
||||
|
@ -314,4 +352,16 @@ public class ExOleObjAtom extends RecordAtom {
|
|||
buf.append(" options: " + getOptions() + "\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"drawAspect", getBitsAsString(this::getDrawAspect, DRAWASPECT_MASKS, DRAWASPECT_NAMES),
|
||||
"type", safeEnum(OleType.values(), this::getType),
|
||||
"objID", this::getObjID,
|
||||
"subType", safeEnum(Subtype.values(), this::getSubType),
|
||||
"objStgDataRef", this::getObjStgDataRef,
|
||||
"options", this::getOptions
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,10 +23,12 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import org.apache.poi.util.BoundedInputStream;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -185,4 +187,14 @@ public class ExOleObjStg extends PositionDependentRecordAtom implements PersistR
|
|||
public void updateOtherRecordReferences(Map<Integer,Integer> oldToNewReferencesLookup) {
|
||||
// nothing to update
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"compressed", this::isCompressed,
|
||||
"persistId", this::getPersistId,
|
||||
"dataLength", this::getDataLength,
|
||||
"data", this::getData
|
||||
);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.fonts.FontHeader;
|
||||
import org.apache.poi.common.usermodel.fonts.FontInfo;
|
||||
|
@ -200,4 +201,9 @@ public final class FontCollection extends RecordContainer {
|
|||
public List<HSLFFontInfo> getFonts() {
|
||||
return new ArrayList<>(fonts.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,12 @@ package org.apache.poi.hslf.record;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.fonts.FontFacet;
|
||||
import org.apache.poi.common.usermodel.fonts.FontHeader;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -113,4 +116,9 @@ public class FontEmbeddedData extends RecordAtom implements FontFacet {
|
|||
public Object getFontData() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties("fontHeader", this::getFontHeader);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,11 +17,18 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.common.usermodel.fonts.FontFamily;
|
||||
import org.apache.poi.common.usermodel.fonts.FontPitch;
|
||||
import org.apache.poi.hslf.exceptions.HSLFException;
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
|
@ -40,6 +47,18 @@ public final class FontEntityAtom extends RecordAtom {
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
0x0001, 0x0100, 0x0200, 0x0400, 0x0800
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"EMBED_SUBSETTED",
|
||||
"RASTER_FONT",
|
||||
"DEVICE_FONT",
|
||||
"TRUETYPE_FONT",
|
||||
"NO_FONT_SUBSTITUTION"
|
||||
};
|
||||
|
||||
/**
|
||||
* record header
|
||||
*/
|
||||
|
@ -210,4 +229,16 @@ public final class FontEntityAtom extends RecordAtom {
|
|||
out.write(_header);
|
||||
out.write(_recdata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"fontName", this::getFontName,
|
||||
"fontIndex", this::getFontIndex,
|
||||
"charset", this::getCharSet,
|
||||
"fontFlags", getBitsAsString(this::getFontFlags, FLAGS_MASKS, FLAGS_NAMES),
|
||||
"fontPitch", () -> FontPitch.valueOfPitchFamily((byte)getPitchAndFamily()),
|
||||
"fontFamily", () -> FontFamily.valueOfPitchFamily((byte)getPitchAndFamily())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,17 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
import static org.apache.poi.util.GenericRecordUtil.safeEnum;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* An atom record that specifies options for displaying headers and footers
|
||||
|
@ -31,10 +38,33 @@ import java.io.OutputStream;
|
|||
|
||||
public final class HeadersFootersAtom extends RecordAtom {
|
||||
|
||||
/** FormatIndex enum without LCID mapping */
|
||||
public enum FormatIndex {
|
||||
SHORT_DATE,
|
||||
LONG_DATE,
|
||||
LONG_DATE_WITHOUT_WEEKDAY,
|
||||
ALTERNATE_SHORT_DATE,
|
||||
ISO_STANDARD_DATE,
|
||||
SHORT_DATE_WITH_ABBREVIATED_MONTH,
|
||||
SHORT_DATE_WITH_SLASHES,
|
||||
ALTERNATE_SHORT_DATE_WITH_ABBREVIATED_MONTH,
|
||||
ENGLISH_DATE,
|
||||
MONTH_AND_YEAR,
|
||||
ABBREVIATED_MONTH_AND_YEAR,
|
||||
DATE_AND_HOUR12_TIME,
|
||||
DATE_AND_HOUR12_TIME_WITH_SECONDS,
|
||||
HOUR12_TIME,
|
||||
HOUR12_TIME_WITH_SECONDS,
|
||||
HOUR24_TIME,
|
||||
HOUR24_TIME_WITH_SECONDS,
|
||||
CHINESE1,
|
||||
CHINESE2,
|
||||
CHINESE3
|
||||
}
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
|
||||
/**
|
||||
* A bit that specifies whether the date is displayed in the footer.
|
||||
* @see #getMask()
|
||||
|
@ -82,6 +112,21 @@ public final class HeadersFootersAtom extends RecordAtom {
|
|||
*/
|
||||
public static final int fHasFooter = 32;
|
||||
|
||||
private static final int[] PLACEHOLDER_MASKS = {
|
||||
fHasDate,
|
||||
fHasTodayDate,
|
||||
fHasUserDate,
|
||||
fHasSlideNumber,
|
||||
fHasHeader,
|
||||
fHasFooter
|
||||
};
|
||||
|
||||
private static final String[] PLACEHOLDER_NAMES = {
|
||||
"DATE", "TODAY_DATE", "USER_DATE", "SLIDE_NUMBER", "HEADER", "FOOTER"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* record header
|
||||
*/
|
||||
|
@ -213,4 +258,12 @@ public final class HeadersFootersAtom extends RecordAtom {
|
|||
buf.append("\t fHasFooter : " + getFlag(fHasFooter) + "\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"formatIndex", safeEnum(FormatIndex.values(), this::getFormatId),
|
||||
"flags", getBitsAsString(this::getMask, PLACEHOLDER_MASKS, PLACEHOLDER_NAMES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A container record that specifies information about the footers on a presentation slide.
|
||||
* <p>
|
||||
|
@ -63,24 +63,39 @@ public final class HeadersFootersContainer extends RecordContainer {
|
|||
System.arraycopy(source,start,_header,0,8);
|
||||
|
||||
_children = Record.findChildRecords(source,start+8,len-8);
|
||||
for(int i=0; i < _children.length; i++){
|
||||
if(_children[i] instanceof HeadersFootersAtom) hdAtom = (HeadersFootersAtom)_children[i];
|
||||
else if(_children[i] instanceof CString) {
|
||||
CString cs = (CString)_children[i];
|
||||
findInterestingChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through our child records, picking out the ones that are
|
||||
* interesting, and saving those for use by the easy helper
|
||||
* methods.
|
||||
*/
|
||||
private void findInterestingChildren() {
|
||||
for (Record child : _children) {
|
||||
if (child instanceof HeadersFootersAtom) {
|
||||
hdAtom = (HeadersFootersAtom) child;
|
||||
} else if (child instanceof CString) {
|
||||
CString cs = (CString) child;
|
||||
int opts = cs.getOptions() >> 4;
|
||||
switch(opts){
|
||||
case USERDATEATOM: csDate = cs; break;
|
||||
case HEADERATOM: csHeader = cs; break;
|
||||
case FOOTERATOM: csFooter = cs; break;
|
||||
switch (opts) {
|
||||
case USERDATEATOM:
|
||||
csDate = cs;
|
||||
break;
|
||||
case HEADERATOM:
|
||||
csHeader = cs;
|
||||
break;
|
||||
case FOOTERATOM:
|
||||
csFooter = cs;
|
||||
break;
|
||||
default:
|
||||
logger.log(POILogger.WARN, "Unexpected CString.Options in HeadersFootersContainer: " + opts);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
logger.log(POILogger.WARN, "Unexpected record in HeadersFootersContainer: " + _children[i]);
|
||||
logger.log(POILogger.WARN, "Unexpected record in HeadersFootersContainer: " + child);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public HeadersFootersContainer(short options) {
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.apache.poi.util.POILogger;
|
|||
*/
|
||||
public class InteractiveInfo extends RecordContainer {
|
||||
private byte[] _header;
|
||||
private static long _type = 4082;
|
||||
private static final long _type = RecordTypes.InteractiveInfo.typeID;
|
||||
|
||||
// Links to our more interesting children
|
||||
private InteractiveInfoAtom infoAtom;
|
||||
|
|
|
@ -17,9 +17,15 @@
|
|||
|
||||
package org.apache.poi.hslf.record;
|
||||
|
||||
import static org.apache.poi.util.GenericRecordUtil.getBitsAsString;
|
||||
import static org.apache.poi.util.GenericRecordUtil.safeEnum;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.poi.util.GenericRecordUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
|
@ -35,6 +41,39 @@ public class InteractiveInfoAtom extends RecordAtom {
|
|||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
public enum Action {
|
||||
NONE,
|
||||
MACRO,
|
||||
RUN_PROGRAM,
|
||||
JUMP,
|
||||
HYPERLINK,
|
||||
OLE,
|
||||
MEDIA,
|
||||
CUSTOM_SHOW
|
||||
}
|
||||
|
||||
public enum Jump {
|
||||
NONE,
|
||||
NEXT_SLIDE,
|
||||
PREVIOUS_SLIDE,
|
||||
FIRST_SLIDE,
|
||||
LAST_SLIDE,
|
||||
LAST_SLIDE_VIEWED,
|
||||
END_SHOW
|
||||
}
|
||||
|
||||
public enum Link {
|
||||
NEXT_SLIDE,
|
||||
PREVIOUS_SLIDE,
|
||||
FIRST_SLIDE,
|
||||
LAST_SLIDE,
|
||||
CUSTOM_SHOW,
|
||||
SLIDE_NUMBER,
|
||||
URL,
|
||||
OTHER_PRESENTATION,
|
||||
OTHER_FILE,
|
||||
NULL
|
||||
}
|
||||
|
||||
/**
|
||||
* Action Table
|
||||
|
@ -73,6 +112,14 @@ public class InteractiveInfoAtom extends RecordAtom {
|
|||
public static final byte LINK_OtherFile = 0x0A;
|
||||
public static final byte LINK_NULL = (byte)0xFF;
|
||||
|
||||
private static final int[] FLAGS_MASKS = {
|
||||
0x0001, 0x0002, 0x0004, 0x0008
|
||||
};
|
||||
|
||||
private static final String[] FLAGS_NAMES = {
|
||||
"ANIMATED", "STOP_SOUND", "CUSTOM_SHOW_RETURN", "VISITED"
|
||||
};
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
*/
|
||||
|
@ -280,4 +327,16 @@ public class InteractiveInfoAtom extends RecordAtom {
|
|||
out.write(_header);
|
||||
out.write(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<?>> getGenericProperties() {
|
||||
return GenericRecordUtil.getGenericProperties(
|
||||
"hyperlinkID", this::getHyperlinkID,
|
||||
"soundRef", this::getSoundRef,
|
||||
"action", safeEnum(Action.values(), this::getAction),
|
||||
"jump", safeEnum(Jump.values(), this::getJump),
|
||||
"hyperlinkType", safeEnum(Link.values(), this::getHyperlinkType, Link.NULL),
|
||||
"flags", getBitsAsString(this::getFlags, FLAGS_MASKS, FLAGS_NAMES)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue