Просмотр исходного кода

#59004 - HSLF rendering - adjust values for presetShapeDefinition differs in HSLF/XSLF

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1859102 13f79535-47bb-0310-9956-ffa450edef68
pull/148/head
Andreas Beeker 5 лет назад
Родитель
Сommit
0bdae1ac7b

+ 25
- 84
src/java/org/apache/poi/sl/draw/DrawSimpleShape.java Просмотреть файл

@@ -307,98 +307,39 @@ public class DrawSimpleShape extends DrawShape {
, Paint fill
, Paint line
) {
Shadow<?,?> shadow = getShape().getShadow();
if (shadow == null || (fill == null && line == null)) {
return;
}

SolidPaint shadowPaint = shadow.getFillStyle();
Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor());

double shapeRotation = getShape().getRotation();
if(getShape().getFlipVertical()) {
shapeRotation += 180;
}
double angle = shadow.getAngle() - shapeRotation;
double dist = shadow.getDistance();
double dx = dist * Math.cos(Math.toRadians(angle));
double dy = dist * Math.sin(Math.toRadians(angle));

graphics.translate(dx, dy);

for(Outline o : outlines){
java.awt.Shape s = o.getOutline();
Path p = o.getPath();
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
graphics.setPaint(shadowColor);

if(fill != null && p.isFilled()){
fillPaintWorkaround(graphics, s);
} else if (line != null && p.isStroked()) {
graphics.draw(s);
}
}

graphics.translate(-dx, -dy);
}

protected static CustomGeometry getCustomGeometry(String name) {
return getCustomGeometry(name, null);
}
Shadow<?,?> shadow = getShape().getShadow();
if (shadow == null || (fill == null && line == null)) {
return;
}

protected static CustomGeometry getCustomGeometry(String name, Graphics2D graphics) {
@SuppressWarnings("unchecked")
Map<String, CustomGeometry> presets = (graphics == null)
? null
: (Map<String, CustomGeometry>)graphics.getRenderingHint(Drawable.PRESET_GEOMETRY_CACHE);
SolidPaint shadowPaint = shadow.getFillStyle();
Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor());

if (presets == null) {
presets = new HashMap<>();
if (graphics != null) {
graphics.setRenderingHint(Drawable.PRESET_GEOMETRY_CACHE, presets);
}
double shapeRotation = getShape().getRotation();
if (getShape().getFlipVertical()) {
shapeRotation += 180;
}
double angle = shadow.getAngle() - shapeRotation;
double dist = shadow.getDistance();
double dx = dist * Math.cos(Math.toRadians(angle));
double dy = dist * Math.sin(Math.toRadians(angle));

String packageName = "org.apache.poi.sl.draw.binding";
InputStream presetIS = Drawable.class.getResourceAsStream("presetShapeDefinitions.xml");
graphics.translate(dx, dy);

// StAX:
EventFilter startElementFilter = new EventFilter() {
@Override
public boolean accept(XMLEvent event) {
return event.isStartElement();
}
};

try {
XMLInputFactory staxFactory = StaxHelper.newXMLInputFactory();
XMLEventReader staxReader = staxFactory.createXMLEventReader(presetIS);
XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter);
// Ignore StartElement:
staxFiltRd.nextEvent();
// JAXB:
JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

while (staxFiltRd.peek() != null) {
StartElement evRoot = (StartElement)staxFiltRd.peek();
String cusName = evRoot.getName().getLocalPart();
// XMLEvent ev = staxReader.nextEvent();
JAXBElement<org.apache.poi.sl.draw.binding.CTCustomGeometry2D> el = unmarshaller.unmarshal(staxReader, CTCustomGeometry2D.class);
CTCustomGeometry2D cusGeom = el.getValue();

presets.put(cusName, new CustomGeometry(cusGeom));
}
for (Outline o : outlines) {
java.awt.Shape s = o.getOutline();
Path p = o.getPath();
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
graphics.setPaint(shadowColor);

staxFiltRd.close();
staxReader.close();
} catch (Exception e) {
throw new RuntimeException("Unable to load preset geometries.", e);
} finally {
IOUtils.closeQuietly(presetIS);
if (fill != null && p.isFilled()) {
fillPaintWorkaround(graphics, s);
} else if (line != null && p.isStroked()) {
graphics.draw(s);
}
}

return presets.get(name);
graphics.translate(-dx, -dy);
}

protected Collection<Outline> computeOutlines(Graphics2D graphics) {

+ 1
- 2
src/java/org/apache/poi/sl/draw/geom/Context.java Просмотреть файл

@@ -51,8 +51,7 @@ public class Context {
}

Guide getAdjustValue(String name){
// ignore HSLF props for now ... the results with default value are usually better - see #59004
return (_props.getClass().getName().contains("hslf")) ? null : _props.getAdjustValue(name);
return _props.getAdjustValue(name);
}

public double getValue(String key){

+ 31
- 7
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java Просмотреть файл

@@ -321,8 +321,10 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
name = "1";
}

final int adjInt = Integer.parseInt(name);

short escherProp;
switch (Integer.parseInt(name)) {
switch (adjInt) {
case 1: escherProp = EscherProperties.GEOMETRY__ADJUSTVALUE; break;
case 2: escherProp = EscherProperties.GEOMETRY__ADJUST2VALUE; break;
case 3: escherProp = EscherProperties.GEOMETRY__ADJUST3VALUE; break;
@@ -336,14 +338,36 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
default: throw new HSLFException();
}

// TODO: the adjust values need to be corrected somehow depending on the shape width/height
// see https://social.msdn.microsoft.com/Forums/en-US/3f69ebb3-62a0-4fdd-b367-64790dfb2491/presetshapedefinitionsxml-does-not-specify-width-and-height-form-some-autoshapes?forum=os_binaryfile
// the adjust value can be format dependent, e.g. hexagon has different values,
// other shape types have the same adjust values in OOXML and native
int adjval = getEscherProperty(escherProp, -1);

return (adjval == -1) ? null : new Guide(name, "val "+adjval);
if (adjval == -1) {
return null;
}

// Bug 59004
// the adjust value are format dependent, we scale them up so they match the OOXML ones.
// see https://social.msdn.microsoft.com/Forums/en-US/33e458e6-58df-48fe-9a10-e303ab08991d/preset-shapes-for-ppt?forum=os_binaryfile

// usually we deal with length units and only very few degree units:
boolean isDegreeUnit = false;
switch (getShapeType()) {
case ARC:
case BLOCK_ARC:
case CHORD:
case PIE:
isDegreeUnit = (adjInt == 1 || adjInt == 2);
break;
case CIRCULAR_ARROW:
case LEFT_CIRCULAR_ARROW:
case LEFT_RIGHT_CIRCULAR_ARROW:
isDegreeUnit = (adjInt == 2 || adjInt == 3 || adjInt == 4);
break;
case MATH_NOT_EQUAL:
isDegreeUnit = (adjInt == 2);
break;
}

return new Guide(name, "val "+Math.rint(adjval * (isDegreeUnit ? 65536. : 100000./21000.)));
}

@Override

Загрузка…
Отмена
Сохранить