View | Details | Raw Unified | Return to bug 55075
Collapse All | Expand All

(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java (-1 / +1 lines)
Lines 1704-1710 Link Here
1704
    @Override
1704
    @Override
1705
    public Drawing createDrawingPatriarch()
1705
    public Drawing createDrawingPatriarch()
1706
    {
1706
    {
1707
        return _sh.createDrawingPatriarch();
1707
        return new SXSSFDrawing((SXSSFWorkbook)getWorkbook(), _sh.createDrawingPatriarch());
1708
    }
1708
    }
1709
1709
1710
1710
(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFDrawing.java (+64 lines)
Line 0 Link Here
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
18
package org.apache.poi.xssf.streaming;
19
20
import org.apache.poi.ss.usermodel.Chart;
21
import org.apache.poi.ss.usermodel.ClientAnchor;
22
import org.apache.poi.ss.usermodel.Comment;
23
import org.apache.poi.ss.usermodel.Drawing;
24
import org.apache.poi.xssf.usermodel.XSSFDrawing;
25
import org.apache.poi.xssf.usermodel.XSSFPicture;
26
27
/**
28
 * Streaming version of Drawing.
29
 * Delegates most tasks to the non-streaming XSSF code.
30
 * TODO: Potentially, Comment and Chart need a similar streaming wrapper like Picture.
31
 * @author: Frank Plößel, Beyond Data GmbH
32
 */
33
public class SXSSFDrawing implements Drawing {
34
    private SXSSFWorkbook _wb;
35
    private XSSFDrawing _drawing;
36
37
    public SXSSFDrawing(SXSSFWorkbook workbook, XSSFDrawing drawing) {
38
        this._wb = workbook;
39
        this._drawing = drawing;
40
    }
41
42
    @Override
43
    public SXSSFPicture createPicture(ClientAnchor anchor, int pictureIndex) {
44
        XSSFPicture pict = _drawing.createPicture(anchor, pictureIndex);
45
        return new SXSSFPicture(_wb, pict);
46
    }
47
48
    @Override
49
    public Comment createCellComment(ClientAnchor anchor) {
50
        return _drawing.createCellComment(anchor);
51
    }
52
53
    @Override
54
    public Chart createChart(ClientAnchor anchor) {
55
        return _drawing.createChart(anchor);
56
    }
57
58
    @Override
59
    public ClientAnchor createAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2) {
60
        return _drawing.createAnchor(dx1, dy1, dx2, dy2, col1, row1, col2, row2);
61
    }
62
}
63
64
native
(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFPicture.java (+241 lines)
Line 0 Link Here
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
18
package org.apache.poi.xssf.streaming;
19
20
import org.apache.poi.openxml4j.opc.PackagePart;
21
import org.apache.poi.ss.usermodel.Picture;
22
import org.apache.poi.ss.usermodel.Row;
23
import org.apache.poi.ss.usermodel.Workbook;
24
import org.apache.poi.ss.util.ImageUtils;
25
import org.apache.poi.util.Internal;
26
import org.apache.poi.util.POILogFactory;
27
import org.apache.poi.util.POILogger;
28
import org.apache.poi.xssf.usermodel.*;
29
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
30
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
31
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTPicture;
32
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
33
34
import java.awt.*;
35
import java.io.IOException;
36
37
/**
38
 * Streaming version of Picture.
39
 * Most of the code is a copy of the non-streaming XSSFPicture code.
40
 * This is necessary as a private method getRowHeightInPixels of that class needs to be changed, which is called by a method call chain nested several levels.
41
 *
42
 * The main change is to access the rows in the SXSSF sheet, not the always empty rows in the XSSF sheet when checking the row heights.
43
 *
44
 * @author: Frank Plößel, Beyond Data GmbH
45
 */
46
public final class SXSSFPicture implements Picture {
47
    private static final POILogger logger = POILogFactory.getLogger(SXSSFPicture.class);
48
    /**
49
     * Column width measured as the number of characters of the maximum digit width of the
50
     * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin
51
     * padding (two on each side), plus 1 pixel padding for the gridlines.
52
     *
53
     * This value is the same for default font in Office 2007 (Calibry) and Office 2003 and earlier (Arial)
54
     */
55
    private static float DEFAULT_COLUMN_WIDTH = 9.140625f;
56
57
    private final SXSSFWorkbook _wb;
58
    private final XSSFPicture _picture;
59
60
    SXSSFPicture(SXSSFWorkbook _wb, XSSFPicture _picture) {
61
        this._wb = _wb;
62
        this._picture = _picture;
63
    }
64
65
    /**
66
     * Return the underlying CTPicture bean that holds all properties for this picture
67
     *
68
     * @return the underlying CTPicture bean
69
     */
70
    @Internal
71
    public CTPicture getCTPicture(){
72
        return _picture.getCTPicture();
73
    }
74
75
    /**
76
     * Reset the image to the original size.
77
     *
78
     * <p>
79
     * Please note, that this method works correctly only for workbooks
80
     * with the default font size (Calibri 11pt for .xlsx).
81
     * If the default font is changed the resized image can be streched vertically or horizontally.
82
     * </p>
83
     */
84
    public void resize(){
85
        resize(1.0);
86
    }
87
88
    /**
89
     * Reset the image to the original size.
90
     * <p>
91
     * Please note, that this method works correctly only for workbooks
92
     * with the default font size (Calibri 11pt for .xlsx).
93
     * If the default font is changed the resized image can be streched vertically or horizontally.
94
     * </p>
95
     *
96
     * @param scale the amount by which image dimensions are multiplied relative to the original size.
97
     * <code>resize(1.0)</code> sets the original size, <code>resize(0.5)</code> resize to 50% of the original,
98
     * <code>resize(2.0)</code> resizes to 200% of the original.
99
     */
100
    public void resize(double scale){
101
        XSSFClientAnchor anchor = getAnchor();
102
103
        XSSFClientAnchor pref = getPreferredSize(scale);
104
105
        int row2 = anchor.getRow1() + (pref.getRow2() - pref.getRow1());
106
        int col2 = anchor.getCol1() + (pref.getCol2() - pref.getCol1());
107
108
        anchor.setCol2(col2);
109
        anchor.setDx1(0);
110
        anchor.setDx2(pref.getDx2());
111
112
        anchor.setRow2(row2);
113
        anchor.setDy1(0);
114
        anchor.setDy2(pref.getDy2());
115
    }
116
117
    /**
118
     * Calculate the preferred size for this picture.
119
     *
120
     * @return XSSFClientAnchor with the preferred size for this image
121
     */
122
    public XSSFClientAnchor getPreferredSize(){
123
        return getPreferredSize(1);
124
    }
125
126
    /**
127
     * Calculate the preferred size for this picture.
128
     *
129
     * @param scale the amount by which image dimensions are multiplied relative to the original size.
130
     * @return XSSFClientAnchor with the preferred size for this image
131
     */
132
    public XSSFClientAnchor getPreferredSize(double scale){
133
        XSSFClientAnchor anchor = getAnchor();
134
135
        XSSFPictureData data = getPictureData();
136
        Dimension size = getImageDimension(data.getPackagePart(), data.getPictureType());
137
        double scaledWidth = size.getWidth() * scale;
138
        double scaledHeight = size.getHeight() * scale;
139
140
        float w = 0;
141
        int col2 = anchor.getCol1();
142
        int dx2 = 0;
143
144
        for (;;) {
145
            w += getColumnWidthInPixels(col2);
146
            if(w > scaledWidth) break;
147
            col2++;
148
        }
149
150
        if(w > scaledWidth) {
151
            double cw = getColumnWidthInPixels(col2 );
152
            double delta = w - scaledWidth;
153
            dx2 = (int)(XSSFShape.EMU_PER_PIXEL * (cw - delta));
154
        }
155
        anchor.setCol2(col2);
156
        anchor.setDx2(dx2);
157
158
        double h = 0;
159
        int row2 = anchor.getRow1();
160
        int dy2 = 0;
161
162
        for (;;) {
163
            h += getRowHeightInPixels(row2);
164
            if(h > scaledHeight) break;
165
            row2++;
166
        }
167
168
        if(h > scaledHeight) {
169
            double ch = getRowHeightInPixels(row2);
170
            double delta = h - scaledHeight;
171
            dy2 = (int)(XSSFShape.EMU_PER_PIXEL * (ch - delta));
172
        }
173
        anchor.setRow2(row2);
174
        anchor.setDy2(dy2);
175
176
        CTPositiveSize2D size2d =  getCTPicture().getSpPr().getXfrm().getExt();
177
        size2d.setCx((long)(scaledWidth * XSSFShape.EMU_PER_PIXEL));
178
        size2d.setCy((long)(scaledHeight * XSSFShape.EMU_PER_PIXEL));
179
180
        return anchor;
181
    }
182
183
    private float getColumnWidthInPixels(int columnIndex){
184
        XSSFSheet sheet = getParent();
185
186
        CTCol col = sheet.getColumnHelper().getColumn(columnIndex, false);
187
        double numChars = col == null || !col.isSetWidth() ? DEFAULT_COLUMN_WIDTH : col.getWidth();
188
189
        return (float)numChars*XSSFWorkbook.DEFAULT_CHARACTER_WIDTH;
190
    }
191
192
    private float getRowHeightInPixels(int rowIndex) {
193
        // THE FOLLOWING THREE LINES ARE THE MAIN CHANGE compared to the non-streaming version: use the SXSSF sheet,
194
		// not the XSSF sheet (which never contais rows when using SXSSF)
195
        XSSFSheet xssfSheet = getParent();
196
        SXSSFSheet sheet = _wb.getSXSSFSheet(xssfSheet);
197
        Row row = sheet.getRow(rowIndex);
198
        float height = row != null ?  row.getHeightInPoints() : sheet.getDefaultRowHeightInPoints();
199
        return height * XSSFShape.PIXEL_DPI / XSSFShape.POINT_DPI;
200
    }
201
    /**
202
     * Return the dimension of this image
203
     *
204
     * @param part the package part holding raw picture data
205
     * @param type type of the picture: {@link Workbook#PICTURE_TYPE_JPEG},
206
     * {@link Workbook#PICTURE_TYPE_PNG} or {@link Workbook#PICTURE_TYPE_DIB}
207
     *
208
     * @return image dimension in pixels
209
     */
210
    protected static Dimension getImageDimension(PackagePart part, int type){
211
        try {
212
            return ImageUtils.getImageDimension(part.getInputStream(), type);
213
        } catch (IOException e){
214
            //return a "singulariry" if ImageIO failed to read the image
215
            logger.log(POILogger.WARN, e);
216
            return new Dimension();
217
        }
218
    }
219
220
    /**
221
     * Return picture data for this shape
222
     *
223
     * @return picture data for this shape
224
     */
225
    public XSSFPictureData getPictureData() {
226
        return _picture.getPictureData();
227
    }
228
229
    protected CTShapeProperties getShapeProperties(){
230
        return getCTPicture().getSpPr();
231
    }
232
233
    private XSSFSheet getParent() {
234
        return (XSSFSheet)_picture.getDrawing().getParent();
235
    }
236
237
    private XSSFClientAnchor getAnchor() {
238
        return (XSSFClientAnchor)_picture.getAnchor();
239
    }
240
}
241
native

Return to bug 55075