fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / vcl / generic / glyphs / gcach_rbmp.cxx
blob684f8869328d54a3f2ffe50b356b7e7df2b314ca
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "generic/glyphcache.hxx"
22 #include <string.h>
25 RawBitmap::RawBitmap()
26 : mpBits(0), mnAllocated(0)
30 RawBitmap::~RawBitmap()
32 delete[] mpBits;
33 mpBits = 0;
34 mnAllocated = 0;
38 // used by 90 and 270 degree rotations on 8 bit deep bitmaps
39 static void ImplRotate8_90( unsigned char* p1, const unsigned char* p2,
40 int xmax, int ymax, int dx, int dy, int nPad )
42 for( int y = ymax; --y >= 0; p2 += dy )
44 for( int x = xmax; --x >= 0; p2 += dx )
45 *(p1++) = *p2;
46 for( int i = nPad; --i >= 0; )
47 *(p1++) = 0;
52 // used by inplace 180 degree rotation on 8 bit deep bitmaps
53 static void ImplRotate8_180( unsigned char* p1, int xmax, int ymax, int nPad )
55 unsigned char* p2 = p1 + ymax * (xmax + nPad);
56 for( int y = ymax/2; --y >= 0; )
58 p2 -= nPad;
59 for( int x = xmax; --x >= 0; )
61 unsigned char cTmp = *(--p2);
62 *p2 = *p1;
63 *(p1++) = cTmp;
65 p1 += nPad;
68 // reverse middle line
69 p2 -= nPad;
70 while( p1 < p2 )
72 unsigned char cTmp = *(--p2);
73 *p2 = *p1;
74 *(p1++) = cTmp;
79 // used by 90 or 270 degree rotations on 1 bit deep bitmaps
80 static void ImplRotate1_90( unsigned char* p1, const unsigned char* p2,
81 int xmax, int ymax, int dx, int nShift, int nDeltaShift, int nPad )
83 for( int y = ymax; --y >= 0; )
85 unsigned nTemp = 1;
86 const unsigned char* p20 = p2;
87 for( int x = xmax; --x >= 0; p2 += dx )
89 // build bitwise and store when byte finished
90 nTemp += nTemp + ((*p2 >> nShift) & 1);
91 if( nTemp >= 0x100U )
93 *(p1++) = (unsigned char)nTemp;
94 nTemp = 1;
97 p2 = p20;
99 // store left aligned remainder if needed
100 if( nTemp > 1 )
102 for(; nTemp < 0x100U; nTemp += nTemp ) ;
103 *(p1++) = (unsigned char)nTemp;
105 // pad scanline with zeroes
106 for( int i = nPad; --i >= 0;)
107 *(p1++) = 0;
109 // increase/decrease shift, but keep bound inside 0 to 7
110 nShift += nDeltaShift;
111 if( nShift != (nShift & 7) )
112 p2 -= nDeltaShift;
113 nShift &= 7;
118 // used by 180 degrees rotations on 1 bit deep bitmaps
119 static void ImplRotate1_180( unsigned char* p1, const unsigned char* p2,
120 int xmax, int ymax, int nPad )
122 --p2;
123 for( int y = ymax; --y >= 0; )
125 p2 -= nPad;
127 unsigned nTemp = 1;
128 unsigned nInp = (0x100 + *p2) >> (-xmax & 7);
129 for( int x = xmax; --x >= 0; )
131 // build bitwise and store when byte finished
132 nTemp += nTemp + (nInp & 1);
133 if( nTemp >= 0x100 )
135 *(p1++) = (unsigned char)nTemp;
136 nTemp = 1;
138 // update input byte if needed (and available)
139 if( (nInp >>= 1) <= 1 && ((y != 0) || (x != 0)) )
140 nInp = 0x100 + *(--p2);
143 // store left aligned remainder if needed
144 if( nTemp > 1 )
146 for(; nTemp < 0x100; nTemp += nTemp ) ;
147 *(p1++) = (unsigned char)nTemp;
149 // scanline pad is already clean
150 p1 += nPad;
155 bool RawBitmap::Rotate( int nAngle )
157 sal_uLong nNewScanlineSize = 0;
158 sal_uLong nNewHeight = 0;
159 sal_uLong nNewWidth = 0;
161 // do inplace rotation or prepare double buffered rotation
162 switch( nAngle )
164 case 0: // nothing to do
165 case 3600:
166 return true;
167 default: // non rectangular angles not allowed
168 return false;
169 case 1800: // rotate by 180 degrees
170 mnXOffset = -(mnXOffset + mnWidth);
171 mnYOffset = -(mnYOffset + mnHeight);
172 if( mnBitCount == 8 )
174 ImplRotate8_180( mpBits, mnWidth, mnHeight, mnScanlineSize-mnWidth );
175 return true;
177 nNewWidth = mnWidth;
178 nNewHeight = mnHeight;
179 nNewScanlineSize = mnScanlineSize;
180 break;
181 case +900: // left by 90 degrees
182 case -900:
183 case 2700: // right by 90 degrees
184 nNewWidth = mnHeight;
185 nNewHeight = mnWidth;
186 if( mnBitCount==1 )
187 nNewScanlineSize = (nNewWidth + 7) / 8;
188 else
189 nNewScanlineSize = (nNewWidth + 3) & -4;
190 break;
193 unsigned int nBufSize = nNewHeight * nNewScanlineSize;
194 unsigned char* pBuf = new unsigned char[ nBufSize ];
195 if( !pBuf )
196 return false;
198 memset( pBuf, 0, nBufSize );
199 int i;
201 // dispatch non-inplace rotations
202 switch( nAngle )
204 case 1800: // rotate by 180 degrees
205 // we know we only need to deal with 1 bit depth
206 ImplRotate1_180( pBuf, mpBits + mnHeight * mnScanlineSize,
207 mnWidth, mnHeight, mnScanlineSize - (mnWidth + 7) / 8 );
208 break;
209 case +900: // rotate left by 90 degrees
210 i = mnXOffset;
211 mnXOffset = mnYOffset;
212 mnYOffset = -nNewHeight - i;
213 if( mnBitCount == 8 )
214 ImplRotate8_90( pBuf, mpBits + mnWidth - 1,
215 nNewWidth, nNewHeight, +mnScanlineSize, -1-mnHeight*mnScanlineSize,
216 nNewScanlineSize - nNewWidth );
217 else
218 ImplRotate1_90( pBuf, mpBits + (mnWidth - 1) / 8,
219 nNewWidth, nNewHeight, +mnScanlineSize,
220 (-mnWidth & 7), +1, nNewScanlineSize - (nNewWidth + 7) / 8 );
221 break;
222 case 2700: // rotate right by 90 degrees
223 case -900:
224 i = mnXOffset;
225 mnXOffset = -(nNewWidth + mnYOffset);
226 mnYOffset = i;
227 if( mnBitCount == 8 )
228 ImplRotate8_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
229 nNewWidth, nNewHeight, -mnScanlineSize, +1+mnHeight*mnScanlineSize,
230 nNewScanlineSize - nNewWidth );
231 else
232 ImplRotate1_90( pBuf, mpBits + mnScanlineSize * (mnHeight-1),
233 nNewWidth, nNewHeight, -mnScanlineSize,
234 +7, -1, nNewScanlineSize - (nNewWidth + 7) / 8 );
235 break;
238 mnWidth = nNewWidth;
239 mnHeight = nNewHeight;
240 mnScanlineSize = nNewScanlineSize;
242 if( nBufSize < mnAllocated )
244 memcpy( mpBits, pBuf, nBufSize );
245 delete[] pBuf;
247 else
249 delete[] mpBits;
250 mpBits = pBuf;
251 mnAllocated = nBufSize;
254 return true;
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */