image/encoders/ico/nsICOEncoder.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 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsCRT.h"
michael@0 6 #include "mozilla/Endian.h"
michael@0 7 #include "nsBMPEncoder.h"
michael@0 8 #include "nsPNGEncoder.h"
michael@0 9 #include "nsICOEncoder.h"
michael@0 10 #include "prprf.h"
michael@0 11 #include "nsString.h"
michael@0 12 #include "nsStreamUtils.h"
michael@0 13 #include "nsTArray.h"
michael@0 14
michael@0 15 using namespace mozilla;
michael@0 16 using namespace mozilla::image;
michael@0 17
michael@0 18 NS_IMPL_ISUPPORTS(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
michael@0 19
michael@0 20 nsICOEncoder::nsICOEncoder() : mImageBufferStart(nullptr),
michael@0 21 mImageBufferCurr(0),
michael@0 22 mImageBufferSize(0),
michael@0 23 mImageBufferReadPoint(0),
michael@0 24 mFinished(false),
michael@0 25 mUsePNG(true),
michael@0 26 mNotifyThreshold(0)
michael@0 27 {
michael@0 28 }
michael@0 29
michael@0 30 nsICOEncoder::~nsICOEncoder()
michael@0 31 {
michael@0 32 if (mImageBufferStart) {
michael@0 33 moz_free(mImageBufferStart);
michael@0 34 mImageBufferStart = nullptr;
michael@0 35 mImageBufferCurr = nullptr;
michael@0 36 }
michael@0 37 }
michael@0 38
michael@0 39 // nsICOEncoder::InitFromData
michael@0 40 // Two output options are supported: format=<png|bmp>;bpp=<bpp_value>
michael@0 41 // format specifies whether to use png or bitmap format
michael@0 42 // bpp specifies the bits per pixel to use where bpp_value can be 24 or 32
michael@0 43 NS_IMETHODIMP nsICOEncoder::InitFromData(const uint8_t* aData,
michael@0 44 uint32_t aLength,
michael@0 45 uint32_t aWidth,
michael@0 46 uint32_t aHeight,
michael@0 47 uint32_t aStride,
michael@0 48 uint32_t aInputFormat,
michael@0 49 const nsAString& aOutputOptions)
michael@0 50 {
michael@0 51 // validate input format
michael@0 52 if (aInputFormat != INPUT_FORMAT_RGB &&
michael@0 53 aInputFormat != INPUT_FORMAT_RGBA &&
michael@0 54 aInputFormat != INPUT_FORMAT_HOSTARGB) {
michael@0 55 return NS_ERROR_INVALID_ARG;
michael@0 56 }
michael@0 57
michael@0 58 // Stride is the padded width of each row, so it better be longer
michael@0 59 if ((aInputFormat == INPUT_FORMAT_RGB &&
michael@0 60 aStride < aWidth * 3) ||
michael@0 61 ((aInputFormat == INPUT_FORMAT_RGBA || aInputFormat == INPUT_FORMAT_HOSTARGB) &&
michael@0 62 aStride < aWidth * 4)) {
michael@0 63 NS_WARNING("Invalid stride for InitFromData");
michael@0 64 return NS_ERROR_INVALID_ARG;
michael@0 65 }
michael@0 66
michael@0 67 nsresult rv;
michael@0 68 rv = StartImageEncode(aWidth, aHeight, aInputFormat, aOutputOptions);
michael@0 69 NS_ENSURE_SUCCESS(rv, rv);
michael@0 70
michael@0 71 rv = AddImageFrame(aData, aLength, aWidth, aHeight, aStride,
michael@0 72 aInputFormat, aOutputOptions);
michael@0 73 NS_ENSURE_SUCCESS(rv, rv);
michael@0 74
michael@0 75 rv = EndImageEncode();
michael@0 76 return rv;
michael@0 77 }
michael@0 78
michael@0 79 // Returns the number of bytes in the image buffer used
michael@0 80 // For an ICO file, this is all bytes in the buffer.
michael@0 81 NS_IMETHODIMP
michael@0 82 nsICOEncoder::GetImageBufferUsed(uint32_t *aOutputSize)
michael@0 83 {
michael@0 84 NS_ENSURE_ARG_POINTER(aOutputSize);
michael@0 85 *aOutputSize = mImageBufferSize;
michael@0 86 return NS_OK;
michael@0 87 }
michael@0 88
michael@0 89 // Returns a pointer to the start of the image buffer
michael@0 90 NS_IMETHODIMP
michael@0 91 nsICOEncoder::GetImageBuffer(char **aOutputBuffer)
michael@0 92 {
michael@0 93 NS_ENSURE_ARG_POINTER(aOutputBuffer);
michael@0 94 *aOutputBuffer = reinterpret_cast<char*>(mImageBufferStart);
michael@0 95 return NS_OK;
michael@0 96 }
michael@0 97
michael@0 98 NS_IMETHODIMP
michael@0 99 nsICOEncoder::AddImageFrame(const uint8_t* aData,
michael@0 100 uint32_t aLength,
michael@0 101 uint32_t aWidth,
michael@0 102 uint32_t aHeight,
michael@0 103 uint32_t aStride,
michael@0 104 uint32_t aInputFormat,
michael@0 105 const nsAString& aFrameOptions)
michael@0 106 {
michael@0 107 if (mUsePNG) {
michael@0 108
michael@0 109 mContainedEncoder = new nsPNGEncoder();
michael@0 110 nsresult rv;
michael@0 111 nsAutoString noParams;
michael@0 112 rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight,
michael@0 113 aStride, aInputFormat, noParams);
michael@0 114 NS_ENSURE_SUCCESS(rv, rv);
michael@0 115
michael@0 116 uint32_t PNGImageBufferSize;
michael@0 117 mContainedEncoder->GetImageBufferUsed(&PNGImageBufferSize);
michael@0 118 mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE +
michael@0 119 PNGImageBufferSize;
michael@0 120 mImageBufferStart = static_cast<uint8_t*>(moz_malloc(mImageBufferSize));
michael@0 121 if (!mImageBufferStart) {
michael@0 122 return NS_ERROR_OUT_OF_MEMORY;
michael@0 123 }
michael@0 124 mImageBufferCurr = mImageBufferStart;
michael@0 125 mICODirEntry.mBytesInRes = PNGImageBufferSize;
michael@0 126
michael@0 127 EncodeFileHeader();
michael@0 128 EncodeInfoHeader();
michael@0 129
michael@0 130 char *imageBuffer;
michael@0 131 rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
michael@0 132 NS_ENSURE_SUCCESS(rv, rv);
michael@0 133 memcpy(mImageBufferCurr, imageBuffer, PNGImageBufferSize);
michael@0 134 mImageBufferCurr += PNGImageBufferSize;
michael@0 135 } else {
michael@0 136 mContainedEncoder = new nsBMPEncoder();
michael@0 137 nsresult rv;
michael@0 138
michael@0 139 nsAutoString params;
michael@0 140 params.AppendLiteral("bpp=");
michael@0 141 params.AppendInt(mICODirEntry.mBitCount);
michael@0 142
michael@0 143 rv = mContainedEncoder->InitFromData(aData, aLength, aWidth, aHeight,
michael@0 144 aStride, aInputFormat, params);
michael@0 145 NS_ENSURE_SUCCESS(rv, rv);
michael@0 146
michael@0 147 uint32_t andMaskSize = ((GetRealWidth() + 31) / 32) * 4 * // row AND mask
michael@0 148 GetRealHeight(); // num rows
michael@0 149
michael@0 150 uint32_t BMPImageBufferSize;
michael@0 151 mContainedEncoder->GetImageBufferUsed(&BMPImageBufferSize);
michael@0 152 mImageBufferSize = ICONFILEHEADERSIZE + ICODIRENTRYSIZE +
michael@0 153 BMPImageBufferSize + andMaskSize;
michael@0 154 mImageBufferStart = static_cast<uint8_t*>(moz_malloc(mImageBufferSize));
michael@0 155 if (!mImageBufferStart) {
michael@0 156 return NS_ERROR_OUT_OF_MEMORY;
michael@0 157 }
michael@0 158 mImageBufferCurr = mImageBufferStart;
michael@0 159
michael@0 160 // The icon buffer does not include the BFH at all.
michael@0 161 mICODirEntry.mBytesInRes = BMPImageBufferSize - BFH_LENGTH + andMaskSize;
michael@0 162
michael@0 163 // Encode the icon headers
michael@0 164 EncodeFileHeader();
michael@0 165 EncodeInfoHeader();
michael@0 166
michael@0 167 char *imageBuffer;
michael@0 168 rv = mContainedEncoder->GetImageBuffer(&imageBuffer);
michael@0 169 NS_ENSURE_SUCCESS(rv, rv);
michael@0 170 memcpy(mImageBufferCurr, imageBuffer + BFH_LENGTH,
michael@0 171 BMPImageBufferSize - BFH_LENGTH);
michael@0 172 // We need to fix the BMP height to be *2 for the AND mask
michael@0 173 uint32_t fixedHeight = GetRealHeight() * 2;
michael@0 174 NativeEndian::swapToLittleEndianInPlace(&fixedHeight, 1);
michael@0 175 // The height is stored at an offset of 8 from the DIB header
michael@0 176 memcpy(mImageBufferCurr + 8, &fixedHeight, sizeof(fixedHeight));
michael@0 177 mImageBufferCurr += BMPImageBufferSize - BFH_LENGTH;
michael@0 178
michael@0 179 // Calculate rowsize in DWORD's
michael@0 180 uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
michael@0 181 int32_t currentLine = GetRealHeight();
michael@0 182
michael@0 183 // Write out the AND mask
michael@0 184 while (currentLine > 0) {
michael@0 185 currentLine--;
michael@0 186 uint8_t* encoded = mImageBufferCurr + currentLine * rowSize;
michael@0 187 uint8_t* encodedEnd = encoded + rowSize;
michael@0 188 while (encoded != encodedEnd) {
michael@0 189 *encoded = 0; // make everything visible
michael@0 190 encoded++;
michael@0 191 }
michael@0 192 }
michael@0 193
michael@0 194 mImageBufferCurr += andMaskSize;
michael@0 195 }
michael@0 196
michael@0 197 return NS_OK;
michael@0 198 }
michael@0 199
michael@0 200 // See ::InitFromData for other info.
michael@0 201 NS_IMETHODIMP nsICOEncoder::StartImageEncode(uint32_t aWidth,
michael@0 202 uint32_t aHeight,
michael@0 203 uint32_t aInputFormat,
michael@0 204 const nsAString& aOutputOptions)
michael@0 205 {
michael@0 206 // can't initialize more than once
michael@0 207 if (mImageBufferStart || mImageBufferCurr) {
michael@0 208 return NS_ERROR_ALREADY_INITIALIZED;
michael@0 209 }
michael@0 210
michael@0 211 // validate input format
michael@0 212 if (aInputFormat != INPUT_FORMAT_RGB &&
michael@0 213 aInputFormat != INPUT_FORMAT_RGBA &&
michael@0 214 aInputFormat != INPUT_FORMAT_HOSTARGB) {
michael@0 215 return NS_ERROR_INVALID_ARG;
michael@0 216 }
michael@0 217
michael@0 218 // Icons are only 1 byte, so make sure our bitmap is in range
michael@0 219 if (aWidth > 256 || aHeight > 256) {
michael@0 220 return NS_ERROR_INVALID_ARG;
michael@0 221 }
michael@0 222
michael@0 223 // parse and check any provided output options
michael@0 224 uint32_t bpp = 24;
michael@0 225 bool usePNG = true;
michael@0 226 nsresult rv = ParseOptions(aOutputOptions, &bpp, &usePNG);
michael@0 227 NS_ENSURE_SUCCESS(rv, rv);
michael@0 228
michael@0 229 mUsePNG = usePNG;
michael@0 230
michael@0 231 InitFileHeader();
michael@0 232 // The width and height are stored as 0 when we have a value of 256
michael@0 233 InitInfoHeader(bpp, aWidth == 256 ? 0 : (uint8_t)aWidth,
michael@0 234 aHeight == 256 ? 0 : (uint8_t)aHeight);
michael@0 235
michael@0 236 return NS_OK;
michael@0 237 }
michael@0 238
michael@0 239 NS_IMETHODIMP nsICOEncoder::EndImageEncode()
michael@0 240 {
michael@0 241 // must be initialized
michael@0 242 if (!mImageBufferStart || !mImageBufferCurr) {
michael@0 243 return NS_ERROR_NOT_INITIALIZED;
michael@0 244 }
michael@0 245
michael@0 246 mFinished = true;
michael@0 247 NotifyListener();
michael@0 248
michael@0 249 // if output callback can't get enough memory, it will free our buffer
michael@0 250 if (!mImageBufferStart || !mImageBufferCurr) {
michael@0 251 return NS_ERROR_OUT_OF_MEMORY;
michael@0 252 }
michael@0 253
michael@0 254 return NS_OK;
michael@0 255 }
michael@0 256
michael@0 257 // Parses the encoder options and sets the bits per pixel to use and PNG or BMP
michael@0 258 // See InitFromData for a description of the parse options
michael@0 259 nsresult
michael@0 260 nsICOEncoder::ParseOptions(const nsAString& aOptions, uint32_t* bpp,
michael@0 261 bool *usePNG)
michael@0 262 {
michael@0 263 // If no parsing options just use the default of 24BPP and PNG yes
michael@0 264 if (aOptions.Length() == 0) {
michael@0 265 if (usePNG) {
michael@0 266 *usePNG = true;
michael@0 267 }
michael@0 268 if (bpp) {
michael@0 269 *bpp = 24;
michael@0 270 }
michael@0 271 }
michael@0 272
michael@0 273 // Parse the input string into a set of name/value pairs.
michael@0 274 // From format: format=<png|bmp>;bpp=<bpp_value>
michael@0 275 // to format: [0] = format=<png|bmp>, [1] = bpp=<bpp_value>
michael@0 276 nsTArray<nsCString> nameValuePairs;
michael@0 277 if (!ParseString(NS_ConvertUTF16toUTF8(aOptions), ';', nameValuePairs)) {
michael@0 278 return NS_ERROR_INVALID_ARG;
michael@0 279 }
michael@0 280
michael@0 281 // For each name/value pair in the set
michael@0 282 for (unsigned i = 0; i < nameValuePairs.Length(); ++i) {
michael@0 283
michael@0 284 // Split the name value pair [0] = name, [1] = value
michael@0 285 nsTArray<nsCString> nameValuePair;
michael@0 286 if (!ParseString(nameValuePairs[i], '=', nameValuePair)) {
michael@0 287 return NS_ERROR_INVALID_ARG;
michael@0 288 }
michael@0 289 if (nameValuePair.Length() != 2) {
michael@0 290 return NS_ERROR_INVALID_ARG;
michael@0 291 }
michael@0 292
michael@0 293 // Parse the format portion of the string format=<png|bmp>;bpp=<bpp_value>
michael@0 294 if (nameValuePair[0].Equals("format", nsCaseInsensitiveCStringComparator())) {
michael@0 295 if (nameValuePair[1].Equals("png", nsCaseInsensitiveCStringComparator())) {
michael@0 296 *usePNG = true;
michael@0 297 }
michael@0 298 else if (nameValuePair[1].Equals("bmp", nsCaseInsensitiveCStringComparator())) {
michael@0 299 *usePNG = false;
michael@0 300 }
michael@0 301 else {
michael@0 302 return NS_ERROR_INVALID_ARG;
michael@0 303 }
michael@0 304 }
michael@0 305
michael@0 306 // Parse the bpp portion of the string format=<png|bmp>;bpp=<bpp_value>
michael@0 307 if (nameValuePair[0].Equals("bpp", nsCaseInsensitiveCStringComparator())) {
michael@0 308 if (nameValuePair[1].Equals("24")) {
michael@0 309 *bpp = 24;
michael@0 310 }
michael@0 311 else if (nameValuePair[1].Equals("32")) {
michael@0 312 *bpp = 32;
michael@0 313 }
michael@0 314 else {
michael@0 315 return NS_ERROR_INVALID_ARG;
michael@0 316 }
michael@0 317 }
michael@0 318 }
michael@0 319
michael@0 320 return NS_OK;
michael@0 321 }
michael@0 322
michael@0 323 NS_IMETHODIMP nsICOEncoder::Close()
michael@0 324 {
michael@0 325 if (mImageBufferStart) {
michael@0 326 moz_free(mImageBufferStart);
michael@0 327 mImageBufferStart = nullptr;
michael@0 328 mImageBufferSize = 0;
michael@0 329 mImageBufferReadPoint = 0;
michael@0 330 mImageBufferCurr = nullptr;
michael@0 331 }
michael@0 332
michael@0 333 return NS_OK;
michael@0 334 }
michael@0 335
michael@0 336 // Obtains the available bytes to read
michael@0 337 NS_IMETHODIMP nsICOEncoder::Available(uint64_t *_retval)
michael@0 338 {
michael@0 339 if (!mImageBufferStart || !mImageBufferCurr) {
michael@0 340 return NS_BASE_STREAM_CLOSED;
michael@0 341 }
michael@0 342
michael@0 343 *_retval = GetCurrentImageBufferOffset() - mImageBufferReadPoint;
michael@0 344 return NS_OK;
michael@0 345 }
michael@0 346
michael@0 347 // [noscript] Reads bytes which are available
michael@0 348 NS_IMETHODIMP nsICOEncoder::Read(char *aBuf, uint32_t aCount,
michael@0 349 uint32_t *_retval)
michael@0 350 {
michael@0 351 return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
michael@0 352 }
michael@0 353
michael@0 354 // [noscript] Reads segments
michael@0 355 NS_IMETHODIMP nsICOEncoder::ReadSegments(nsWriteSegmentFun aWriter,
michael@0 356 void *aClosure, uint32_t aCount,
michael@0 357 uint32_t *_retval)
michael@0 358 {
michael@0 359 uint32_t maxCount = GetCurrentImageBufferOffset() - mImageBufferReadPoint;
michael@0 360 if (maxCount == 0) {
michael@0 361 *_retval = 0;
michael@0 362 return mFinished ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
michael@0 363 }
michael@0 364
michael@0 365 if (aCount > maxCount) {
michael@0 366 aCount = maxCount;
michael@0 367 }
michael@0 368
michael@0 369 nsresult rv = aWriter(this, aClosure,
michael@0 370 reinterpret_cast<const char*>(mImageBufferStart +
michael@0 371 mImageBufferReadPoint),
michael@0 372 0, aCount, _retval);
michael@0 373 if (NS_SUCCEEDED(rv)) {
michael@0 374 NS_ASSERTION(*_retval <= aCount, "bad write count");
michael@0 375 mImageBufferReadPoint += *_retval;
michael@0 376 }
michael@0 377 // errors returned from the writer end here!
michael@0 378 return NS_OK;
michael@0 379 }
michael@0 380
michael@0 381 NS_IMETHODIMP
michael@0 382 nsICOEncoder::IsNonBlocking(bool *_retval)
michael@0 383 {
michael@0 384 *_retval = true;
michael@0 385 return NS_OK;
michael@0 386 }
michael@0 387
michael@0 388 NS_IMETHODIMP
michael@0 389 nsICOEncoder::AsyncWait(nsIInputStreamCallback *aCallback,
michael@0 390 uint32_t aFlags,
michael@0 391 uint32_t aRequestedCount,
michael@0 392 nsIEventTarget *aTarget)
michael@0 393 {
michael@0 394 if (aFlags != 0) {
michael@0 395 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 396 }
michael@0 397
michael@0 398 if (mCallback || mCallbackTarget) {
michael@0 399 return NS_ERROR_UNEXPECTED;
michael@0 400 }
michael@0 401
michael@0 402 mCallbackTarget = aTarget;
michael@0 403 // 0 means "any number of bytes except 0"
michael@0 404 mNotifyThreshold = aRequestedCount;
michael@0 405 if (!aRequestedCount) {
michael@0 406 mNotifyThreshold = 1024; // We don't want to notify incessantly
michael@0 407 }
michael@0 408
michael@0 409 // We set the callback absolutely last, because NotifyListener uses it to
michael@0 410 // determine if someone needs to be notified. If we don't set it last,
michael@0 411 // NotifyListener might try to fire off a notification to a null target
michael@0 412 // which will generally cause non-threadsafe objects to be used off the main thread
michael@0 413 mCallback = aCallback;
michael@0 414
michael@0 415 // What we are being asked for may be present already
michael@0 416 NotifyListener();
michael@0 417 return NS_OK;
michael@0 418 }
michael@0 419
michael@0 420 NS_IMETHODIMP nsICOEncoder::CloseWithStatus(nsresult aStatus)
michael@0 421 {
michael@0 422 return Close();
michael@0 423 }
michael@0 424
michael@0 425 void
michael@0 426 nsICOEncoder::NotifyListener()
michael@0 427 {
michael@0 428 if (mCallback &&
michael@0 429 (GetCurrentImageBufferOffset() - mImageBufferReadPoint >= mNotifyThreshold ||
michael@0 430 mFinished)) {
michael@0 431 nsCOMPtr<nsIInputStreamCallback> callback;
michael@0 432 if (mCallbackTarget) {
michael@0 433 callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget);
michael@0 434 } else {
michael@0 435 callback = mCallback;
michael@0 436 }
michael@0 437
michael@0 438 NS_ASSERTION(callback, "Shouldn't fail to make the callback");
michael@0 439 // Null the callback first because OnInputStreamReady could reenter
michael@0 440 // AsyncWait
michael@0 441 mCallback = nullptr;
michael@0 442 mCallbackTarget = nullptr;
michael@0 443 mNotifyThreshold = 0;
michael@0 444
michael@0 445 callback->OnInputStreamReady(this);
michael@0 446 }
michael@0 447 }
michael@0 448
michael@0 449 // Initializes the icon file header mICOFileHeader
michael@0 450 void
michael@0 451 nsICOEncoder::InitFileHeader()
michael@0 452 {
michael@0 453 memset(&mICOFileHeader, 0, sizeof(mICOFileHeader));
michael@0 454 mICOFileHeader.mReserved = 0;
michael@0 455 mICOFileHeader.mType = 1;
michael@0 456 mICOFileHeader.mCount = 1;
michael@0 457 }
michael@0 458
michael@0 459 // Initializes the icon directory info header mICODirEntry
michael@0 460 void
michael@0 461 nsICOEncoder::InitInfoHeader(uint32_t aBPP, uint8_t aWidth, uint8_t aHeight)
michael@0 462 {
michael@0 463 memset(&mICODirEntry, 0, sizeof(mICODirEntry));
michael@0 464 mICODirEntry.mBitCount = aBPP;
michael@0 465 mICODirEntry.mBytesInRes = 0;
michael@0 466 mICODirEntry.mColorCount = 0;
michael@0 467 mICODirEntry.mWidth = aWidth;
michael@0 468 mICODirEntry.mHeight = aHeight;
michael@0 469 mICODirEntry.mImageOffset = ICONFILEHEADERSIZE + ICODIRENTRYSIZE;
michael@0 470 mICODirEntry.mPlanes = 1;
michael@0 471 mICODirEntry.mReserved = 0;
michael@0 472 }
michael@0 473
michael@0 474 // Encodes the icon file header mICOFileHeader
michael@0 475 void
michael@0 476 nsICOEncoder::EncodeFileHeader()
michael@0 477 {
michael@0 478 IconFileHeader littleEndianIFH = mICOFileHeader;
michael@0 479 NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mReserved, 1);
michael@0 480 NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mType, 1);
michael@0 481 NativeEndian::swapToLittleEndianInPlace(&littleEndianIFH.mCount, 1);
michael@0 482
michael@0 483 memcpy(mImageBufferCurr, &littleEndianIFH.mReserved,
michael@0 484 sizeof(littleEndianIFH.mReserved));
michael@0 485 mImageBufferCurr += sizeof(littleEndianIFH.mReserved);
michael@0 486 memcpy(mImageBufferCurr, &littleEndianIFH.mType,
michael@0 487 sizeof(littleEndianIFH.mType));
michael@0 488 mImageBufferCurr += sizeof(littleEndianIFH.mType);
michael@0 489 memcpy(mImageBufferCurr, &littleEndianIFH.mCount,
michael@0 490 sizeof(littleEndianIFH.mCount));
michael@0 491 mImageBufferCurr += sizeof(littleEndianIFH.mCount);
michael@0 492 }
michael@0 493
michael@0 494 // Encodes the icon directory info header mICODirEntry
michael@0 495 void
michael@0 496 nsICOEncoder::EncodeInfoHeader()
michael@0 497 {
michael@0 498 IconDirEntry littleEndianmIDE = mICODirEntry;
michael@0 499
michael@0 500 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mPlanes, 1);
michael@0 501 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mBitCount, 1);
michael@0 502 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mBytesInRes, 1);
michael@0 503 NativeEndian::swapToLittleEndianInPlace(&littleEndianmIDE.mImageOffset, 1);
michael@0 504
michael@0 505 memcpy(mImageBufferCurr, &littleEndianmIDE.mWidth,
michael@0 506 sizeof(littleEndianmIDE.mWidth));
michael@0 507 mImageBufferCurr += sizeof(littleEndianmIDE.mWidth);
michael@0 508 memcpy(mImageBufferCurr, &littleEndianmIDE.mHeight,
michael@0 509 sizeof(littleEndianmIDE.mHeight));
michael@0 510 mImageBufferCurr += sizeof(littleEndianmIDE.mHeight);
michael@0 511 memcpy(mImageBufferCurr, &littleEndianmIDE.mColorCount,
michael@0 512 sizeof(littleEndianmIDE.mColorCount));
michael@0 513 mImageBufferCurr += sizeof(littleEndianmIDE.mColorCount);
michael@0 514 memcpy(mImageBufferCurr, &littleEndianmIDE.mReserved,
michael@0 515 sizeof(littleEndianmIDE.mReserved));
michael@0 516 mImageBufferCurr += sizeof(littleEndianmIDE.mReserved);
michael@0 517 memcpy(mImageBufferCurr, &littleEndianmIDE.mPlanes,
michael@0 518 sizeof(littleEndianmIDE.mPlanes));
michael@0 519 mImageBufferCurr += sizeof(littleEndianmIDE.mPlanes);
michael@0 520 memcpy(mImageBufferCurr, &littleEndianmIDE.mBitCount,
michael@0 521 sizeof(littleEndianmIDE.mBitCount));
michael@0 522 mImageBufferCurr += sizeof(littleEndianmIDE.mBitCount);
michael@0 523 memcpy(mImageBufferCurr, &littleEndianmIDE.mBytesInRes,
michael@0 524 sizeof(littleEndianmIDE.mBytesInRes));
michael@0 525 mImageBufferCurr += sizeof(littleEndianmIDE.mBytesInRes);
michael@0 526 memcpy(mImageBufferCurr, &littleEndianmIDE.mImageOffset,
michael@0 527 sizeof(littleEndianmIDE.mImageOffset));
michael@0 528 mImageBufferCurr += sizeof(littleEndianmIDE.mImageOffset);
michael@0 529 }

mercurial