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 .
20 #include "generic/glyphcache.hxx"
23 RawBitmap::RawBitmap()
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
)
45 for( int i
= nPad
; --i
>= 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; )
57 for( int x
= xmax
; --x
>= 0; )
59 unsigned char cTmp
= *(--p2
);
66 // reverse middle line
70 unsigned char cTmp
= *(--p2
);
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; )
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);
90 *(p1
++) = (unsigned char)nTemp
;
96 // store left aligned remainder if needed
99 for(; nTemp
< 0x100U
; nTemp
+= nTemp
) ;
100 *(p1
++) = (unsigned char)nTemp
;
102 // pad scanline with zeroes
103 for( int i
= nPad
; --i
>= 0;)
106 // increase/decrease shift, but keep bound inside 0 to 7
107 nShift
+= nDeltaShift
;
108 if( nShift
!= (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
)
119 for( int y
= ymax
; --y
>= 0; )
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);
131 *(p1
++) = (unsigned char)nTemp
;
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
142 for(; nTemp
< 0x100; nTemp
+= nTemp
) ;
143 *(p1
++) = (unsigned char)nTemp
;
145 // scanline pad is already clean
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
159 case 0: // nothing to do
162 default: // non rectangular angles not allowed
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
);
173 nNewHeight
= mnHeight
;
174 nNewScanlineSize
= mnScanlineSize
;
176 case +900: // left by 90 degrees
178 case 2700: // right by 90 degrees
179 nNewWidth
= mnHeight
;
180 nNewHeight
= mnWidth
;
182 nNewScanlineSize
= (nNewWidth
+ 7) / 8;
184 nNewScanlineSize
= (nNewWidth
+ 3) & -4;
188 unsigned int nBufSize
= nNewHeight
* nNewScanlineSize
;
189 unsigned char* pBuf
= new unsigned char[ nBufSize
];
193 memset( pBuf
, 0, nBufSize
);
196 // dispatch non-inplace rotations
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 );
204 case +900: // rotate left by 90 degrees
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
);
213 ImplRotate1_90( pBuf
, mpBits
.get() + (mnWidth
- 1) / 8,
214 nNewWidth
, nNewHeight
, +mnScanlineSize
,
215 (-mnWidth
& 7), +1, nNewScanlineSize
- (nNewWidth
+ 7) / 8 );
217 case 2700: // rotate right by 90 degrees
220 mnXOffset
= -(nNewWidth
+ mnYOffset
);
222 if( mnBitCount
== 8 )
223 ImplRotate8_90( pBuf
, mpBits
.get() + mnScanlineSize
* (mnHeight
-1),
224 nNewWidth
, nNewHeight
, -mnScanlineSize
, +1+mnHeight
*mnScanlineSize
,
225 nNewScanlineSize
- nNewWidth
);
227 ImplRotate1_90( pBuf
, mpBits
.get() + mnScanlineSize
* (mnHeight
-1),
228 nNewWidth
, nNewHeight
, -mnScanlineSize
,
229 +7, -1, nNewScanlineSize
- (nNewWidth
+ 7) / 8 );
234 mnHeight
= nNewHeight
;
235 mnScanlineSize
= nNewScanlineSize
;
237 if( nBufSize
< mnAllocated
)
239 memcpy( mpBits
.get(), pBuf
, nBufSize
);
245 mnAllocated
= nBufSize
;
251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */