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.

HSSFShapeFactory.java 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.poi.hssf.usermodel;
  18. import java.util.List;
  19. import java.util.Map;
  20. import org.apache.poi.ddf.EscherClientDataRecord;
  21. import org.apache.poi.ddf.EscherContainerRecord;
  22. import org.apache.poi.ddf.EscherOptRecord;
  23. import org.apache.poi.ddf.EscherProperty;
  24. import org.apache.poi.ddf.EscherPropertyTypes;
  25. import org.apache.poi.ddf.EscherRecord;
  26. import org.apache.poi.ddf.EscherRecordTypes;
  27. import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
  28. import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
  29. import org.apache.poi.hssf.record.EscherAggregate;
  30. import org.apache.poi.hssf.record.ObjRecord;
  31. import org.apache.poi.hssf.record.Record;
  32. import org.apache.poi.hssf.record.SubRecord;
  33. import org.apache.poi.hssf.record.TextObjectRecord;
  34. import org.apache.poi.poifs.filesystem.DirectoryNode;
  35. import org.apache.poi.util.RecordFormatException;
  36. /**
  37. * Factory class for producing Excel Shapes from Escher records
  38. */
  39. public class HSSFShapeFactory {
  40. /**
  41. * build shape tree from escher container
  42. * @param container root escher container from which escher records must be taken
  43. * @param agg - EscherAggregate
  44. * @param out - shape container to which shapes must be added
  45. * @param root - node to create HSSFObjectData shapes
  46. */
  47. public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out, DirectoryNode root) {
  48. if (container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) {
  49. ObjRecord obj = null;
  50. EscherRecord child = container.getChild(0);
  51. if (!(child instanceof EscherContainerRecord)) {
  52. throw new IllegalArgumentException("Had unexpected type of child: " + child.getClass());
  53. }
  54. EscherClientDataRecord clientData = ((EscherContainerRecord) child).getChildById(EscherClientDataRecord.RECORD_ID);
  55. if (null != clientData) {
  56. obj = (ObjRecord) agg.getShapeToObjMapping().get(clientData);
  57. }
  58. HSSFShapeGroup group = new HSSFShapeGroup(container, obj);
  59. List<EscherContainerRecord> children = container.getChildContainers();
  60. // skip the first child record, it is group descriptor
  61. if (children.size() > 1) {
  62. children.subList(1, children.size()).forEach(c -> createShapeTree(c, agg, group, root));
  63. }
  64. out.addShape(group);
  65. } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
  66. Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping();
  67. ObjRecord objRecord = null;
  68. TextObjectRecord txtRecord = null;
  69. for (EscherRecord record : container) {
  70. switch (EscherRecordTypes.forTypeID(record.getRecordId())) {
  71. case CLIENT_DATA: {
  72. Record subRecord = shapeToObj.get(record);
  73. if (!(subRecord instanceof ObjRecord)) {
  74. throw new RecordFormatException("Did not have a ObjRecord: " + subRecord);
  75. }
  76. objRecord = (ObjRecord) subRecord;
  77. break;
  78. }
  79. case CLIENT_TEXTBOX: {
  80. Record subRecord = shapeToObj.get(record);
  81. if (!(subRecord instanceof TextObjectRecord)) {
  82. throw new RecordFormatException("Did not have a TextObjRecord: " + subRecord);
  83. }
  84. txtRecord = (TextObjectRecord) subRecord;
  85. break;
  86. }
  87. default:
  88. break;
  89. }
  90. }
  91. if (objRecord == null) {
  92. throw new RecordFormatException("EscherClientDataRecord can't be found.");
  93. }
  94. if (isEmbeddedObject(objRecord)) {
  95. HSSFObjectData objectData = new HSSFObjectData(container, objRecord, root);
  96. out.addShape(objectData);
  97. return;
  98. }
  99. CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord) objRecord.getSubRecords().get(0);
  100. final HSSFShape shape;
  101. switch (cmo.getObjectType()) {
  102. case CommonObjectDataSubRecord.OBJECT_TYPE_PICTURE:
  103. shape = new HSSFPicture(container, objRecord);
  104. break;
  105. case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE:
  106. shape = new HSSFSimpleShape(container, objRecord, txtRecord);
  107. break;
  108. case CommonObjectDataSubRecord.OBJECT_TYPE_LINE:
  109. shape = new HSSFSimpleShape(container, objRecord);
  110. break;
  111. case CommonObjectDataSubRecord.OBJECT_TYPE_COMBO_BOX:
  112. shape = new HSSFCombobox(container, objRecord);
  113. break;
  114. case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:
  115. EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
  116. if(optRecord == null) {
  117. shape = new HSSFSimpleShape(container, objRecord, txtRecord);
  118. } else {
  119. EscherProperty property = optRecord.lookup(EscherPropertyTypes.GEOMETRY__VERTICES);
  120. if (null != property) {
  121. shape = new HSSFPolygon(container, objRecord, txtRecord);
  122. } else {
  123. shape = new HSSFSimpleShape(container, objRecord, txtRecord);
  124. }
  125. }
  126. break;
  127. case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT:
  128. shape = new HSSFTextbox(container, objRecord, txtRecord);
  129. break;
  130. case CommonObjectDataSubRecord.OBJECT_TYPE_COMMENT:
  131. shape = new HSSFComment(container, objRecord, txtRecord, agg.getNoteRecordByObj(objRecord));
  132. break;
  133. default:
  134. shape = new HSSFSimpleShape(container, objRecord, txtRecord);
  135. }
  136. out.addShape(shape);
  137. }
  138. }
  139. private static boolean isEmbeddedObject(ObjRecord obj) {
  140. for (SubRecord sub : obj.getSubRecords()) {
  141. if (sub instanceof EmbeddedObjectRefSubRecord) {
  142. return true;
  143. }
  144. }
  145. return false;
  146. }
  147. }