| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
| 9 #include "SkImageDecoder.h" | 9 #include "SkImageDecoder.h" |
| 10 #include "SkStream.h" | 10 #include "SkStream.h" |
| 11 #include "SkStreamPriv.h" | 11 #include "SkStreamPriv.h" |
| 12 #include "SkTypes.h" | 12 #include "SkTypes.h" |
| 13 | 13 |
| 14 class SkICOImageDecoder : public SkImageDecoder { | 14 class SkICOImageDecoder : public SkImageDecoder { |
| 15 public: | 15 public: |
| 16 SkICOImageDecoder(); | 16 SkICOImageDecoder(); |
| 17 | 17 |
| 18 Format getFormat() const SK_OVERRIDE { | 18 SkEncodedFormat getFormat() const SK_OVERRIDE { |
| 19 return kICO_Format; | 19 return kICO_SkEncodedFormat; |
| 20 } | 20 } |
| 21 | 21 |
| 22 protected: | 22 protected: |
| 23 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; | 23 Result onDecode(SkStream* stream, SkBitmap* bm, Mode) SK_OVERRIDE; |
| 24 | 24 |
| 25 private: | 25 private: |
| 26 typedef SkImageDecoder INHERITED; | 26 typedef SkImageDecoder INHERITED; |
| 27 }; | 27 }; |
| 28 | 28 |
| 29 ////////////////////////////////////////////////////////////////////////////////
///////// | 29 ////////////////////////////////////////////////////////////////////////////////
///////// |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 return (w + 1) << 2; | 69 return (w + 1) << 2; |
| 70 } | 70 } |
| 71 // Otherwise return 0, which will allow it to be calculated automatically. | 71 // Otherwise return 0, which will allow it to be calculated automatically. |
| 72 return 0; | 72 return 0; |
| 73 } | 73 } |
| 74 | 74 |
| 75 SkImageDecoder::Result SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* b
m, Mode mode) | 75 SkImageDecoder::Result SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* b
m, Mode mode) |
| 76 { | 76 { |
| 77 SkAutoMalloc autoMal; | 77 SkAutoMalloc autoMal; |
| 78 const size_t length = SkCopyStreamToStorage(&autoMal, stream); | 78 const size_t length = SkCopyStreamToStorage(&autoMal, stream); |
| 79 // Check that the buffer is large enough to read the directory header | 79 if (0 == length) { |
| 80 if (length < 6) { | |
| 81 return kFailure; | 80 return kFailure; |
| 82 } | 81 } |
| 83 | 82 |
| 84 unsigned char* buf = (unsigned char*)autoMal.get(); | 83 unsigned char* buf = (unsigned char*)autoMal.get(); |
| 85 | 84 |
| 86 //these should always be the same - should i use for error checking? - what
about files that have some | 85 //these should always be the same - should i use for error checking? - what
about files that have some |
| 87 //incorrect values, but still decode properly? | 86 //incorrect values, but still decode properly? |
| 88 int reserved = read2Bytes(buf, 0); // 0 | 87 int reserved = read2Bytes(buf, 0); // 0 |
| 89 int type = read2Bytes(buf, 2); // 1 | 88 int type = read2Bytes(buf, 2); // 1 |
| 90 if (reserved != 0 || type != 1) { | 89 if (reserved != 0 || type != 1) { |
| 91 return kFailure; | 90 return kFailure; |
| 92 } | 91 } |
| 93 | 92 |
| 94 int count = read2Bytes(buf, 4); | 93 int count = read2Bytes(buf, 4); |
| 95 // Check that there are directory entries | |
| 96 if (count < 1) { | |
| 97 return kFailure; | |
| 98 } | |
| 99 | 94 |
| 100 // Check that buffer is large enough to read directory entries. | 95 //need to at least have enough space to hold the initial table of info |
| 101 // We are guaranteed that count is at least 1. We might as well assume | |
| 102 // count is 1 because this deprecated decoder only looks at the first | |
| 103 // directory entry. | |
| 104 if (length < (size_t)(6 + count*16)) { | 96 if (length < (size_t)(6 + count*16)) { |
| 105 return kFailure; | 97 return kFailure; |
| 106 } | 98 } |
| 107 | 99 |
| 108 //skip ahead to the correct header | 100 //skip ahead to the correct header |
| 109 //commented out lines are not used, but if i switch to other read method, ne
ed to know how many to skip | 101 //commented out lines are not used, but if i switch to other read method, ne
ed to know how many to skip |
| 110 //otherwise, they could be used for error checking | 102 //otherwise, they could be used for error checking |
| 111 int w = readByte(buf, 6); | 103 int w = readByte(buf, 6); |
| 112 int h = readByte(buf, 7); | 104 int h = readByte(buf, 7); |
| 113 SkASSERT(w >= 0 && h >= 0); | |
| 114 int colorCount = readByte(buf, 8); | 105 int colorCount = readByte(buf, 8); |
| 115 //int reservedToo = readByte(buf, 9 + choice*16); //0 | 106 //int reservedToo = readByte(buf, 9 + choice*16); //0 |
| 116 //int planes = read2Bytes(buf, 10 + choice*16); //1 - but often 0 | 107 //int planes = read2Bytes(buf, 10 + choice*16); //1 - but often 0 |
| 117 //int fakeBitCount = read2Bytes(buf, 12 + choice*16); //should be real - usu
ally 0 | 108 //int fakeBitCount = read2Bytes(buf, 12 + choice*16); //should be real - usu
ally 0 |
| 118 const size_t size = read4Bytes(buf, 14); //matters? | 109 const size_t size = read4Bytes(buf, 14); //matters? |
| 119 const size_t offset = read4Bytes(buf, 18); | 110 const size_t offset = read4Bytes(buf, 18); |
| 120 // promote the sum to 64-bits to avoid overflow | 111 // promote the sum to 64-bits to avoid overflow |
| 121 // Check that buffer is large enough to read image data | |
| 122 if (offset > length || size > length || ((uint64_t)offset + size) > length)
{ | 112 if (offset > length || size > length || ((uint64_t)offset + size) > length)
{ |
| 123 return kFailure; | 113 return kFailure; |
| 124 } | 114 } |
| 125 | 115 |
| 126 // Check to see if this is a PNG image inside the ICO | 116 // Check to see if this is a PNG image inside the ICO |
| 127 { | 117 { |
| 128 SkMemoryStream subStream(buf + offset, size, false); | 118 SkMemoryStream subStream(buf + offset, size, false); |
| 129 SkAutoTDelete<SkImageDecoder> otherDecoder(SkImageDecoder::Factory(&subS
tream)); | 119 SkAutoTDelete<SkImageDecoder> otherDecoder(SkImageDecoder::Factory(&subS
tream)); |
| 130 if (otherDecoder.get() != NULL) { | 120 if (otherDecoder.get() != NULL) { |
| 131 // Disallow nesting ICO files within one another | 121 // Disallow nesting ICO files within one another |
| 132 // FIXME: Can ICO files contain other formats besides PNG? | 122 // FIXME: Can ICO files contain other formats besides PNG? |
| 133 if (otherDecoder->getFormat() == SkImageDecoder::kICO_Format) { | 123 if (otherDecoder->getFormat() == kICO_SkEncodedFormat) { |
| 134 return kFailure; | 124 return kFailure; |
| 135 } | 125 } |
| 136 // Set fields on the other decoder to be the same as this one. | 126 // Set fields on the other decoder to be the same as this one. |
| 137 this->copyFieldsToOther(otherDecoder.get()); | 127 this->copyFieldsToOther(otherDecoder.get()); |
| 138 const Result result = otherDecoder->decode(&subStream, bm, this->get
DefaultPref(), | 128 const Result result = otherDecoder->decode(&subStream, bm, this->get
DefaultPref(), |
| 139 mode); | 129 mode); |
| 140 // FIXME: Should we just return result here? Is it possible that dat
a that looked like | 130 // FIXME: Should we just return result here? Is it possible that dat
a that looked like |
| 141 // a subimage was not, but was actually a valid ICO? | 131 // a subimage was not, but was actually a valid ICO? |
| 142 if (result != kFailure) { | 132 if (result != kFailure) { |
| 143 return result; | 133 return result; |
| 144 } | 134 } |
| 145 } | 135 } |
| 146 } | 136 } |
| 147 | 137 |
| 148 //int infoSize = read4Bytes(buf, offset); //40 | 138 //int infoSize = read4Bytes(buf, offset); //40 |
| 149 //int width = read4Bytes(buf, offset+4); //should == w | 139 //int width = read4Bytes(buf, offset+4); //should == w |
| 150 //int height = read4Bytes(buf, offset+8); //should == 2*h | 140 //int height = read4Bytes(buf, offset+8); //should == 2*h |
| 151 //int planesToo = read2Bytes(buf, offset+12); //should == 1 (does it
?) | 141 //int planesToo = read2Bytes(buf, offset+12); //should == 1 (does it
?) |
| 152 | |
| 153 // For ico images, only a byte is used to store each dimension | |
| 154 // 0 is used to represent 256 | |
| 155 if (w == 0) { | |
| 156 w = 256; | |
| 157 } | |
| 158 if (h == 0) { | |
| 159 h = 256; | |
| 160 } | |
| 161 | |
| 162 // Check that buffer is large enough to read the bit depth | |
| 163 if (length < offset + 16) { | |
| 164 return kFailure; | |
| 165 } | |
| 166 int bitCount = read2Bytes(buf, offset+14); | 142 int bitCount = read2Bytes(buf, offset+14); |
| 167 | 143 |
| 168 void (*placePixel)(const int pixelNo, const unsigned char* buf, | 144 void (*placePixel)(const int pixelNo, const unsigned char* buf, |
| 169 const int xorOffset, int& x, int y, const int w, | 145 const int xorOffset, int& x, int y, const int w, |
| 170 SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors) = NULL
; | 146 SkBitmap* bm, int alphaByte, int m, int shift, SkPMColor* colors) = NULL
; |
| 171 switch (bitCount) | 147 switch (bitCount) |
| 172 { | 148 { |
| 173 case 1: | 149 case 1: |
| 174 placePixel = &editPixelBit1; | 150 placePixel = &editPixelBit1; |
| 175 colorCount = 2; | 151 colorCount = 2; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 197 | 173 |
| 198 //these should all be zero, but perhaps are not - need to check | 174 //these should all be zero, but perhaps are not - need to check |
| 199 //int compression = read4Bytes(buf, offset+16); //0 | 175 //int compression = read4Bytes(buf, offset+16); //0 |
| 200 //int imageSize = read4Bytes(buf, offset+20); //0 - sometimes has a
value | 176 //int imageSize = read4Bytes(buf, offset+20); //0 - sometimes has a
value |
| 201 //int xPixels = read4Bytes(buf, offset+24); //0 | 177 //int xPixels = read4Bytes(buf, offset+24); //0 |
| 202 //int yPixels = read4Bytes(buf, offset+28); //0 | 178 //int yPixels = read4Bytes(buf, offset+28); //0 |
| 203 //int colorsUsed = read4Bytes(buf, offset+32) //0 - might have an ac
tual value though | 179 //int colorsUsed = read4Bytes(buf, offset+32) //0 - might have an ac
tual value though |
| 204 //int colorsImportant = read4Bytes(buf, offset+36); //0 | 180 //int colorsImportant = read4Bytes(buf, offset+36); //0 |
| 205 | 181 |
| 206 int begin = SkToInt(offset + 40); | 182 int begin = SkToInt(offset + 40); |
| 207 // Check that the buffer is large enough to read the color table | |
| 208 // For bmp-in-icos, there should be 4 bytes per color | |
| 209 if (length < (size_t) (begin + 4*colorCount)) { | |
| 210 return kFailure; | |
| 211 } | |
| 212 | |
| 213 //this array represents the colortable | 183 //this array represents the colortable |
| 214 //if i allow other types of bitmaps, it may actually be used as a part of th
e bitmap | 184 //if i allow other types of bitmaps, it may actually be used as a part of th
e bitmap |
| 215 SkPMColor* colors = NULL; | 185 SkPMColor* colors = NULL; |
| 216 int blue, green, red; | 186 int blue, green, red; |
| 217 if (colorCount) | 187 if (colorCount) |
| 218 { | 188 { |
| 219 colors = new SkPMColor[colorCount]; | 189 colors = new SkPMColor[colorCount]; |
| 220 for (int j = 0; j < colorCount; j++) | 190 for (int j = 0; j < colorCount; j++) |
| 221 { | 191 { |
| 222 //should this be a function - maybe a #define? | 192 //should this be a function - maybe a #define? |
| (...skipping 28 matching lines...) Expand all Loading... |
| 251 delete[] colors; | 221 delete[] colors; |
| 252 return kSuccess; | 222 return kSuccess; |
| 253 } | 223 } |
| 254 | 224 |
| 255 if (!this->allocPixelRef(bm, NULL)) | 225 if (!this->allocPixelRef(bm, NULL)) |
| 256 { | 226 { |
| 257 delete[] colors; | 227 delete[] colors; |
| 258 return kFailure; | 228 return kFailure; |
| 259 } | 229 } |
| 260 | 230 |
| 261 // The AND mask is a 1-bit alpha mask for each pixel that comes after the | |
| 262 // XOR mask in the bmp. If we check that the largest AND offset is safe, | |
| 263 // it should mean all other buffer accesses will be at smaller indices and | |
| 264 // will therefore be safe. | |
| 265 size_t maxAndOffset = andOffset + ((andLineWidth*(h-1)+(w-1)) >> 3); | |
| 266 if (length <= maxAndOffset) { | |
| 267 return kFailure; | |
| 268 } | |
| 269 | |
| 270 // Here we assert that all reads from the buffer using the XOR offset are | |
| 271 // less than the AND offset. This should be guaranteed based on the above | |
| 272 // calculations. | |
| 273 #ifdef SK_DEBUG | |
| 274 int maxPixelNum = lineWidth*(h-1)+w-1; | |
| 275 int maxByte; | |
| 276 switch (bitCount) { | |
| 277 case 1: | |
| 278 maxByte = maxPixelNum >> 3; | |
| 279 break; | |
| 280 case 4: | |
| 281 maxByte = maxPixelNum >> 1; | |
| 282 break; | |
| 283 case 8: | |
| 284 maxByte = maxPixelNum; | |
| 285 break; | |
| 286 case 24: | |
| 287 maxByte = maxPixelNum * 3 + 2; | |
| 288 break; | |
| 289 case 32: | |
| 290 maxByte = maxPixelNum * 4 + 3; | |
| 291 break; | |
| 292 default: | |
| 293 SkASSERT(false); | |
| 294 return kFailure; | |
| 295 } | |
| 296 int maxXOROffset = xorOffset + maxByte; | |
| 297 SkASSERT(maxXOROffset < andOffset); | |
| 298 #endif | |
| 299 | |
| 300 SkAutoLockPixels alp(*bm); | 231 SkAutoLockPixels alp(*bm); |
| 301 | 232 |
| 302 for (int y = 0; y < h; y++) | 233 for (int y = 0; y < h; y++) |
| 303 { | 234 { |
| 304 for (int x = 0; x < w; x++) | 235 for (int x = 0; x < w; x++) |
| 305 { | 236 { |
| 306 //U32* address = bm->getAddr32(x, y); | 237 //U32* address = bm->getAddr32(x, y); |
| 307 | 238 |
| 308 //check the alpha bit first, but pass it along to the function to fi
gure out how to deal with it | 239 //check the alpha bit first, but pass it along to the function to fi
gure out how to deal with it |
| 309 int andPixelNo = andLineWidth*(h-y-1)+x; | 240 int andPixelNo = andLineWidth*(h-y-1)+x; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 366 |
| 436 static SkImageDecoder* sk_libico_dfactory(SkStreamRewindable* stream) { | 367 static SkImageDecoder* sk_libico_dfactory(SkStreamRewindable* stream) { |
| 437 if (is_ico(stream)) { | 368 if (is_ico(stream)) { |
| 438 return SkNEW(SkICOImageDecoder); | 369 return SkNEW(SkICOImageDecoder); |
| 439 } | 370 } |
| 440 return NULL; | 371 return NULL; |
| 441 } | 372 } |
| 442 | 373 |
| 443 static SkImageDecoder_DecodeReg gReg(sk_libico_dfactory); | 374 static SkImageDecoder_DecodeReg gReg(sk_libico_dfactory); |
| 444 | 375 |
| 445 static SkImageDecoder::Format get_format_ico(SkStreamRewindable* stream) { | 376 SkEncodedFormat get_format_ico(SkStreamRewindable* stream) { |
| 446 if (is_ico(stream)) { | 377 if (is_ico(stream)) { |
| 447 return SkImageDecoder::kICO_Format; | 378 return kICO_SkEncodedFormat; |
| 448 } | 379 } |
| 449 return SkImageDecoder::kUnknown_Format; | 380 return kUnknown_SkEncodedFormat; |
| 450 } | 381 } |
| 451 | 382 |
| 452 static SkImageDecoder_FormatReg gFormatReg(get_format_ico); | 383 static SkImageDecoder_FormatReg gFormatReg(get_format_ico); |
| OLD | NEW |