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