Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / generic / glyphs / gcach_rbmp.cxx
blob37f079c7548b3756e97747784a6d53bd6d8f48b8
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 .
20 #include "generic/glyphcache.hxx"
21 #include <string.h>
23 RawBitmap::RawBitmap()
24 : mnAllocated(0)
25 , mnWidth(0)
26 , mnHeight(0)
27 , mnScanlineSize(0)
28 , mnBitCount(0)
29 , mnXOffset(0)
30 , mnYOffset(0)
34 RawBitmap::~RawBitmap()
37 // used by 90 and 270 degree rotations on 8 bit deep bitmaps
38 static void ImplRotate8_90( unsigned char* p1, const unsigned char* p2,
39 int xmax, int ymax, int dx, int dy, int nPad )
41 for( int y = ymax; --y >= 0; p2 += dy )
43 for( int x = xmax; --x >= 0; p2 += dx )
44 *(p1++) = *p2;
45 for( int i = nPad; --i >= 0; )
46 *(p1++) = 0;
50 // used by inplace 180 degree rotation on 8 bit deep bitmaps
51 static void ImplRotate8_180( unsigned char* p1, int xmax, int ymax, int nPad )
53 unsigned char* p2 = p1 + ymax * (xmax + nPad);
54 for( int y = ymax/2; --y >= 0; )
56 p2 -= nPad;
57 for( int x = xmax; --x >= 0; )
59 unsigned char cTmp = *(--p2);
60 *p2 = *p1;
61 *(p1++) = cTmp;
63 p1 += nPad;
66 // reverse middle line
67 p2 -= nPad;
68 while( p1 < p2 )
70 unsigned char cTmp = *(--p2);
71 *p2 = *p1;
72 *(p1++) = cTmp;
76 // used by 90 or 270 degree rotations on 1 bit deep bitmaps
77 static void ImplRotate1_90( unsigned char* p1, const unsigned char* p2,
78 int xmax, int ymax, int dx, int nShift, int nDeltaShift, int nPad )
80 for( int y = ymax; --y >= 0; )
82 unsigned nTemp = 1;
83 const unsigned char* p20 = p2;
84 for( int x = xmax; --x >= 0; p2 += dx )
86 // build bitwise and store when byte finished
87 nTemp += nTemp + ((*p2 >> nShift) & 1);
88 if( nTemp >= 0x100U )
90 *(p1++) = (unsigned char)nTemp;
91 nTemp = 1;
94 p2 = p20;
96 // store left aligned remainder if needed
97 if( nTemp > 1 )
99 for(; nTemp < 0x100U; nTemp += nTemp ) ;
100 *(p1++) = (unsigned char)nTemp;
102 // pad scanline with zeroes
103 for( int i = nPad; --i >= 0;)
104 *(p1++) = 0;
106 // increase/decrease shift, but keep bound inside 0 to 7
107 nShift += nDeltaShift;
108 if( nShift != (nShift & 7) )
109 p2 -= nDeltaShift;
110 nShift &= 7;
114 // used by 180 degrees rotations on 1 bit deep bitmaps
115 static void ImplRotate1_180( unsigned char* p1, const unsigned char* p2,
116 int xmax, int ymax, int nPad )
118 --p2;
119 for( int y = ymax; --y >= 0; )
121 p2 -= nPad;
123 unsigned nTemp = 1;
124 unsigned nInp = (0x100 + *p2) >> (-xmax & 7);
125 for( int x = xmax; --x >= 0; )
127 // build bitwise and store when byte finished
128 nTemp += nTemp + (nInp & 1);
129 if( nTemp >= 0x100 )
131 *(p1++) = (unsigned char)nTemp;
132 nTemp = 1;
134 // update input byte if needed (and available)
135 if( (nInp >>= 1) <= 1 && ((y != 0) || (x != 0)) )
136 nInp = 0x100 + *(--p2);
139 // store left aligned remainder if needed
140 if( nTemp > 1 )
142 for(; nTemp < 0x100; nTemp += nTemp ) ;
143 *(p1++) = (unsigned char)nTemp;
145 // scanline pad is already clean
146 p1 += nPad;
150 bool RawBitmap::Rotate( int nAngle )
152 sal_uLong nNewScanlineSize = 0;
153 sal_uLong nNewHeight = 0;
154 sal_uLong nNewWidth = 0;
156 // do inplace rotation or prepare double buffered rotation
157 switch( nAngle )
159 case 0: // nothing to do
160 case 3600:
161 return true;
162 default: // non rectangular angles not allowed
163 return false;
164 case 1800: // rotate by 180 degrees
165 mnXOffset = -(mnXOffset + mnWidth);
166 mnYOffset = -(mnYOffset + mnHeight);
167 if( mnBitCount == 8 )
169 ImplRotate8_180( mpBits.get(), mnWidth, mnHeight, mnScanlineSize-mnWidth );
170 return true;
172 nNewWidth = mnWidth;
173 nNewHeight = mnHeight;
174 nNewScanlineSize = mnScanlineSize;
175 break;
176 case +900: // left by 90 degrees
177 case -900:
178 case 2700: // right by 90 degrees
179 nNewWidth = mnHeight;
180 nNewHeight = mnWidth;
181 if( mnBitCount==1 )
182 nNewScanlineSize = (nNewWidth + 7) / 8;
183 else
184 nNewScanlineSize = (nNewWidth + 3) & -4;
185 break;
188 unsigned int nBufSize = nNewHeight * nNewScanlineSize;
189 unsigned char* pBuf = new unsigned char[ nBufSize ];
190 if( !pBuf )
191 return false;
193 memset( pBuf, 0, nBufSize );
194 int i;
196 // dispatch non-inplace rotations
197 switch( nAngle )
199 case 1800: // rotate by 180 degrees
200 // we know we only need to deal with 1 bit depth
201 ImplRotate1_180( pBuf, mpBits.get() + mnHeight * mnScanlineSize,
202 mnWidth, mnHeight, mnScanlineSize - (mnWidth + 7) / 8 );
203 break;
204 case +900: // rotate left by 90 degrees
205 i = mnXOffset;
206 mnXOffset = mnYOffset;
207 mnYOffset = -nNewHeight - i;
208 if( mnBitCount == 8 )
209 ImplRotate8_90( pBuf, mpBits.get() + mnWidth - 1,
210 nNewWidth, nNewHeight, +mnScanlineSize, -1-mnHeight*mnScanlineSize,
211 nNewScanlineSize - nNewWidth );
212 else
213 ImplRotate1_90( pBuf, mpBits.get() + (mnWidth - 1) / 8,
214 nNewWidth, nNewHeight, +mnScanlineSize,
215 (-mnWidth & 7), +1, nNewScanlineSize - (nNewWidth + 7) / 8 );
216 break;
217 case 2700: // rotate right by 90 degrees
218 case -900:
219 i = mnXOffset;
220 mnXOffset = -(nNewWidth + mnYOffset);
221 mnYOffset = i;
222 if( mnBitCount == 8 )
223 ImplRotate8_90( pBuf, mpBits.get() + mnScanlineSize * (mnHeight-1),
224 nNewWidth, nNewHeight, -mnScanlineSize, +1+mnHeight*mnScanlineSize,
225 nNewScanlineSize - nNewWidth );
226 else
227 ImplRotate1_90( pBuf, mpBits.get() + mnScanlineSize * (mnHeight-1),
228 nNewWidth, nNewHeight, -mnScanlineSize,
229 +7, -1, nNewScanlineSize - (nNewWidth + 7) / 8 );
230 break;
233 mnWidth = nNewWidth;
234 mnHeight = nNewHeight;
235 mnScanlineSize = nNewScanlineSize;
237 if( nBufSize < mnAllocated )
239 memcpy( mpBits.get(), pBuf, nBufSize );
240 delete[] pBuf;
242 else
244 mpBits.reset(pBuf);
245 mnAllocated = nBufSize;
248 return true;
251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */