001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.model;
019:
020: import org.apache.poi.ddf.EscherDggRecord;
021: import org.apache.poi.ddf.EscherDgRecord;
022:
023: import java.util.Map;
024: import java.util.HashMap;
025:
026: /**
027: * Provides utilities to manage drawing groups.
028: *
029: * @author Glen Stampoultzis (glens at apache.org)
030: */
031: public class DrawingManager {
032: EscherDggRecord dgg;
033: Map dgMap = new HashMap(); // key = Short(drawingId), value=EscherDgRecord
034:
035: public DrawingManager(EscherDggRecord dgg) {
036: this .dgg = dgg;
037: }
038:
039: public EscherDgRecord createDgRecord() {
040: EscherDgRecord dg = new EscherDgRecord();
041: dg.setRecordId(EscherDgRecord.RECORD_ID);
042: short dgId = findNewDrawingGroupId();
043: dg.setOptions((short) (dgId << 4));
044: dg.setNumShapes(0);
045: dg.setLastMSOSPID(-1);
046: dgg.addCluster(dgId, 0);
047: dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1);
048: dgMap.put(new Short(dgId), dg);
049: return dg;
050: }
051:
052: /**
053: * Allocates new shape id for the new drawing group id.
054: *
055: * @return a new shape id.
056: */
057: public int allocateShapeId(short drawingGroupId) {
058: // Get the last shape id for this drawing group.
059: EscherDgRecord dg = (EscherDgRecord) dgMap.get(new Short(
060: drawingGroupId));
061: int lastShapeId = dg.getLastMSOSPID();
062:
063: // Have we run out of shapes for this cluster?
064: int newShapeId = 0;
065: if (lastShapeId % 1024 == 1023) {
066: // Yes:
067: // Find the starting shape id of the next free cluster
068: newShapeId = findFreeSPIDBlock();
069: // Create a new cluster in the dgg record.
070: dgg.addCluster(drawingGroupId, 1);
071: } else {
072: // No:
073: // Find the cluster for this drawing group with free space.
074: for (int i = 0; i < dgg.getFileIdClusters().length; i++) {
075: EscherDggRecord.FileIdCluster c = dgg
076: .getFileIdClusters()[i];
077: if (c.getDrawingGroupId() == drawingGroupId) {
078: if (c.getNumShapeIdsUsed() != 1024) {
079: // Increment the number of shapes used for this cluster.
080: c.incrementShapeId();
081: }
082: }
083: // If the last shape id = -1 then we know to find a free block;
084: if (dg.getLastMSOSPID() == -1) {
085: newShapeId = findFreeSPIDBlock();
086: } else {
087: // The new shape id to be the last shapeid of this cluster + 1
088: newShapeId = dg.getLastMSOSPID() + 1;
089: }
090: }
091: }
092: // Increment the total number of shapes used in the dgg.
093: dgg.setNumShapesSaved(dgg.getNumShapesSaved() + 1);
094: // Is the new shape id >= max shape id for dgg?
095: if (newShapeId >= dgg.getShapeIdMax()) {
096: // Yes:
097: // Set the max shape id = new shape id + 1
098: dgg.setShapeIdMax(newShapeId + 1);
099: }
100: // Set last shape id for this drawing group.
101: dg.setLastMSOSPID(newShapeId);
102: // Increased the number of shapes used for this drawing group.
103: dg.incrementShapeCount();
104:
105: return newShapeId;
106: }
107:
108: //////////// Non-public methods /////////////
109: short findNewDrawingGroupId() {
110: short dgId = 1;
111: while (drawingGroupExists(dgId))
112: dgId++;
113: return dgId;
114: }
115:
116: boolean drawingGroupExists(short dgId) {
117: for (int i = 0; i < dgg.getFileIdClusters().length; i++) {
118: if (dgg.getFileIdClusters()[i].getDrawingGroupId() == dgId)
119: return true;
120: }
121: return false;
122: }
123:
124: int findFreeSPIDBlock() {
125: int max = dgg.getShapeIdMax();
126: int next = ((max / 1024) + 1) * 1024;
127: return next;
128: }
129:
130: public EscherDggRecord getDgg() {
131: return dgg;
132: }
133:
134: }
|