org.apache.poi.sl.draw.geom.PresetParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apache-poi Show documentation
Show all versions of apache-poi Show documentation
The Apache Commons Codec package contains simple encoder and decoders for
various formats such as Base64 and Hexadecimal. In addition to these
widely used encoders and decoders, the codec package also maintains a
collection of phonetic encoding utilities.
/*
* ====================================================================
* 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.sl.draw.geom;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.sl.usermodel.PaintStyle.PaintModifier;
import org.apache.poi.util.Internal;
@Internal
class PresetParser {
enum Mode {
FILE(PresetParser::updateFile),
SHAPE_LST(PresetParser::updateShapeList),
SHAPE(PresetParser::updateShape),
GUIDE_LST(PresetParser::updateGuideList),
AH_LST(PresetParser::updateAhList),
CXN_LST(PresetParser::updateCxnList),
PATH_LST(PresetParser::updatePathLst),
PATH(PresetParser::updatePath);
interface Handler {
void update(PresetParser parser, XMLStreamReader sr) throws XMLStreamException;
}
final Handler handler;
Mode(Handler handler) {
this.handler = handler;
}
}
private static final Logger LOG = LogManager.getLogger(PresetParser.class);
private Mode mode;
private final Map geom = new HashMap<>();
private CustomGeometry customGeometry;
private boolean useAdjustValue;
private Path path;
PresetParser(Mode mode) {
this.mode = mode;
if (mode == Mode.SHAPE) {
customGeometry = new CustomGeometry();
geom.put("custom", customGeometry);
}
}
void parse(XMLStreamReader sr) throws XMLStreamException {
while (sr.hasNext()) {
switch (sr.next()) {
case XMLStreamConstants.START_ELEMENT:
mode.handler.update(this, sr);
break;
case XMLStreamConstants.END_ELEMENT:
endContext();
break;
case XMLStreamConstants.END_DOCUMENT:
return;
default:
break;
}
}
}
Map getGeom() {
return geom;
}
private void updateFile(XMLStreamReader sr) {
final String name = sr.getLocalName();
assert("presetShapeDefinitons".equals(name));
mode = Mode.SHAPE_LST;
}
private void updateShapeList(XMLStreamReader sr) {
final String name = sr.getLocalName();
customGeometry = new CustomGeometry();
if (geom.containsKey(name)) {
LOG.atWarn().log("Duplicate definition of {}", name);
}
geom.put(name, customGeometry);
mode = Mode.SHAPE;
}
private void updateShape(XMLStreamReader sr) throws XMLStreamException {
final String name = sr.getLocalName();
switch (name) {
case "avLst":
useAdjustValue = true;
mode = Mode.GUIDE_LST;
break;
case "gdLst":
useAdjustValue = false;
mode = Mode.GUIDE_LST;
break;
case "ahLst":
mode = Mode.AH_LST;
break;
case "cxnLst":
mode = Mode.CXN_LST;
break;
case "rect":
addRectangle(sr);
break;
case "pathLst":
mode = Mode.PATH_LST;
break;
}
}
private void updateGuideList(XMLStreamReader sr) throws XMLStreamException {
final String name = sr.getLocalName();
assert("gd".equals(name));
final Guide gd;
if (useAdjustValue) {
customGeometry.addAdjustGuide((AdjustValue)(gd = new AdjustValue()));
} else {
customGeometry.addGeomGuide(gd = new Guide());
}
parseAttributes(sr, (key,val) -> {
switch (key) {
case "name":
// CollapsedStringAdapter
gd.setName(collapseString(val));
break;
case "fmla":
gd.setFmla(val);
break;
}
});
int tag = nextTag(sr);
assert(tag == XMLStreamConstants.END_ELEMENT);
}
private void updateAhList(XMLStreamReader sr) throws XMLStreamException {
String name = sr.getLocalName();
switch (name) {
case "ahXY":
addXY(sr);
break;
case "ahPolar":
addPolar(sr);
break;
}
}
private void addXY(XMLStreamReader sr) throws XMLStreamException {
XYAdjustHandle ahXY = new XYAdjustHandle();
customGeometry.addAdjustHandle(ahXY);
parseAttributes(sr, (key, val) -> {
switch (key) {
case "gdRefX":
ahXY.setGdRefX(collapseString(val));
break;
case "minX":
ahXY.setMinX(val);
break;
case "maxX":
ahXY.setMaxX(val);
break;
case "gdRefY":
ahXY.setGdRefY(collapseString(val));
break;
case "minY":
ahXY.setMinY(val);
break;
case "maxY":
ahXY.setMaxY(val);
break;
}
});
ahXY.setPos(parsePosPoint(sr));
}
private void addPolar(XMLStreamReader sr) throws XMLStreamException {
PolarAdjustHandle ahPolar = new PolarAdjustHandle();
customGeometry.addAdjustHandle(ahPolar);
parseAttributes(sr, (key, val) -> {
switch (key) {
case "gdRefR":
ahPolar.setGdRefR(collapseString(val));
break;
case "minR":
ahPolar.setMinR(val);
break;
case "maxR":
ahPolar.setMaxR(val);
break;
case "gdRefAng":
ahPolar.setGdRefAng(collapseString(val));
break;
case "minAng":
ahPolar.setMinAng(val);
break;
case "maxAng":
ahPolar.setMaxAng(val);
break;
}
});
ahPolar.setPos(parsePosPoint(sr));
}
private void updateCxnList(XMLStreamReader sr) throws XMLStreamException {
String name = sr.getLocalName();
assert("cxn".equals(name));
ConnectionSite cxn = new ConnectionSite();
customGeometry.addConnectionSite(cxn);
parseAttributes(sr, (key, val) -> {
if ("ang".equals(key)) {
cxn.setAng(val);
}
});
cxn.setPos(parsePosPoint(sr));
}
private void updatePathLst(XMLStreamReader sr) {
String name = sr.getLocalName();
assert("path".equals(name));
path = new Path();
customGeometry.addPath(path);
parseAttributes(sr, (key, val) -> {
switch (key) {
case "w":
path.setW(Long.parseLong(val));
break;
case "h":
path.setH(Long.parseLong(val));
break;
case "fill":
path.setFill(mapFill(val));
break;
case "stroke":
path.setStroke(Boolean.parseBoolean(val));
break;
case "extrusionOk":
path.setExtrusionOk(Boolean.parseBoolean(val));
break;
}
});
mode = Mode.PATH;
}
private static PaintModifier mapFill(String fill) {
switch (fill) {
default:
case "none":
return PaintModifier.NONE;
case "norm":
return PaintModifier.NORM;
case "lighten":
return PaintModifier.LIGHTEN;
case "lightenLess":
return PaintModifier.LIGHTEN_LESS;
case "darken":
return PaintModifier.DARKEN;
case "darkenLess":
return PaintModifier.DARKEN_LESS;
}
}
private void updatePath(XMLStreamReader sr) throws XMLStreamException {
String name = sr.getLocalName();
switch (name) {
case "close":
closePath(sr);
break;
case "moveTo":
moveTo(sr);
break;
case "lnTo":
lineTo(sr);
break;
case "arcTo":
arcTo(sr);
break;
case "quadBezTo":
quadBezTo(sr);
break;
case "cubicBezTo":
cubicBezTo(sr);
break;
}
}
private void closePath(XMLStreamReader sr) throws XMLStreamException {
path.addCommand(new ClosePathCommand());
int tag = nextTag(sr);
assert(tag == XMLStreamConstants.END_ELEMENT);
}
private void moveTo(XMLStreamReader sr) throws XMLStreamException {
MoveToCommand cmd = new MoveToCommand();
path.addCommand(cmd);
AdjustPoint pt = parsePtPoint(sr, true);
assert(pt != null);
cmd.setPt(pt);
}
private void lineTo(XMLStreamReader sr) throws XMLStreamException {
LineToCommand cmd = new LineToCommand();
path.addCommand(cmd);
AdjustPoint pt = parsePtPoint(sr, true);
assert(pt != null);
cmd.setPt(pt);
}
private void arcTo(XMLStreamReader sr) throws XMLStreamException {
ArcToCommand cmd = new ArcToCommand();
path.addCommand(cmd);
parseAttributes(sr, (key, val) -> {
switch (key) {
case "wR":
cmd.setWR(val);
break;
case "hR":
cmd.setHR(val);
break;
case "stAng":
cmd.setStAng(val);
break;
case "swAng":
cmd.setSwAng(val);
break;
}
});
int tag = nextTag(sr);
assert (tag == XMLStreamConstants.END_ELEMENT);
}
private void quadBezTo(XMLStreamReader sr) throws XMLStreamException {
QuadToCommand cmd = new QuadToCommand();
path.addCommand(cmd);
AdjustPoint pt1 = parsePtPoint(sr, false);
AdjustPoint pt2 = parsePtPoint(sr, true);
assert (pt1 != null && pt2 != null);
cmd.setPt1(pt1);
cmd.setPt2(pt2);
}
private void cubicBezTo(XMLStreamReader sr) throws XMLStreamException {
CurveToCommand cmd = new CurveToCommand();
path.addCommand(cmd);
AdjustPoint pt1 = parsePtPoint(sr, false);
AdjustPoint pt2 = parsePtPoint(sr, false);
AdjustPoint pt3 = parsePtPoint(sr, true);
assert (pt1 != null && pt2 != null && pt3 != null);
cmd.setPt1(pt1);
cmd.setPt2(pt2);
cmd.setPt3(pt3);
}
private void addRectangle(XMLStreamReader sr) throws XMLStreamException {
String[] ltrb = new String[4];
parseAttributes(sr, (key,val) -> {
switch (key) {
case "l":
ltrb[0] = val;
break;
case "t":
ltrb[1] = val;
break;
case "r":
ltrb[2] = val;
break;
case "b":
ltrb[3] = val;
break;
}
});
customGeometry.setTextBounds(ltrb[0],ltrb[1],ltrb[2],ltrb[3]);
int tag = nextTag(sr);
assert(tag == XMLStreamConstants.END_ELEMENT);
}
private void endContext() {
switch (mode) {
case FILE:
case SHAPE_LST:
mode = Mode.FILE;
break;
case SHAPE:
mode = Mode.SHAPE_LST;
break;
case CXN_LST:
case AH_LST:
case GUIDE_LST:
case PATH_LST:
useAdjustValue = false;
path = null;
mode = Mode.SHAPE;
break;
case PATH:
path = null;
mode = Mode.PATH_LST;
break;
}
}
private AdjustPoint parsePosPoint(XMLStreamReader sr) throws XMLStreamException {
return parseAdjPoint(sr, true, "pos");
}
private AdjustPoint parsePtPoint(XMLStreamReader sr, boolean closeOuter) throws XMLStreamException {
return parseAdjPoint(sr, closeOuter, "pt");
}
private AdjustPoint parseAdjPoint(XMLStreamReader sr, boolean closeOuter, String name) throws XMLStreamException {
int tag = nextTag(sr);
if (tag == XMLStreamConstants.END_ELEMENT) {
return null;
}
assert (name.equals(sr.getLocalName()));
AdjustPoint pos = new AdjustPoint();
parseAttributes(sr, (key, val) -> {
switch (key) {
case "x":
pos.setX(val);
break;
case "y":
pos.setY(val);
break;
}
});
tag = nextTag(sr);
assert(tag == XMLStreamConstants.END_ELEMENT);
if (closeOuter) {
tag = nextTag(sr);
assert(tag == XMLStreamConstants.END_ELEMENT);
}
return pos;
}
private void parseAttributes(XMLStreamReader sr, BiConsumer c) {
for (int i=0; i 0 && result.charAt(len - 1) == ' ') {
result.setLength(len - 1);
}
// whitespaces are already collapsed, so all we have to do is
// to remove the last one character if it's a whitespace.
return result.toString();
}
/** returns true if the specified char is a white space character. */
private static boolean isWhiteSpace(char ch) {
return ch == 0x9 || ch == 0xA || ch == 0xD || ch == 0x20;
}
}