Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "generic/glyphcache.hxx"
22 : #include <string.h>
23 :
24 : //------------------------------------------------------------------------
25 :
26 17149 : RawBitmap::RawBitmap()
27 17149 : : mpBits(0), mnAllocated(0)
28 17149 : {}
29 :
30 : //------------------------------------------------------------------------
31 :
32 259 : RawBitmap::~RawBitmap()
33 : {
34 259 : delete[] mpBits;
35 259 : mpBits = 0;
36 259 : mnAllocated = 0;
37 259 : }
38 :
39 : //------------------------------------------------------------------------
40 :
41 : // used by 90 and 270 degree rotations on 8 bit deep bitmaps
42 2140 : static void ImplRotate8_90( unsigned char* p1, const unsigned char* p2,
43 : int xmax, int ymax, int dx, int dy, int nPad )
44 : {
45 13886 : for( int y = ymax; --y >= 0; p2 += dy )
46 : {
47 105714 : for( int x = xmax; --x >= 0; p2 += dx )
48 93968 : *(p1++) = *p2;
49 23492 : for( int i = nPad; --i >= 0; )
50 0 : *(p1++) = 0;
51 : }
52 2140 : }
53 :
54 : //------------------------------------------------------------------------
55 :
56 : // used by inplace 180 degree rotation on 8 bit deep bitmaps
57 0 : static void ImplRotate8_180( unsigned char* p1, int xmax, int ymax, int nPad )
58 : {
59 0 : unsigned char* p2 = p1 + ymax * (xmax + nPad);
60 0 : for( int y = ymax/2; --y >= 0; )
61 : {
62 0 : p2 -= nPad;
63 0 : for( int x = xmax; --x >= 0; )
64 : {
65 0 : unsigned char cTmp = *(--p2);
66 0 : *p2 = *p1;
67 0 : *(p1++) = cTmp;
68 : }
69 0 : p1 += nPad;
70 : }
71 :
72 : // reverse middle line
73 0 : p2 -= nPad;
74 0 : while( p1 < p2 )
75 : {
76 0 : unsigned char cTmp = *(--p2);
77 0 : *p2 = *p1;
78 0 : *(p1++) = cTmp;
79 : }
80 0 : }
81 :
82 : //------------------------------------------------------------------------
83 :
84 : // used by 90 or 270 degree rotations on 1 bit deep bitmaps
85 0 : static void ImplRotate1_90( unsigned char* p1, const unsigned char* p2,
86 : int xmax, int ymax, int dx, int nShift, int nDeltaShift, int nPad )
87 : {
88 0 : for( int y = ymax; --y >= 0; )
89 : {
90 0 : unsigned nTemp = 1;
91 0 : const unsigned char* p20 = p2;
92 0 : for( int x = xmax; --x >= 0; p2 += dx )
93 : {
94 : // build bitwise and store when byte finished
95 0 : nTemp += nTemp + ((*p2 >> nShift) & 1);
96 0 : if( nTemp >= 0x100U )
97 : {
98 0 : *(p1++) = (unsigned char)nTemp;
99 0 : nTemp = 1;
100 : }
101 : }
102 0 : p2 = p20;
103 :
104 : // store left aligned remainder if needed
105 0 : if( nTemp > 1 )
106 : {
107 0 : for(; nTemp < 0x100U; nTemp += nTemp ) ;
108 0 : *(p1++) = (unsigned char)nTemp;
109 : }
110 : // pad scanline with zeroes
111 0 : for( int i = nPad; --i >= 0;)
112 0 : *(p1++) = 0;
113 :
114 : // increase/decrease shift, but keep bound inside 0 to 7
115 0 : nShift += nDeltaShift;
116 0 : if( nShift != (nShift & 7) )
117 0 : p2 -= nDeltaShift;
118 0 : nShift &= 7;
119 : }
120 0 : }
121 :
122 : //------------------------------------------------------------------------
123 :
124 : // used by 180 degrees rotations on 1 bit deep bitmaps
125 0 : static void ImplRotate1_180( unsigned char* p1, const unsigned char* p2,
126 : int xmax, int ymax, int nPad )
127 : {
128 0 : --p2;
129 0 : for( int y = ymax; --y >= 0; )
130 : {
131 0 : p2 -= nPad;
132 :
133 0 : unsigned nTemp = 1;
134 0 : unsigned nInp = (0x100 + *p2) >> (-xmax & 7);
135 0 : for( int x = xmax; --x >= 0; )
136 : {
137 : // build bitwise and store when byte finished
138 0 : nTemp += nTemp + (nInp & 1);
139 0 : if( nTemp >= 0x100 )
140 : {
141 0 : *(p1++) = (unsigned char)nTemp;
142 0 : nTemp = 1;
143 : }
144 : // update input byte if needed (and available)
145 0 : if( (nInp >>= 1) <= 1 && ((y != 0) || (x != 0)) )
146 0 : nInp = 0x100 + *(--p2);
147 : }
148 :
149 : // store left aligned remainder if needed
150 0 : if( nTemp > 1 )
151 : {
152 0 : for(; nTemp < 0x100; nTemp += nTemp ) ;
153 0 : *(p1++) = (unsigned char)nTemp;
154 : }
155 : // scanline pad is already clean
156 0 : p1 += nPad;
157 : }
158 0 : }
159 :
160 : //------------------------------------------------------------------------
161 :
162 2140 : bool RawBitmap::Rotate( int nAngle )
163 : {
164 2140 : sal_uLong nNewScanlineSize = 0;
165 2140 : sal_uLong nNewHeight = 0;
166 2140 : sal_uLong nNewWidth = 0;
167 :
168 : // do inplace rotation or prepare double buffered rotation
169 2140 : switch( nAngle )
170 : {
171 : case 0: // nothing to do
172 : case 3600:
173 0 : return true;
174 : default: // non rectangular angles not allowed
175 0 : return false;
176 : case 1800: // rotate by 180 degrees
177 0 : mnXOffset = -(mnXOffset + mnWidth);
178 0 : mnYOffset = -(mnYOffset + mnHeight);
179 0 : if( mnBitCount == 8 )
180 : {
181 0 : ImplRotate8_180( mpBits, mnWidth, mnHeight, mnScanlineSize-mnWidth );
182 0 : return true;
183 : }
184 0 : nNewWidth = mnWidth;
185 0 : nNewHeight = mnHeight;
186 0 : nNewScanlineSize = mnScanlineSize;
187 0 : break;
188 : case +900: // left by 90 degrees
189 : case -900:
190 : case 2700: // right by 90 degrees
191 2140 : nNewWidth = mnHeight;
192 2140 : nNewHeight = mnWidth;
193 2140 : if( mnBitCount==1 )
194 0 : nNewScanlineSize = (nNewWidth + 7) / 8;
195 : else
196 2140 : nNewScanlineSize = (nNewWidth + 3) & -4;
197 2140 : break;
198 : }
199 :
200 2140 : unsigned int nBufSize = nNewHeight * nNewScanlineSize;
201 2140 : unsigned char* pBuf = new unsigned char[ nBufSize ];
202 2140 : if( !pBuf )
203 0 : return false;
204 :
205 2140 : memset( pBuf, 0, nBufSize );
206 : int i;
207 :
208 : // dispatch non-inplace rotations
209 2140 : switch( nAngle )
210 : {
211 : case 1800: // rotate by 180 degrees
212 : // we know we only need to deal with 1 bit depth
213 : ImplRotate1_180( pBuf, mpBits + mnHeight * mnScanlineSize,
214 0 : mnWidth, mnHeight, mnScanlineSize - (mnWidth + 7) / 8 );
215 0 : break;
216 : case +900: // rotate left by 90 degrees
217 2140 : i = mnXOffset;
218 2140 : mnXOffset = mnYOffset;
219 2140 : mnYOffset = -nNewHeight - i;
220 2140 : if( mnBitCount == 8 )
221 2140 : ImplRotate8_90( pBuf, mpBits + mnWidth - 1,
222 : nNewWidth, nNewHeight, +mnScanlineSize, -1-mnHeight*mnScanlineSize,
223 4280 : nNewScanlineSize - nNewWidth );
224 : else
225 : ImplRotate1_90( pBuf, mpBits + (mnWidth - 1) / 8,
226 : nNewWidth, nNewHeight, +mnScanlineSize,
227 0 : (-mnWidth & 7), +1, nNewScanlineSize - (nNewWidth + 7) / 8 );
228 2140 : break;
229 : case 2700: // rotate right by 90 degrees
230 : case -900:
231 0 : i = mnXOffset;
232 0 : mnXOffset = -(nNewWidth + mnYOffset);
233 0 : mnYOffset = i;
234 0 : if( mnBitCount == 8 )
235 : ImplRotate8_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
236 : nNewWidth, nNewHeight, -mnScanlineSize, +1+mnHeight*mnScanlineSize,
237 0 : nNewScanlineSize - nNewWidth );
238 : else
239 : ImplRotate1_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
240 : nNewWidth, nNewHeight, -mnScanlineSize,
241 0 : +7, -1, nNewScanlineSize - (nNewWidth + 7) / 8 );
242 0 : break;
243 : }
244 :
245 2140 : mnWidth = nNewWidth;
246 2140 : mnHeight = nNewHeight;
247 2140 : mnScanlineSize = nNewScanlineSize;
248 :
249 2140 : if( nBufSize < mnAllocated )
250 : {
251 2140 : memcpy( mpBits, pBuf, nBufSize );
252 2140 : delete[] pBuf;
253 : }
254 : else
255 : {
256 0 : delete[] mpBits;
257 0 : mpBits = pBuf;
258 0 : mnAllocated = nBufSize;
259 : }
260 :
261 2140 : return true;
262 : }
263 :
264 : //------------------------------------------------------------------------
265 :
266 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|