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