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