Update from Yegor in bug 41046 - support background shapes and fills

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@480104 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2006-11-28 15:55:27 +00:00
parent d5de2ed9a5
commit c6960a5c08
8 changed files with 597 additions and 0 deletions
src
documentation/content/xdocs/hslf
scratchpad
src/org/apache/poi/hslf/model
testcases/org/apache/poi/hslf

View File

@ -19,6 +19,7 @@
<li><link href="#Shapes">Drawing a shape on a slide</link></li>
<li><link href="#Pictures">How to work with pictures</link></li>
<li><link href="#SlideTitle">How to set slide title</link></li>
<li><link href="#Fill">How to work with slide/shape background</link></li>
</ul>
</section>
<section><title>Features</title>
@ -252,6 +253,47 @@
myDocument.Shapes.AddTitle.TextFrame.TextRange.Text = "Hello, World!"
</source>
</section>
<anchor id="Fill"/>
<section><title>How to modify background of a slide master</title>
<source>
SlideShow ppt = new SlideShow();
SlideMaster master = ppt.getSlidesMasters()[0];
Fill fill = master.getBackground().getFill();
int idx = ppt.addPicture(new File("background.png"), Picture.PNG);
fill.setFillType(Fill.FILL_PICTURE);
fill.setPictureData(idx);
</source>
</section>
<section><title>How to modify background of a slide</title>
<source>
SlideShow ppt = new SlideShow();
Slide slide = ppt.createSlide();
//This slide has its own background.
//Without this line it will use master's background.
slide.setFollowMasterBackground(false);
Fill fill = slide.getBackground().getFill();
int idx = ppt.addPicture(new File("background.png"), Picture.PNG);
fill.setFillType(Fill.FILL_PATTERN);
fill.setPictureData(idx);
</source>
</section>
<section><title>How to modify background of a shape</title>
<source>
SlideShow ppt = new SlideShow();
Slide slide = ppt.createSlide();
Shape shape = new AutoShape(ShapeTypes.Rectangle);
shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
Fill fill = shape.getFill();
fill.setFillType(Fill.FILL_SHADE);
fill.setBackgroundColor(Color.red);
fill.setForegroundColor(Color.green);
slide.addShape(shape);
</source>
</section>
</section>
</section>

View File

@ -0,0 +1,37 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed 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.hslf.model;
import org.apache.poi.ddf.EscherContainerRecord;
/**
* Background shape
*
* @author Yegor Kozlov
*/
public class Background extends Shape {
protected Background(EscherContainerRecord escherRecord, Shape parent){
super(escherRecord, parent);
}
protected EscherContainerRecord createSpContainer(boolean isChild){
return null;
}
}

View File

@ -0,0 +1,228 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed 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.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.usermodel.PictureData;
import org.apache.poi.hslf.usermodel.SlideShow;
import java.awt.*;
import java.util.*;
/**
* Represents functionality provided by the 'Fill Effects' dialog in PowerPoint.
*
* @author Yegor Kozlov
*/
public class Fill {
/**
* Fill with a solid color
*/
public static final int FILL_SOLID = 0;
/**
* Fill with a pattern (bitmap)
*/
public static final int FILL_PATTERN = 1;
/**
* A texture (pattern with its own color map)
*/
public static final int FILL_TEXTURE = 2;
/**
* Center a picture in the shape
*/
public static final int FILL_PICTURE = 3;
/**
* Shade from start to end points
*/
public static final int FILL_SHADE = 4;
/**
* Shade from bounding rectangle to end point
*/
public static final int FILL_SHADE_CENTER = 5;
/**
* Shade from shape outline to end point
*/
public static final int FILL_SHADE_SHAPE = 6;
/**
* Similar to FILL_SHADE, but the fill angle
* is additionally scaled by the aspect ratio of
* the shape. If shape is square, it is the same as FILL_SHADE
*/
public static final int FILL_SHADE_SCALE = 7;
/**
* shade to title
*/
public static final int FILL_SHADE_TITLE = 8;
/**
* Use the background fill color/pattern
*/
public static final int FILL_BACKGROUND = 9;
/**
* The shape this background applies to
*/
protected Shape shape;
/**
* Construct a <code>Fill</code> object for a shape.
* Fill information will be read from shape's escher properties.
*
* @param shape the shape this background applies to
*/
public Fill(Shape shape){
this.shape = shape;
}
/**
* Returns fill type.
* Must be one of the <code>FILL_*</code> constants defined in this class.
*
* @return type of fill
*/
public int getFillType(){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
EscherSimpleProperty prop = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__FILLTYPE);
return prop == null ? FILL_SOLID : prop.getPropertyValue();
}
/**
* Sets fill type.
* Must be one of the <code>FILL_*</code> constants defined in this class.
*
* @param type type of the fill
*/
public void setFillType(int type){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLTYPE, type);
}
/**
* Foreground color
*/
public Color getForegroundColor(){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
EscherSimpleProperty p1 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__FILLCOLOR);
EscherSimpleProperty p2 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST);
int p2val = p2 == null ? 0 : p2.getPropertyValue();
Color clr = null;
if (p1 != null && (p2val & 0x10) != 0){
int rgb = p1.getPropertyValue();
clr = shape.getColor(rgb);
}
return clr;
}
/**
* Foreground color
*/
public void setForegroundColor(Color color){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
if (color == null) {
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, -1);
}
else {
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);
}
}
/**
* Background color
*/
public Color getBackgroundColor(){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
EscherSimpleProperty p1 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR);
EscherSimpleProperty p2 = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST);
int p2val = p2 == null ? 0 : p2.getPropertyValue();
Color clr = null;
if (p1 != null && (p2val & 0x10) != 0){
int rgb = p1.getPropertyValue();
clr = shape.getColor(rgb);
}
return clr;
}
/**
* Background color
*/
public void setBackgroundColor(Color color){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
if (color == null) {
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, -1);
}
else {
int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
Shape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb);
}
}
/**
* <code>PictureData</code> object used in a texture, pattern of picture fill.
*/
public PictureData getPictureData(){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
EscherSimpleProperty p = (EscherSimpleProperty)Shape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE);
if (p == null) return null;
SlideShow ppt = shape.getSheet().getSlideShow();
PictureData[] pict = ppt.getPictureData();
Document doc = ppt.getDocumentRecord();
EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
EscherContainerRecord bstore = (EscherContainerRecord)Shape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
java.util.List lst = bstore.getChildRecords();
int idx = p.getPropertyValue();
EscherBSERecord bse = (EscherBSERecord)lst.get(idx);
for ( int i = 0; i < pict.length; i++ ) {
if (pict[i].getOffset() == bse.getOffset()){
return pict[i];
}
}
throw new RuntimeException("Picture data not found: \n" +
" bse: " + bse + " at " + bse.getOffset() );
}
/**
* Assign picture used to fill the underlying shape.
*
* @param idx 0-based index of the picture added to this ppt by <code>SlideShow.addPicture</code> method.
*/
public void setPictureData(int idx){
EscherOptRecord opt = (EscherOptRecord)Shape.getEscherChild(shape.getSpContainer(), EscherOptRecord.RECORD_ID);
Shape.setEscherProperty(opt, (short)(EscherProperties.FILL__PATTERNTEXTURE + 0x4000), idx);
}
}

View File

@ -17,7 +17,10 @@ package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.model.ShapeTypes;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import java.util.Iterator;
import java.awt.*;
/**
* <p>
@ -282,4 +285,23 @@ public abstract class Shape {
_sheet = sheet;
}
protected Color getColor(int rgb){
if (rgb >= 0x8000000) {
int idx = rgb - 0x8000000;
ColorSchemeAtom ca = getSheet().getColorScheme();
if(idx >= 0 && idx <= 7) rgb = ca.getColor(idx);
}
Color tmp = new Color(rgb, true);
return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());
}
/**
* Fill properties of this shape
*
* @return fill properties of this shape
*/
public Fill getFill(){
return new Fill(this);
}
}

View File

@ -20,12 +20,17 @@
package org.apache.poi.hslf.model;
import java.util.Vector;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
import org.apache.poi.hslf.record.PPDrawing;
import org.apache.poi.hslf.record.SlideAtom;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
/**
* This class represents a slide in a PowerPoint Document. It allows
@ -33,6 +38,7 @@ import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
* the text side of things though
*
* @author Nick Burch
* @author Yegor Kozlov
*/
public class Slide extends Sheet
@ -45,6 +51,7 @@ public class Slide extends Sheet
private TextRun[] _runs;
private TextRun[] _otherRuns; // Any from the PPDrawing, shouldn't really be any though
private Notes _notes; // usermodel needs to set this
private Background _background;
/**
* Constructs a Slide from the Slide record, and the SlideAtomsSet
@ -245,4 +252,51 @@ public class Slide extends Sheet
return _slide.getColorScheme();
}
/**
* Returns the background shape for this sheet.
*
* @return the background shape for this sheet.
*/
public Background getBackground(){
if (_background == null){
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
EscherContainerRecord spContainer = null;
List ch = dg.getChildRecords();
for (Iterator it = ch.iterator(); it.hasNext();) {
EscherRecord rec = (EscherRecord)it.next();
if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER){
spContainer = (EscherContainerRecord)rec;
break;
}
}
_background = new Background(spContainer, null);
_background.setSheet(this);
}
return _background;
}
/**
* Sets whether this slide follows master background
*
* @param flag <code>true</code> if the slide follows master,
* <code>false</code> otherwise
*/
public void setFollowMasterBackground(boolean flag){
SlideAtom sa = _slide.getSlideAtom();
sa.setFollowMasterBackground(flag);
}
/**
* Whether this slide follows master sheet background
*
* @return <code>true</code> if the slide follows master background,
* <code>false</code> otherwise
*/
public boolean getFollowMasterBackground(){
SlideAtom sa = _slide.getSlideAtom();
return sa.getFollowMasterBackground();
}
}

View File

@ -19,6 +19,11 @@ package org.apache.poi.hslf.model;
import org.apache.poi.hslf.record.*;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.hslf.record.StyleTextPropAtom.*;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
import java.util.List;
import java.util.Iterator;
/**
* SlideMaster determines the graphics, layout, and formatting for all the slides in a given presentation.
@ -32,6 +37,7 @@ public class SlideMaster extends MasterSheet {
private int _sheetNo;
private MainMaster _master;
private TextRun[] _runs;
private Background _background;
/**
* all TxMasterStyleAtoms available in this master
@ -143,4 +149,30 @@ public class SlideMaster extends MasterSheet {
return _master.getColorScheme();
}
/**
* Returns the background shape for this sheet.
*
* @return the background shape for this sheet.
*/
public Background getBackground(){
if (_background == null){
PPDrawing ppdrawing = getPPDrawing();
EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
EscherContainerRecord spContainer = null;
List ch = dg.getChildRecords();
for (Iterator it = ch.iterator(); it.hasNext();) {
EscherRecord rec = (EscherRecord)it.next();
if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER){
spContainer = (EscherContainerRecord)rec;
break;
}
}
_background = new Background(spContainer, null);
_background.setSheet(this);
}
return _background;
}
}

View File

@ -0,0 +1,182 @@
/* ====================================================================
Copyright 2002-2004 Apache Software Foundation
Licensed 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.hslf.model;
import junit.framework.TestCase;
import java.io.*;
import java.awt.*;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.hslf.HSLFSlideShow;
/**
* Test <code>Fill</code> object.
*
* @author Yegor Kozlov
*/
public class TestBackground extends TestCase {
/**
* Default background for slide, shape and slide master.
*/
public void testDefaults() throws Exception {
SlideShow ppt = new SlideShow();
assertEquals(Fill.FILL_SOLID, ppt.getSlidesMasters()[0].getBackground().getFill().getFillType());
Slide slide = ppt.createSlide();
assertTrue(slide.getFollowMasterBackground());
assertEquals(Fill.FILL_SOLID, slide.getBackground().getFill().getFillType());
Shape shape = new AutoShape(ShapeTypes.Rectangle);
assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType());
}
/**
* Read fill information from an reference ppt file
*/
public void testReadBackground() throws Exception {
SlideShow ppt = new SlideShow(new HSLFSlideShow(System.getProperty("HSLF.testdata.path") + "/backgrounds.ppt"));
Fill fill;
Shape shape;
Slide[] slide = ppt.getSlides();
fill = slide[0].getBackground().getFill();
assertEquals(Fill.FILL_PICTURE, fill.getFillType());
shape = slide[0].getShapes()[0];
assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType());
fill = slide[1].getBackground().getFill();
assertEquals(Fill.FILL_PATTERN, fill.getFillType());
shape = slide[1].getShapes()[0];
assertEquals(Fill.FILL_BACKGROUND, shape.getFill().getFillType());
fill = slide[2].getBackground().getFill();
assertEquals(Fill.FILL_TEXTURE, fill.getFillType());
shape = slide[2].getShapes()[0];
assertEquals(Fill.FILL_PICTURE, shape.getFill().getFillType());
fill = slide[3].getBackground().getFill();
assertEquals(Fill.FILL_SHADE_CENTER, fill.getFillType());
shape = slide[3].getShapes()[0];
assertEquals(Fill.FILL_SHADE, shape.getFill().getFillType());
}
/**
* Create a ppt with various fill effects
*/
public void testBackgroundPicture() throws Exception {
SlideShow ppt = new SlideShow();
Slide slide;
Fill fill;
Shape shape;
int idx;
//slide 1
slide = ppt.createSlide();
slide.setFollowMasterBackground(false);
fill = slide.getBackground().getFill();
idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/tomcat.png"), Picture.PNG);
fill.setFillType(Fill.FILL_PICTURE);
fill.setPictureData(idx);
shape = new AutoShape(ShapeTypes.Rectangle);
shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
fill = shape.getFill();
fill.setFillType(Fill.FILL_SOLID);
slide.addShape(shape);
//slide 2
slide = ppt.createSlide();
slide.setFollowMasterBackground(false);
fill = slide.getBackground().getFill();
idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/tomcat.png"), Picture.PNG);
fill.setFillType(Fill.FILL_PATTERN);
fill.setPictureData(idx);
fill.setBackgroundColor(Color.green);
fill.setForegroundColor(Color.red);
shape = new AutoShape(ShapeTypes.Rectangle);
shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
fill = shape.getFill();
fill.setFillType(Fill.FILL_BACKGROUND);
slide.addShape(shape);
//slide 3
slide = ppt.createSlide();
slide.setFollowMasterBackground(false);
fill = slide.getBackground().getFill();
idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/tomcat.png"), Picture.PNG);
fill.setFillType(Fill.FILL_TEXTURE);
fill.setPictureData(idx);
shape = new AutoShape(ShapeTypes.Rectangle);
shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
fill = shape.getFill();
fill.setFillType(Fill.FILL_PICTURE);
idx = ppt.addPicture(new File(System.getProperty("HSLF.testdata.path") + "/clock.jpg"), Picture.JPEG);
fill.setPictureData(idx);
slide.addShape(shape);
// slide 4
slide = ppt.createSlide();
slide.setFollowMasterBackground(false);
fill = slide.getBackground().getFill();
fill.setFillType(Fill.FILL_SHADE_CENTER);
fill.setBackgroundColor(Color.white);
fill.setForegroundColor(Color.darkGray);
shape = new AutoShape(ShapeTypes.Rectangle);
shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
fill = shape.getFill();
fill.setFillType(Fill.FILL_SHADE);
fill.setBackgroundColor(Color.red);
fill.setForegroundColor(Color.green);
slide.addShape(shape);
//serialize and read again
ByteArrayOutputStream out = new ByteArrayOutputStream();
ppt.write(out);
out.close();
ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));
Slide[] slides = ppt.getSlides();
fill = slides[0].getBackground().getFill();
assertEquals(Fill.FILL_PICTURE, fill.getFillType());
shape = slides[0].getShapes()[0];
assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType());
fill = slides[1].getBackground().getFill();
assertEquals(Fill.FILL_PATTERN, fill.getFillType());
shape = slides[1].getShapes()[0];
assertEquals(Fill.FILL_BACKGROUND, shape.getFill().getFillType());
fill = slides[2].getBackground().getFill();
assertEquals(Fill.FILL_TEXTURE, fill.getFillType());
shape = slides[2].getShapes()[0];
assertEquals(Fill.FILL_PICTURE, shape.getFill().getFillType());
fill = slides[3].getBackground().getFill();
assertEquals(Fill.FILL_SHADE_CENTER, fill.getFillType());
shape = slides[3].getShapes()[0];
assertEquals(Fill.FILL_SHADE, shape.getFill().getFillType());
}
}