widget/windows/nsImageClipboard.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsImageClipboard.h"
michael@0 7
michael@0 8 #include "gfxUtils.h"
michael@0 9 #include "mozilla/gfx/2D.h"
michael@0 10 #include "mozilla/gfx/DataSurfaceHelpers.h"
michael@0 11 #include "mozilla/RefPtr.h"
michael@0 12 #include "nsITransferable.h"
michael@0 13 #include "nsGfxCIID.h"
michael@0 14 #include "nsMemory.h"
michael@0 15 #include "prmem.h"
michael@0 16 #include "imgIEncoder.h"
michael@0 17 #include "nsLiteralString.h"
michael@0 18 #include "nsComponentManagerUtils.h"
michael@0 19
michael@0 20 #define BFH_LENGTH 14
michael@0 21
michael@0 22 using namespace mozilla;
michael@0 23 using namespace mozilla::gfx;
michael@0 24
michael@0 25 /* Things To Do 11/8/00
michael@0 26
michael@0 27 Check image metrics, can we support them? Do we need to?
michael@0 28 Any other render format? HTML?
michael@0 29
michael@0 30 */
michael@0 31
michael@0 32
michael@0 33 //
michael@0 34 // nsImageToClipboard ctor
michael@0 35 //
michael@0 36 // Given an imgIContainer, convert it to a DIB that is ready to go on the win32 clipboard
michael@0 37 //
michael@0 38 nsImageToClipboard::nsImageToClipboard(imgIContainer* aInImage, bool aWantDIBV5)
michael@0 39 : mImage(aInImage)
michael@0 40 , mWantDIBV5(aWantDIBV5)
michael@0 41 {
michael@0 42 // nothing to do here
michael@0 43 }
michael@0 44
michael@0 45
michael@0 46 //
michael@0 47 // nsImageToClipboard dtor
michael@0 48 //
michael@0 49 // Clean up after ourselves. We know that we have created the bitmap
michael@0 50 // successfully if we still have a pointer to the header.
michael@0 51 //
michael@0 52 nsImageToClipboard::~nsImageToClipboard()
michael@0 53 {
michael@0 54 }
michael@0 55
michael@0 56
michael@0 57 //
michael@0 58 // GetPicture
michael@0 59 //
michael@0 60 // Call to get the actual bits that go on the clipboard. If an error
michael@0 61 // ocurred during conversion, |outBits| will be null.
michael@0 62 //
michael@0 63 // NOTE: The caller owns the handle and must delete it with ::GlobalRelease()
michael@0 64 //
michael@0 65 nsresult
michael@0 66 nsImageToClipboard :: GetPicture ( HANDLE* outBits )
michael@0 67 {
michael@0 68 NS_ASSERTION ( outBits, "Bad parameter" );
michael@0 69
michael@0 70 return CreateFromImage ( mImage, outBits );
michael@0 71
michael@0 72 } // GetPicture
michael@0 73
michael@0 74
michael@0 75 //
michael@0 76 // CalcSize
michael@0 77 //
michael@0 78 // Computes # of bytes needed by a bitmap with the specified attributes.
michael@0 79 //
michael@0 80 int32_t
michael@0 81 nsImageToClipboard :: CalcSize ( int32_t aHeight, int32_t aColors, WORD aBitsPerPixel, int32_t aSpanBytes )
michael@0 82 {
michael@0 83 int32_t HeaderMem = sizeof(BITMAPINFOHEADER);
michael@0 84
michael@0 85 // add size of pallette to header size
michael@0 86 if (aBitsPerPixel < 16)
michael@0 87 HeaderMem += aColors * sizeof(RGBQUAD);
michael@0 88
michael@0 89 if (aHeight < 0)
michael@0 90 aHeight = -aHeight;
michael@0 91
michael@0 92 return (HeaderMem + (aHeight * aSpanBytes));
michael@0 93 }
michael@0 94
michael@0 95
michael@0 96 //
michael@0 97 // CalcSpanLength
michael@0 98 //
michael@0 99 // Computes the span bytes for determining the overall size of the image
michael@0 100 //
michael@0 101 int32_t
michael@0 102 nsImageToClipboard::CalcSpanLength(uint32_t aWidth, uint32_t aBitCount)
michael@0 103 {
michael@0 104 int32_t spanBytes = (aWidth * aBitCount) >> 5;
michael@0 105
michael@0 106 if ((aWidth * aBitCount) & 0x1F)
michael@0 107 spanBytes++;
michael@0 108 spanBytes <<= 2;
michael@0 109
michael@0 110 return spanBytes;
michael@0 111 }
michael@0 112
michael@0 113
michael@0 114 //
michael@0 115 // CreateFromImage
michael@0 116 //
michael@0 117 // Do the work to setup the bitmap header and copy the bits out of the
michael@0 118 // image.
michael@0 119 //
michael@0 120 nsresult
michael@0 121 nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap )
michael@0 122 {
michael@0 123 nsresult rv;
michael@0 124 *outBitmap = nullptr;
michael@0 125
michael@0 126 RefPtr<SourceSurface> surface =
michael@0 127 inImage->GetFrame(imgIContainer::FRAME_CURRENT,
michael@0 128 imgIContainer::FLAG_SYNC_DECODE);
michael@0 129 NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
michael@0 130
michael@0 131 MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
michael@0 132 surface->GetFormat() == SurfaceFormat::B8G8R8X8);
michael@0 133
michael@0 134 RefPtr<DataSourceSurface> dataSurface;
michael@0 135 if (surface->GetFormat() == SurfaceFormat::B8G8R8A8) {
michael@0 136 dataSurface = surface->GetDataSurface();
michael@0 137 } else {
michael@0 138 // XXXjwatt Bug 995923 - get rid of this copy and handle B8G8R8X8
michael@0 139 // directly below once bug 995807 is fixed.
michael@0 140 dataSurface = gfxUtils::
michael@0 141 CopySurfaceToDataSourceSurfaceWithFormat(surface,
michael@0 142 SurfaceFormat::B8G8R8A8);
michael@0 143 }
michael@0 144 NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
michael@0 145
michael@0 146 nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv);
michael@0 147 NS_ENSURE_SUCCESS(rv, rv);
michael@0 148
michael@0 149 uint32_t format;
michael@0 150 nsAutoString options;
michael@0 151 if (mWantDIBV5) {
michael@0 152 options.AppendLiteral("version=5;bpp=");
michael@0 153 } else {
michael@0 154 options.AppendLiteral("version=3;bpp=");
michael@0 155 }
michael@0 156 switch (dataSurface->GetFormat()) {
michael@0 157 case SurfaceFormat::B8G8R8A8:
michael@0 158 format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
michael@0 159 options.AppendInt(32);
michael@0 160 break;
michael@0 161 #if 0
michael@0 162 // XXXjwatt Bug 995923 - fix |format| and reenable once bug 995807 is fixed.
michael@0 163 case SurfaceFormat::B8G8R8X8:
michael@0 164 format = imgIEncoder::INPUT_FORMAT_RGB;
michael@0 165 options.AppendInt(24);
michael@0 166 break;
michael@0 167 #endif
michael@0 168 default:
michael@0 169 NS_NOTREACHED("Unexpected surface format");
michael@0 170 return NS_ERROR_INVALID_ARG;
michael@0 171 }
michael@0 172
michael@0 173 DataSourceSurface::MappedSurface map;
michael@0 174 bool mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
michael@0 175 NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE);
michael@0 176
michael@0 177 rv = encoder->InitFromData(map.mData, 0,
michael@0 178 dataSurface->GetSize().width,
michael@0 179 dataSurface->GetSize().height,
michael@0 180 map.mStride,
michael@0 181 format, options);
michael@0 182 dataSurface->Unmap();
michael@0 183 NS_ENSURE_SUCCESS(rv, rv);
michael@0 184
michael@0 185 uint32_t size;
michael@0 186 encoder->GetImageBufferUsed(&size);
michael@0 187 NS_ENSURE_TRUE(size > BFH_LENGTH, NS_ERROR_FAILURE);
michael@0 188 HGLOBAL glob = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT,
michael@0 189 size - BFH_LENGTH);
michael@0 190 if (!glob)
michael@0 191 return NS_ERROR_OUT_OF_MEMORY;
michael@0 192
michael@0 193 char *dst = (char*) ::GlobalLock(glob);
michael@0 194 char *src;
michael@0 195 rv = encoder->GetImageBuffer(&src);
michael@0 196 NS_ENSURE_SUCCESS(rv, rv);
michael@0 197
michael@0 198 ::CopyMemory(dst, src + BFH_LENGTH, size - BFH_LENGTH);
michael@0 199 ::GlobalUnlock(glob);
michael@0 200
michael@0 201 *outBitmap = (HANDLE)glob;
michael@0 202 return NS_OK;
michael@0 203 }
michael@0 204
michael@0 205 nsImageFromClipboard :: nsImageFromClipboard ()
michael@0 206 {
michael@0 207 // nothing to do here
michael@0 208 }
michael@0 209
michael@0 210 nsImageFromClipboard :: ~nsImageFromClipboard ( )
michael@0 211 {
michael@0 212 }
michael@0 213
michael@0 214 //
michael@0 215 // GetEncodedImageStream
michael@0 216 //
michael@0 217 // Take the raw clipboard image data and convert it to aMIMEFormat in the form of a nsIInputStream
michael@0 218 //
michael@0 219 nsresult
michael@0 220 nsImageFromClipboard ::GetEncodedImageStream (unsigned char * aClipboardData, const char * aMIMEFormat, nsIInputStream** aInputStream )
michael@0 221 {
michael@0 222 NS_ENSURE_ARG_POINTER (aInputStream);
michael@0 223 NS_ENSURE_ARG_POINTER (aMIMEFormat);
michael@0 224 nsresult rv;
michael@0 225 *aInputStream = nullptr;
michael@0 226
michael@0 227 // pull the size information out of the BITMAPINFO header and
michael@0 228 // initialize the image
michael@0 229 BITMAPINFO* header = (BITMAPINFO *) aClipboardData;
michael@0 230 int32_t width = header->bmiHeader.biWidth;
michael@0 231 int32_t height = header->bmiHeader.biHeight;
michael@0 232 // neg. heights mean the Y axis is inverted and we don't handle that case
michael@0 233 NS_ENSURE_TRUE(height > 0, NS_ERROR_FAILURE);
michael@0 234
michael@0 235 unsigned char * rgbData = new unsigned char[width * height * 3 /* RGB */];
michael@0 236
michael@0 237 if (rgbData) {
michael@0 238 BYTE * pGlobal = (BYTE *) aClipboardData;
michael@0 239 // Convert the clipboard image into RGB packed pixel data
michael@0 240 rv = ConvertColorBitMap((unsigned char *) (pGlobal + header->bmiHeader.biSize), header, rgbData);
michael@0 241 // if that succeeded, encode the bitmap as aMIMEFormat data. Don't return early or we risk leaking rgbData
michael@0 242 if (NS_SUCCEEDED(rv)) {
michael@0 243 nsAutoCString encoderCID(NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type="));
michael@0 244
michael@0 245 // Map image/jpg to image/jpeg (which is how the encoder is registered).
michael@0 246 if (strcmp(aMIMEFormat, kJPGImageMime) == 0)
michael@0 247 encoderCID.Append("image/jpeg");
michael@0 248 else
michael@0 249 encoderCID.Append(aMIMEFormat);
michael@0 250 nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get(), &rv);
michael@0 251 if (NS_SUCCEEDED(rv)){
michael@0 252 rv = encoder->InitFromData(rgbData, 0, width, height, 3 * width /* RGB * # pixels in a row */,
michael@0 253 imgIEncoder::INPUT_FORMAT_RGB, EmptyString());
michael@0 254 if (NS_SUCCEEDED(rv))
michael@0 255 encoder->QueryInterface(NS_GET_IID(nsIInputStream), (void **) aInputStream);
michael@0 256 }
michael@0 257 }
michael@0 258 delete [] rgbData;
michael@0 259 }
michael@0 260 else
michael@0 261 rv = NS_ERROR_OUT_OF_MEMORY;
michael@0 262
michael@0 263 return rv;
michael@0 264 } // GetImage
michael@0 265
michael@0 266 //
michael@0 267 // InvertRows
michael@0 268 //
michael@0 269 // Take the image data from the clipboard and invert the rows. Modifying aInitialBuffer in place.
michael@0 270 //
michael@0 271 void
michael@0 272 nsImageFromClipboard::InvertRows(unsigned char * aInitialBuffer, uint32_t aSizeOfBuffer, uint32_t aNumBytesPerRow)
michael@0 273 {
michael@0 274 if (!aNumBytesPerRow)
michael@0 275 return;
michael@0 276
michael@0 277 uint32_t numRows = aSizeOfBuffer / aNumBytesPerRow;
michael@0 278 unsigned char * row = new unsigned char[aNumBytesPerRow];
michael@0 279
michael@0 280 uint32_t currentRow = 0;
michael@0 281 uint32_t lastRow = (numRows - 1) * aNumBytesPerRow;
michael@0 282 while (currentRow < lastRow)
michael@0 283 {
michael@0 284 // store the current row into a temporary buffer
michael@0 285 memcpy(row, &aInitialBuffer[currentRow], aNumBytesPerRow);
michael@0 286 memcpy(&aInitialBuffer[currentRow], &aInitialBuffer[lastRow], aNumBytesPerRow);
michael@0 287 memcpy(&aInitialBuffer[lastRow], row, aNumBytesPerRow);
michael@0 288 lastRow -= aNumBytesPerRow;
michael@0 289 currentRow += aNumBytesPerRow;
michael@0 290 }
michael@0 291
michael@0 292 delete[] row;
michael@0 293 }
michael@0 294
michael@0 295 //
michael@0 296 // ConvertColorBitMap
michael@0 297 //
michael@0 298 // Takes the clipboard bitmap and converts it into a RGB packed pixel values.
michael@0 299 //
michael@0 300 nsresult
michael@0 301 nsImageFromClipboard::ConvertColorBitMap(unsigned char * aInputBuffer, PBITMAPINFO pBitMapInfo, unsigned char * aOutBuffer)
michael@0 302 {
michael@0 303 uint8_t bitCount = pBitMapInfo->bmiHeader.biBitCount;
michael@0 304 uint32_t imageSize = pBitMapInfo->bmiHeader.biSizeImage; // may be zero for BI_RGB bitmaps which means we need to calculate by hand
michael@0 305 uint32_t bytesPerPixel = bitCount / 8;
michael@0 306
michael@0 307 if (bitCount <= 4)
michael@0 308 bytesPerPixel = 1;
michael@0 309
michael@0 310 // rows are DWORD aligned. Calculate how many real bytes are in each row in the bitmap. This number won't
michael@0 311 // correspond to biWidth.
michael@0 312 uint32_t rowSize = (bitCount * pBitMapInfo->bmiHeader.biWidth + 7) / 8; // +7 to round up
michael@0 313 if (rowSize % 4)
michael@0 314 rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary
michael@0 315
michael@0 316 // if our buffer includes a color map, skip over it
michael@0 317 if (bitCount <= 8)
michael@0 318 {
michael@0 319 int32_t bytesToSkip = (pBitMapInfo->bmiHeader.biClrUsed ? pBitMapInfo->bmiHeader.biClrUsed : (1 << bitCount) ) * sizeof(RGBQUAD);
michael@0 320 aInputBuffer += bytesToSkip;
michael@0 321 }
michael@0 322
michael@0 323 bitFields colorMasks; // only used if biCompression == BI_BITFIELDS
michael@0 324
michael@0 325 if (pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS)
michael@0 326 {
michael@0 327 // color table consists of 3 DWORDS containing the color masks...
michael@0 328 colorMasks.red = (*((uint32_t*)&(pBitMapInfo->bmiColors[0])));
michael@0 329 colorMasks.green = (*((uint32_t*)&(pBitMapInfo->bmiColors[1])));
michael@0 330 colorMasks.blue = (*((uint32_t*)&(pBitMapInfo->bmiColors[2])));
michael@0 331 CalcBitShift(&colorMasks);
michael@0 332 aInputBuffer += 3 * sizeof(DWORD);
michael@0 333 }
michael@0 334 else if (pBitMapInfo->bmiHeader.biCompression == BI_RGB && !imageSize) // BI_RGB can have a size of zero which means we figure it out
michael@0 335 {
michael@0 336 // XXX: note use rowSize here and not biWidth. rowSize accounts for the DWORD padding for each row
michael@0 337 imageSize = rowSize * pBitMapInfo->bmiHeader.biHeight;
michael@0 338 }
michael@0 339
michael@0 340 // The windows clipboard image format inverts the rows
michael@0 341 InvertRows(aInputBuffer, imageSize, rowSize);
michael@0 342
michael@0 343 if (!pBitMapInfo->bmiHeader.biCompression || pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS)
michael@0 344 {
michael@0 345 uint32_t index = 0;
michael@0 346 uint32_t writeIndex = 0;
michael@0 347
michael@0 348 unsigned char redValue, greenValue, blueValue;
michael@0 349 uint8_t colorTableEntry = 0;
michael@0 350 int8_t bit; // used for grayscale bitmaps where each bit is a pixel
michael@0 351 uint32_t numPixelsLeftInRow = pBitMapInfo->bmiHeader.biWidth; // how many more pixels do we still need to read for the current row
michael@0 352 uint32_t pos = 0;
michael@0 353
michael@0 354 while (index < imageSize)
michael@0 355 {
michael@0 356 switch (bitCount)
michael@0 357 {
michael@0 358 case 1:
michael@0 359 for (bit = 7; bit >= 0 && numPixelsLeftInRow; bit--)
michael@0 360 {
michael@0 361 colorTableEntry = (aInputBuffer[index] >> bit) & 1;
michael@0 362 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed;
michael@0 363 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen;
michael@0 364 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue;
michael@0 365 numPixelsLeftInRow--;
michael@0 366 }
michael@0 367 pos += 1;
michael@0 368 break;
michael@0 369 case 4:
michael@0 370 {
michael@0 371 // each aInputBuffer[index] entry contains data for two pixels.
michael@0 372 // read the first pixel
michael@0 373 colorTableEntry = aInputBuffer[index] >> 4;
michael@0 374 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed;
michael@0 375 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen;
michael@0 376 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue;
michael@0 377 numPixelsLeftInRow--;
michael@0 378
michael@0 379 if (numPixelsLeftInRow) // now read the second pixel
michael@0 380 {
michael@0 381 colorTableEntry = aInputBuffer[index] & 0xF;
michael@0 382 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed;
michael@0 383 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen;
michael@0 384 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue;
michael@0 385 numPixelsLeftInRow--;
michael@0 386 }
michael@0 387 pos += 1;
michael@0 388 }
michael@0 389 break;
michael@0 390 case 8:
michael@0 391 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[aInputBuffer[index]].rgbRed;
michael@0 392 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[aInputBuffer[index]].rgbGreen;
michael@0 393 aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[aInputBuffer[index]].rgbBlue;
michael@0 394 numPixelsLeftInRow--;
michael@0 395 pos += 1;
michael@0 396 break;
michael@0 397 case 16:
michael@0 398 {
michael@0 399 uint16_t num = 0;
michael@0 400 num = (uint8_t) aInputBuffer[index+1];
michael@0 401 num <<= 8;
michael@0 402 num |= (uint8_t) aInputBuffer[index];
michael@0 403
michael@0 404 redValue = ((uint32_t) (((float)(num & 0xf800) / 0xf800) * 0xFF0000) & 0xFF0000)>> 16;
michael@0 405 greenValue = ((uint32_t)(((float)(num & 0x07E0) / 0x07E0) * 0x00FF00) & 0x00FF00)>> 8;
michael@0 406 blueValue = ((uint32_t)(((float)(num & 0x001F) / 0x001F) * 0x0000FF) & 0x0000FF);
michael@0 407
michael@0 408 // now we have the right RGB values...
michael@0 409 aOutBuffer[writeIndex++] = redValue;
michael@0 410 aOutBuffer[writeIndex++] = greenValue;
michael@0 411 aOutBuffer[writeIndex++] = blueValue;
michael@0 412 numPixelsLeftInRow--;
michael@0 413 pos += 2;
michael@0 414 }
michael@0 415 break;
michael@0 416 case 32:
michael@0 417 case 24:
michael@0 418 if (pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS)
michael@0 419 {
michael@0 420 uint32_t val = *((uint32_t*) (aInputBuffer + index) );
michael@0 421 aOutBuffer[writeIndex++] = (val & colorMasks.red) >> colorMasks.redRightShift << colorMasks.redLeftShift;
michael@0 422 aOutBuffer[writeIndex++] = (val & colorMasks.green) >> colorMasks.greenRightShift << colorMasks.greenLeftShift;
michael@0 423 aOutBuffer[writeIndex++] = (val & colorMasks.blue) >> colorMasks.blueRightShift << colorMasks.blueLeftShift;
michael@0 424 numPixelsLeftInRow--;
michael@0 425 pos += 4; // we read in 4 bytes of data in order to process this pixel
michael@0 426 }
michael@0 427 else
michael@0 428 {
michael@0 429 aOutBuffer[writeIndex++] = aInputBuffer[index+2];
michael@0 430 aOutBuffer[writeIndex++] = aInputBuffer[index+1];
michael@0 431 aOutBuffer[writeIndex++] = aInputBuffer[index];
michael@0 432 numPixelsLeftInRow--;
michael@0 433 pos += bytesPerPixel; // 3 bytes for 24 bit data, 4 bytes for 32 bit data (we skip over the 4th byte)...
michael@0 434 }
michael@0 435 break;
michael@0 436 default:
michael@0 437 // This is probably the wrong place to check this...
michael@0 438 return NS_ERROR_FAILURE;
michael@0 439 }
michael@0 440
michael@0 441 index += bytesPerPixel; // increment our loop counter
michael@0 442
michael@0 443 if (!numPixelsLeftInRow)
michael@0 444 {
michael@0 445 if (rowSize != pos)
michael@0 446 {
michael@0 447 // advance index to skip over remaining padding bytes
michael@0 448 index += (rowSize - pos);
michael@0 449 }
michael@0 450 numPixelsLeftInRow = pBitMapInfo->bmiHeader.biWidth;
michael@0 451 pos = 0;
michael@0 452 }
michael@0 453
michael@0 454 } // while we still have bytes to process
michael@0 455 }
michael@0 456
michael@0 457 return NS_OK;
michael@0 458 }
michael@0 459
michael@0 460 void nsImageFromClipboard::CalcBitmask(uint32_t aMask, uint8_t& aBegin, uint8_t& aLength)
michael@0 461 {
michael@0 462 // find the rightmost 1
michael@0 463 uint8_t pos;
michael@0 464 bool started = false;
michael@0 465 aBegin = aLength = 0;
michael@0 466 for (pos = 0; pos <= 31; pos++)
michael@0 467 {
michael@0 468 if (!started && (aMask & (1 << pos)))
michael@0 469 {
michael@0 470 aBegin = pos;
michael@0 471 started = true;
michael@0 472 }
michael@0 473 else if (started && !(aMask & (1 << pos)))
michael@0 474 {
michael@0 475 aLength = pos - aBegin;
michael@0 476 break;
michael@0 477 }
michael@0 478 }
michael@0 479 }
michael@0 480
michael@0 481 void nsImageFromClipboard::CalcBitShift(bitFields * aColorMask)
michael@0 482 {
michael@0 483 uint8_t begin, length;
michael@0 484 // red
michael@0 485 CalcBitmask(aColorMask->red, begin, length);
michael@0 486 aColorMask->redRightShift = begin;
michael@0 487 aColorMask->redLeftShift = 8 - length;
michael@0 488 // green
michael@0 489 CalcBitmask(aColorMask->green, begin, length);
michael@0 490 aColorMask->greenRightShift = begin;
michael@0 491 aColorMask->greenLeftShift = 8 - length;
michael@0 492 // blue
michael@0 493 CalcBitmask(aColorMask->blue, begin, length);
michael@0 494 aColorMask->blueRightShift = begin;
michael@0 495 aColorMask->blueLeftShift = 8 - length;
michael@0 496 }

mercurial