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