You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HSLFFill.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hslf.usermodel;
  16. import java.awt.Color;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.InputStream;
  19. import java.util.List;
  20. import org.apache.poi.ddf.*;
  21. import org.apache.poi.hslf.record.Document;
  22. import org.apache.poi.sl.usermodel.*;
  23. import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
  24. import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
  25. import org.apache.poi.util.POILogFactory;
  26. import org.apache.poi.util.POILogger;
  27. /**
  28. * Represents functionality provided by the 'Fill Effects' dialog in PowerPoint.
  29. *
  30. * @author Yegor Kozlov
  31. */
  32. public final class HSLFFill {
  33. // For logging
  34. protected POILogger logger = POILogFactory.getLogger(this.getClass());
  35. /**
  36. * Fill with a solid color
  37. */
  38. public static final int FILL_SOLID = 0;
  39. /**
  40. * Fill with a pattern (bitmap)
  41. */
  42. public static final int FILL_PATTERN = 1;
  43. /**
  44. * A texture (pattern with its own color map)
  45. */
  46. public static final int FILL_TEXTURE = 2;
  47. /**
  48. * Center a picture in the shape
  49. */
  50. public static final int FILL_PICTURE = 3;
  51. /**
  52. * Shade from start to end points
  53. */
  54. public static final int FILL_SHADE = 4;
  55. /**
  56. * Shade from bounding rectangle to end point
  57. */
  58. public static final int FILL_SHADE_CENTER = 5;
  59. /**
  60. * Shade from shape outline to end point
  61. */
  62. public static final int FILL_SHADE_SHAPE = 6;
  63. /**
  64. * Similar to FILL_SHADE, but the fill angle
  65. * is additionally scaled by the aspect ratio of
  66. * the shape. If shape is square, it is the same as FILL_SHADE
  67. */
  68. public static final int FILL_SHADE_SCALE = 7;
  69. /**
  70. * shade to title
  71. */
  72. public static final int FILL_SHADE_TITLE = 8;
  73. /**
  74. * Use the background fill color/pattern
  75. */
  76. public static final int FILL_BACKGROUND = 9;
  77. /**
  78. * The shape this background applies to
  79. */
  80. protected HSLFShape shape;
  81. /**
  82. * Construct a <code>Fill</code> object for a shape.
  83. * Fill information will be read from shape's escher properties.
  84. *
  85. * @param shape the shape this background applies to
  86. */
  87. public HSLFFill(HSLFShape shape){
  88. this.shape = shape;
  89. }
  90. public FillStyle getFillStyle() {
  91. return new FillStyle() {
  92. public PaintStyle getPaint() {
  93. switch (getFillType()) {
  94. case FILL_SOLID: {
  95. return new SolidPaint() {
  96. public ColorStyle getSolidColor() {
  97. return new ColorStyle() {
  98. public Color getColor() { return getForegroundColor(); }
  99. public int getAlpha() { return -1; }
  100. public int getLumOff() { return -1; }
  101. public int getLumMod() { return -1; }
  102. public int getShade() { return -1; }
  103. public int getTint() { return -1; }
  104. };
  105. }
  106. };
  107. }
  108. case FILL_PICTURE: {
  109. final HSLFPictureData pd = getPictureData();
  110. if (pd == null) break;
  111. return new TexturePaint() {
  112. public InputStream getImageData() {
  113. return new ByteArrayInputStream(pd.getData());
  114. }
  115. public String getContentType() {
  116. return pd.getContentType();
  117. }
  118. public int getAlpha() {
  119. return (int)(shape.getAlpha(EscherProperties.FILL__FILLOPACITY)*100000.0);
  120. }
  121. };
  122. }
  123. default:
  124. logger.log(POILogger.WARN, "unsuported fill type: " + getFillType());
  125. break;
  126. }
  127. return PaintStyle.TRANSPARENT_PAINT;
  128. }
  129. };
  130. }
  131. /**
  132. * Returns fill type.
  133. * Must be one of the <code>FILL_*</code> constants defined in this class.
  134. *
  135. * @return type of fill
  136. */
  137. public int getFillType(){
  138. EscherOptRecord opt = shape.getEscherOptRecord();
  139. EscherSimpleProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__FILLTYPE);
  140. return prop == null ? FILL_SOLID : prop.getPropertyValue();
  141. }
  142. /**
  143. */
  144. protected void afterInsert(HSLFSheet sh){
  145. EscherOptRecord opt = shape.getEscherOptRecord();
  146. EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE);
  147. if(p != null) {
  148. int idx = p.getPropertyValue();
  149. EscherBSERecord bse = getEscherBSERecord(idx);
  150. bse.setRef(bse.getRef() + 1);
  151. }
  152. }
  153. protected EscherBSERecord getEscherBSERecord(int idx){
  154. HSLFSheet sheet = shape.getSheet();
  155. if(sheet == null) {
  156. logger.log(POILogger.DEBUG, "Fill has not yet been assigned to a sheet");
  157. return null;
  158. }
  159. HSLFSlideShow ppt = sheet.getSlideShow();
  160. Document doc = ppt.getDocumentRecord();
  161. EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
  162. EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
  163. if(bstore == null) {
  164. logger.log(POILogger.DEBUG, "EscherContainerRecord.BSTORE_CONTAINER was not found ");
  165. return null;
  166. }
  167. List<EscherRecord> lst = bstore.getChildRecords();
  168. return (EscherBSERecord)lst.get(idx-1);
  169. }
  170. /**
  171. * Sets fill type.
  172. * Must be one of the <code>FILL_*</code> constants defined in this class.
  173. *
  174. * @param type type of the fill
  175. */
  176. public void setFillType(int type){
  177. EscherOptRecord opt = shape.getEscherOptRecord();
  178. HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLTYPE, type);
  179. }
  180. /**
  181. * Foreground color
  182. */
  183. public Color getForegroundColor(){
  184. EscherOptRecord opt = shape.getEscherOptRecord();
  185. EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST);
  186. if(p != null && (p.getPropertyValue() & 0x10) == 0) return null;
  187. return shape.getColor(EscherProperties.FILL__FILLCOLOR, EscherProperties.FILL__FILLOPACITY, -1);
  188. }
  189. /**
  190. * Foreground color
  191. */
  192. public void setForegroundColor(Color color){
  193. EscherOptRecord opt = shape.getEscherOptRecord();
  194. if (color == null) {
  195. HSLFShape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150000);
  196. }
  197. else {
  198. int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
  199. HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);
  200. HSLFShape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150011);
  201. }
  202. }
  203. /**
  204. * Background color
  205. */
  206. public Color getBackgroundColor(){
  207. EscherOptRecord opt = shape.getEscherOptRecord();
  208. EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST);
  209. if(p != null && (p.getPropertyValue() & 0x10) == 0) return null;
  210. return shape.getColor(EscherProperties.FILL__FILLBACKCOLOR, EscherProperties.FILL__FILLOPACITY, -1);
  211. }
  212. /**
  213. * Background color
  214. */
  215. public void setBackgroundColor(Color color){
  216. EscherOptRecord opt = shape.getEscherOptRecord();
  217. if (color == null) {
  218. HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, -1);
  219. }
  220. else {
  221. int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();
  222. HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb);
  223. }
  224. }
  225. /**
  226. * <code>PictureData</code> object used in a texture, pattern of picture fill.
  227. */
  228. public HSLFPictureData getPictureData(){
  229. EscherOptRecord opt = shape.getEscherOptRecord();
  230. EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE);
  231. if (p == null) return null;
  232. HSLFSlideShow ppt = shape.getSheet().getSlideShow();
  233. HSLFPictureData[] pict = ppt.getPictureData();
  234. Document doc = ppt.getDocumentRecord();
  235. EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
  236. EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
  237. java.util.List<EscherRecord> lst = bstore.getChildRecords();
  238. int idx = p.getPropertyValue();
  239. if (idx == 0){
  240. logger.log(POILogger.WARN, "no reference to picture data found ");
  241. } else {
  242. EscherBSERecord bse = (EscherBSERecord)lst.get(idx - 1);
  243. for ( int i = 0; i < pict.length; i++ ) {
  244. if (pict[i].getOffset() == bse.getOffset()){
  245. return pict[i];
  246. }
  247. }
  248. }
  249. return null;
  250. }
  251. /**
  252. * Assign picture used to fill the underlying shape.
  253. *
  254. * @param idx 0-based index of the picture added to this ppt by <code>SlideShow.addPicture</code> method.
  255. */
  256. public void setPictureData(int idx){
  257. EscherOptRecord opt = shape.getEscherOptRecord();
  258. HSLFShape.setEscherProperty(opt, (short)(EscherProperties.FILL__PATTERNTEXTURE + 0x4000), idx);
  259. if( idx != 0 ) {
  260. if( shape.getSheet() != null ) {
  261. EscherBSERecord bse = getEscherBSERecord(idx);
  262. bse.setRef(bse.getRef() + 1);
  263. }
  264. }
  265. }
  266. }