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