1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
25 RawBitmap::RawBitmap()
26 : mpBits(0), mnAllocated(0)
30 RawBitmap::~RawBitmap()
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
)
46 for( int i
= nPad
; --i
>= 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; )
59 for( int x
= xmax
; --x
>= 0; )
61 unsigned char cTmp
= *(--p2
);
68 // reverse middle line
72 unsigned char cTmp
= *(--p2
);
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; )
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);
93 *(p1
++) = (unsigned char)nTemp
;
99 // store left aligned remainder if needed
102 for(; nTemp
< 0x100U
; nTemp
+= nTemp
) ;
103 *(p1
++) = (unsigned char)nTemp
;
105 // pad scanline with zeroes
106 for( int i
= nPad
; --i
>= 0;)
109 // increase/decrease shift, but keep bound inside 0 to 7
110 nShift
+= nDeltaShift
;
111 if( nShift
!= (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
)
123 for( int y
= ymax
; --y
>= 0; )
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);
135 *(p1
++) = (unsigned char)nTemp
;
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
146 for(; nTemp
< 0x100; nTemp
+= nTemp
) ;
147 *(p1
++) = (unsigned char)nTemp
;
149 // scanline pad is already clean
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
164 case 0: // nothing to do
167 default: // non rectangular angles not allowed
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
);
178 nNewHeight
= mnHeight
;
179 nNewScanlineSize
= mnScanlineSize
;
181 case +900: // left by 90 degrees
183 case 2700: // right by 90 degrees
184 nNewWidth
= mnHeight
;
185 nNewHeight
= mnWidth
;
187 nNewScanlineSize
= (nNewWidth
+ 7) / 8;
189 nNewScanlineSize
= (nNewWidth
+ 3) & -4;
193 unsigned int nBufSize
= nNewHeight
* nNewScanlineSize
;
194 unsigned char* pBuf
= new unsigned char[ nBufSize
];
198 memset( pBuf
, 0, nBufSize
);
201 // dispatch non-inplace rotations
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 );
209 case +900: // rotate left by 90 degrees
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
);
218 ImplRotate1_90( pBuf
, mpBits
+ (mnWidth
- 1) / 8,
219 nNewWidth
, nNewHeight
, +mnScanlineSize
,
220 (-mnWidth
& 7), +1, nNewScanlineSize
- (nNewWidth
+ 7) / 8 );
222 case 2700: // rotate right by 90 degrees
225 mnXOffset
= -(nNewWidth
+ mnYOffset
);
227 if( mnBitCount
== 8 )
228 ImplRotate8_90( pBuf
, mpBits
+ mnScanlineSize
* (mnHeight
-1),
229 nNewWidth
, nNewHeight
, -mnScanlineSize
, +1+mnHeight
*mnScanlineSize
,
230 nNewScanlineSize
- nNewWidth
);
232 ImplRotate1_90( pBuf
, mpBits
+ mnScanlineSize
* (mnHeight
-1),
233 nNewWidth
, nNewHeight
, -mnScanlineSize
,
234 +7, -1, nNewScanlineSize
- (nNewWidth
+ 7) / 8 );
239 mnHeight
= nNewHeight
;
240 mnScanlineSize
= nNewScanlineSize
;
242 if( nBufSize
< mnAllocated
)
244 memcpy( mpBits
, pBuf
, nBufSize
);
251 mnAllocated
= nBufSize
;
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */