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