Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "generic/glyphcache.hxx"
31 : : #include <string.h>
32 : :
33 : : //------------------------------------------------------------------------
34 : :
35 : 1958267 : RawBitmap::RawBitmap()
36 : 1958267 : : mpBits(0), mnAllocated(0)
37 : 1958267 : {}
38 : :
39 : : //------------------------------------------------------------------------
40 : :
41 : 865 : RawBitmap::~RawBitmap()
42 : : {
43 [ - + ]: 865 : delete[] mpBits;
44 : 865 : mpBits = 0;
45 : 865 : mnAllocated = 0;
46 : 865 : }
47 : :
48 : : //------------------------------------------------------------------------
49 : :
50 : : // used by 90 and 270 degree rotations on 8 bit deep bitmaps
51 : 23891 : static void ImplRotate8_90( unsigned char* p1, const unsigned char* p2,
52 : : int xmax, int ymax, int dx, int dy, int nPad )
53 : : {
54 [ + + ]: 333044 : for( int y = ymax; --y >= 0; p2 += dy )
55 : : {
56 [ + + ]: 10462511 : for( int x = xmax; --x >= 0; p2 += dx )
57 : 10153358 : *(p1++) = *p2;
58 [ + + ]: 634779 : for( int i = nPad; --i >= 0; )
59 : 325626 : *(p1++) = 0;
60 : : }
61 : 23891 : }
62 : :
63 : : //------------------------------------------------------------------------
64 : :
65 : : // used by inplace 180 degree rotation on 8 bit deep bitmaps
66 : 0 : static void ImplRotate8_180( unsigned char* p1, int xmax, int ymax, int nPad )
67 : : {
68 : 0 : unsigned char* p2 = p1 + ymax * (xmax + nPad);
69 [ # # ]: 0 : for( int y = ymax/2; --y >= 0; )
70 : : {
71 : 0 : p2 -= nPad;
72 [ # # ]: 0 : for( int x = xmax; --x >= 0; )
73 : : {
74 : 0 : unsigned char cTmp = *(--p2);
75 : 0 : *p2 = *p1;
76 : 0 : *(p1++) = cTmp;
77 : : }
78 : 0 : p1 += nPad;
79 : : }
80 : :
81 : : // reverse middle line
82 : 0 : p2 -= nPad;
83 [ # # ]: 0 : while( p1 < p2 )
84 : : {
85 : 0 : unsigned char cTmp = *(--p2);
86 : 0 : *p2 = *p1;
87 : 0 : *(p1++) = cTmp;
88 : : }
89 : 0 : }
90 : :
91 : : //------------------------------------------------------------------------
92 : :
93 : : // used by 90 or 270 degree rotations on 1 bit deep bitmaps
94 : 0 : static void ImplRotate1_90( unsigned char* p1, const unsigned char* p2,
95 : : int xmax, int ymax, int dx, int nShift, int nDeltaShift, int nPad )
96 : : {
97 [ # # ]: 0 : for( int y = ymax; --y >= 0; )
98 : : {
99 : 0 : unsigned nTemp = 1;
100 : 0 : const unsigned char* p20 = p2;
101 [ # # ]: 0 : for( int x = xmax; --x >= 0; p2 += dx )
102 : : {
103 : : // build bitwise and store when byte finished
104 : 0 : nTemp += nTemp + ((*p2 >> nShift) & 1);
105 [ # # ]: 0 : if( nTemp >= 0x100U )
106 : : {
107 : 0 : *(p1++) = (unsigned char)nTemp;
108 : 0 : nTemp = 1;
109 : : }
110 : : }
111 : 0 : p2 = p20;
112 : :
113 : : // store left aligned remainder if needed
114 [ # # ]: 0 : if( nTemp > 1 )
115 : : {
116 [ # # ]: 0 : for(; nTemp < 0x100U; nTemp += nTemp ) ;
117 : 0 : *(p1++) = (unsigned char)nTemp;
118 : : }
119 : : // pad scanline with zeroes
120 [ # # ]: 0 : for( int i = nPad; --i >= 0;)
121 : 0 : *(p1++) = 0;
122 : :
123 : : // increase/decrease shift, but keep bound inside 0 to 7
124 : 0 : nShift += nDeltaShift;
125 [ # # ]: 0 : if( nShift != (nShift & 7) )
126 : 0 : p2 -= nDeltaShift;
127 : 0 : nShift &= 7;
128 : : }
129 : 0 : }
130 : :
131 : : //------------------------------------------------------------------------
132 : :
133 : : // used by 180 degrees rotations on 1 bit deep bitmaps
134 : 0 : static void ImplRotate1_180( unsigned char* p1, const unsigned char* p2,
135 : : int xmax, int ymax, int nPad )
136 : : {
137 : 0 : --p2;
138 [ # # ]: 0 : for( int y = ymax; --y >= 0; )
139 : : {
140 : 0 : p2 -= nPad;
141 : :
142 : 0 : unsigned nTemp = 1;
143 : 0 : unsigned nInp = (0x100 + *p2) >> (-xmax & 7);
144 [ # # ]: 0 : for( int x = xmax; --x >= 0; )
145 : : {
146 : : // build bitwise and store when byte finished
147 : 0 : nTemp += nTemp + (nInp & 1);
148 [ # # ]: 0 : if( nTemp >= 0x100 )
149 : : {
150 : 0 : *(p1++) = (unsigned char)nTemp;
151 : 0 : nTemp = 1;
152 : : }
153 : : // update input byte if needed (and available)
154 [ # # ][ # # ]: 0 : if( (nInp >>= 1) <= 1 && ((y != 0) || (x != 0)) )
[ # # ][ # # ]
155 : 0 : nInp = 0x100 + *(--p2);
156 : : }
157 : :
158 : : // store left aligned remainder if needed
159 [ # # ]: 0 : if( nTemp > 1 )
160 : : {
161 [ # # ]: 0 : for(; nTemp < 0x100; nTemp += nTemp ) ;
162 : 0 : *(p1++) = (unsigned char)nTemp;
163 : : }
164 : : // scanline pad is already clean
165 : 0 : p1 += nPad;
166 : : }
167 : 0 : }
168 : :
169 : : //------------------------------------------------------------------------
170 : :
171 : 23891 : bool RawBitmap::Rotate( int nAngle )
172 : : {
173 : 23891 : sal_uLong nNewScanlineSize = 0;
174 : 23891 : sal_uLong nNewHeight = 0;
175 : 23891 : sal_uLong nNewWidth = 0;
176 : :
177 : : // do inplace rotation or prepare double buffered rotation
178 [ - - - + ]: 23891 : switch( nAngle )
179 : : {
180 : : case 0: // nothing to do
181 : : case 3600:
182 : 0 : return true;
183 : : default: // non rectangular angles not allowed
184 : 0 : return false;
185 : : case 1800: // rotate by 180 degrees
186 : 0 : mnXOffset = -(mnXOffset + mnWidth);
187 : 0 : mnYOffset = -(mnYOffset + mnHeight);
188 [ # # ]: 0 : if( mnBitCount == 8 )
189 : : {
190 : 0 : ImplRotate8_180( mpBits, mnWidth, mnHeight, mnScanlineSize-mnWidth );
191 : 0 : return true;
192 : : }
193 : 0 : nNewWidth = mnWidth;
194 : 0 : nNewHeight = mnHeight;
195 : 0 : nNewScanlineSize = mnScanlineSize;
196 : 0 : break;
197 : : case +900: // left by 90 degrees
198 : : case -900:
199 : : case 2700: // right by 90 degrees
200 : 23891 : nNewWidth = mnHeight;
201 : 23891 : nNewHeight = mnWidth;
202 [ - + ]: 23891 : if( mnBitCount==1 )
203 : 0 : nNewScanlineSize = (nNewWidth + 7) / 8;
204 : : else
205 : 23891 : nNewScanlineSize = (nNewWidth + 3) & -4;
206 : 23891 : break;
207 : : }
208 : :
209 : 23891 : unsigned int nBufSize = nNewHeight * nNewScanlineSize;
210 : 23891 : unsigned char* pBuf = new unsigned char[ nBufSize ];
211 [ - + ]: 23891 : if( !pBuf )
212 : 0 : return false;
213 : :
214 : 23891 : memset( pBuf, 0, nBufSize );
215 : : int i;
216 : :
217 : : // dispatch non-inplace rotations
218 [ - + + - ]: 23891 : switch( nAngle )
219 : : {
220 : : case 1800: // rotate by 180 degrees
221 : : // we know we only need to deal with 1 bit depth
222 : : ImplRotate1_180( pBuf, mpBits + mnHeight * mnScanlineSize,
223 : 0 : mnWidth, mnHeight, mnScanlineSize - (mnWidth + 7) / 8 );
224 : 0 : break;
225 : : case +900: // rotate left by 90 degrees
226 : 16745 : i = mnXOffset;
227 : 16745 : mnXOffset = mnYOffset;
228 : 16745 : mnYOffset = -nNewHeight - i;
229 [ + - ]: 16745 : if( mnBitCount == 8 )
230 : 16745 : ImplRotate8_90( pBuf, mpBits + mnWidth - 1,
231 : : nNewWidth, nNewHeight, +mnScanlineSize, -1-mnHeight*mnScanlineSize,
232 : 16745 : nNewScanlineSize - nNewWidth );
233 : : else
234 : : ImplRotate1_90( pBuf, mpBits + (mnWidth - 1) / 8,
235 : : nNewWidth, nNewHeight, +mnScanlineSize,
236 : 0 : (-mnWidth & 7), +1, nNewScanlineSize - (nNewWidth + 7) / 8 );
237 : 16745 : break;
238 : : case 2700: // rotate right by 90 degrees
239 : : case -900:
240 : 7146 : i = mnXOffset;
241 : 7146 : mnXOffset = -(nNewWidth + mnYOffset);
242 : 7146 : mnYOffset = i;
243 [ + - ]: 7146 : if( mnBitCount == 8 )
244 : : ImplRotate8_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
245 : : nNewWidth, nNewHeight, -mnScanlineSize, +1+mnHeight*mnScanlineSize,
246 : 7146 : nNewScanlineSize - nNewWidth );
247 : : else
248 : : ImplRotate1_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
249 : : nNewWidth, nNewHeight, -mnScanlineSize,
250 : 0 : +7, -1, nNewScanlineSize - (nNewWidth + 7) / 8 );
251 : 7146 : break;
252 : : }
253 : :
254 : 23891 : mnWidth = nNewWidth;
255 : 23891 : mnHeight = nNewHeight;
256 : 23891 : mnScanlineSize = nNewScanlineSize;
257 : :
258 [ + - ]: 23891 : if( nBufSize < mnAllocated )
259 : : {
260 : 23891 : memcpy( mpBits, pBuf, nBufSize );
261 [ + - ]: 23891 : delete[] pBuf;
262 : : }
263 : : else
264 : : {
265 [ # # ]: 0 : delete[] mpBits;
266 : 0 : mpBits = pBuf;
267 : 0 : mnAllocated = nBufSize;
268 : : }
269 : :
270 : 23891 : return true;
271 : : }
272 : :
273 : : //------------------------------------------------------------------------
274 : :
275 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|