gfx/skia/trunk/src/images/bmpdecoderhelper.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     2 /*
     3  * Copyright 2007 The Android Open Source Project
     4  *
     5  * Use of this source code is governed by a BSD-style license that can be
     6  * found in the LICENSE file.
     7  */
     9 // Author: cevans@google.com (Chris Evans)
    11 #include "bmpdecoderhelper.h"
    13 namespace image_codec {
    15 static const int kBmpHeaderSize = 14;
    16 static const int kBmpInfoSize = 40;
    17 static const int kBmpOS2InfoSize = 12;
    18 static const int kMaxDim = SHRT_MAX / 2;
    20 bool BmpDecoderHelper::DecodeImage(const char* p,
    21                                    size_t len,
    22                                    int max_pixels,
    23                                    BmpDecoderCallback* callback) {
    24   data_ = reinterpret_cast<const uint8*>(p);
    25   pos_ = 0;
    26   len_ = len;
    27   inverted_ = true;
    28   // Parse the header structure.
    29   if (len < kBmpHeaderSize + 4) {
    30     return false;
    31   }
    32   GetShort();  // Signature.
    33   GetInt();  // Size.
    34   GetInt();  // Reserved.
    35   int offset = GetInt();
    36   // Parse the info structure.
    37   int infoSize = GetInt();
    38   if (infoSize != kBmpOS2InfoSize && infoSize < kBmpInfoSize) {
    39     return false;
    40   }
    41   int cols = 0;
    42   int comp = 0;
    43   int colLen = 4;
    44   if (infoSize >= kBmpInfoSize) {
    45     if (len < kBmpHeaderSize + kBmpInfoSize) {
    46       return false;
    47     }
    48     width_ = GetInt();
    49     height_ = GetInt();
    50     GetShort();  // Planes.
    51     bpp_ = GetShort();
    52     comp = GetInt();
    53     GetInt();  // Size.
    54     GetInt();  // XPPM.
    55     GetInt();  // YPPM.
    56     cols = GetInt();
    57     GetInt();  // Important colours.
    58   } else {
    59     if (len < kBmpHeaderSize + kBmpOS2InfoSize) {
    60       return false;
    61     }
    62     colLen = 3;
    63     width_ = GetShort();
    64     height_ = GetShort();
    65     GetShort();  // Planes.
    66     bpp_ = GetShort();
    67   }
    68   if (height_ < 0) {
    69     height_ = -height_;
    70     inverted_ = false;
    71   }
    72   if (width_ <= 0 || width_ > kMaxDim || height_ <= 0 || height_ > kMaxDim) {
    73     return false;
    74   }
    75   if (width_ * height_ > max_pixels) {
    76     return false;
    77   }
    78   if (cols < 0 || cols > 256) {
    79     return false;
    80   }
    81   // Allocate then read in the colour map.
    82   if (cols == 0 && bpp_ <= 8) {
    83     cols = 1 << bpp_;
    84   }
    85   if (bpp_ <= 8 || cols > 0) {
    86     uint8* colBuf = new uint8[256 * 3];
    87     memset(colBuf, '\0', 256 * 3);
    88     colTab_.reset(colBuf);
    89   }
    90   if (cols > 0) {
    91     if (pos_ + (cols * colLen) > len_) {
    92       return false;
    93     }
    94     for (int i = 0; i < cols; ++i) {
    95       int base = i * 3;
    96       colTab_[base + 2] = GetByte();
    97       colTab_[base + 1] = GetByte();
    98       colTab_[base] = GetByte();
    99       if (colLen == 4) {
   100         GetByte();
   101       }
   102     }
   103   }
   104   // Read in the compression data if necessary.
   105   redBits_ = 0x7c00;
   106   greenBits_ = 0x03e0;
   107   blueBits_ = 0x001f;
   108   bool rle = false;
   109   if (comp == 1 || comp == 2) {
   110     rle = true;
   111   } else if (comp == 3) {
   112     if (pos_ + 12 > len_) {
   113       return false;
   114     }
   115     redBits_ = GetInt() & 0xffff;
   116     greenBits_ = GetInt() & 0xffff;
   117     blueBits_ = GetInt() & 0xffff;
   118   }
   119   redShiftRight_ = CalcShiftRight(redBits_);
   120   greenShiftRight_ = CalcShiftRight(greenBits_);
   121   blueShiftRight_ = CalcShiftRight(blueBits_);
   122   redShiftLeft_ = CalcShiftLeft(redBits_);
   123   greenShiftLeft_ = CalcShiftLeft(greenBits_);
   124   blueShiftLeft_ = CalcShiftLeft(blueBits_);
   125   rowPad_ = 0;
   126   pixelPad_ = 0;
   127   int rowLen;
   128   if (bpp_ == 32) {
   129     rowLen = width_ * 4;
   130     pixelPad_ = 1;
   131   } else if (bpp_ == 24) {
   132     rowLen = width_ * 3;
   133   } else if (bpp_ == 16) {
   134     rowLen = width_ * 2;
   135   } else if (bpp_ == 8) {
   136     rowLen = width_;
   137   } else if (bpp_ == 4) {
   138     rowLen = width_ / 2;
   139     if (width_ & 1) {
   140       rowLen++;
   141     }
   142   } else if (bpp_ == 1) {
   143     rowLen = width_ / 8;
   144     if (width_ & 7) {
   145       rowLen++;
   146     }
   147   } else {
   148     return false;
   149   }
   150   // Round the rowLen up to a multiple of 4.
   151   if (rowLen % 4 != 0) {
   152     rowPad_ = 4 - (rowLen % 4);
   153     rowLen += rowPad_;
   154   }
   156   if (offset > 0 && (size_t)offset > pos_ && (size_t)offset < len_) {
   157     pos_ = offset;
   158   }
   159   // Deliberately off-by-one; a load of BMPs seem to have their last byte
   160   // missing.
   161   if (!rle && (pos_ + (rowLen * height_) > len_ + 1)) {
   162     return false;
   163   }
   165   output_ = callback->SetSize(width_, height_);
   166   if (NULL == output_) {
   167     return true;  // meaning we succeeded, but they want us to stop now
   168   }
   170   if (rle && (bpp_ == 4 || bpp_ == 8)) {
   171     DoRLEDecode();
   172   } else {
   173     DoStandardDecode();
   174   }
   175   return true;
   176 }
   178 void BmpDecoderHelper::DoRLEDecode() {
   179   static const uint8 RLE_ESCAPE = 0;
   180   static const uint8 RLE_EOL = 0;
   181   static const uint8 RLE_EOF = 1;
   182   static const uint8 RLE_DELTA = 2;
   183   int x = 0;
   184   int y = height_ - 1;
   185   while (pos_ + 1 < len_) {
   186     uint8 cmd = GetByte();
   187     if (cmd != RLE_ESCAPE) {
   188       uint8 pixels = GetByte();
   189       int num = 0;
   190       uint8 col = pixels;
   191       while (cmd-- && x < width_) {
   192         if (bpp_ == 4) {
   193           if (num & 1) {
   194             col = pixels & 0xf;
   195           } else {
   196             col = pixels >> 4;
   197           }
   198         }
   199         PutPixel(x++, y, col);
   200         num++;
   201       }
   202     } else {
   203       cmd = GetByte();
   204       if (cmd == RLE_EOF) {
   205         return;
   206       } else if (cmd == RLE_EOL) {
   207         x = 0;
   208         y--;
   209         if (y < 0) {
   210           return;
   211         }
   212       } else if (cmd == RLE_DELTA) {
   213         if (pos_ + 1 < len_) {
   214           uint8 dx = GetByte();
   215           uint8 dy = GetByte();
   216           x += dx;
   217           if (x > width_) {
   218             x = width_;
   219           }
   220           y -= dy;
   221           if (y < 0) {
   222             return;
   223           }
   224         }
   225       } else {
   226         int num = 0;
   227         int bytesRead = 0;
   228         uint8 val = 0;
   229         while (cmd-- && pos_ < len_) {
   230           if (bpp_ == 8 || !(num & 1)) {
   231             val = GetByte();
   232             bytesRead++;
   233           }
   234           uint8 col = val;
   235           if (bpp_ == 4) {
   236             if (num & 1) {
   237               col = col & 0xf;
   238             } else {
   239               col >>= 4;
   240             }
   241           }
   242           if (x < width_) {
   243             PutPixel(x++, y, col);
   244           }
   245           num++;
   246         }
   247         // All pixel runs must be an even number of bytes - skip a byte if we
   248         // read an odd number.
   249         if ((bytesRead & 1) && pos_ < len_) {
   250           GetByte();
   251         }
   252       }
   253     }
   254   }
   255 }
   257 void BmpDecoderHelper::PutPixel(int x, int y, uint8 col) {
   258   CHECK(x >= 0 && x < width_);
   259   CHECK(y >= 0 && y < height_);
   260   if (!inverted_) {
   261     y = height_ - (y + 1);
   262   }
   264   int base = ((y * width_) + x) * 3;
   265   int colBase = col * 3;
   266   output_[base] = colTab_[colBase];
   267   output_[base + 1] = colTab_[colBase + 1];
   268   output_[base + 2] = colTab_[colBase + 2];
   269 }
   271 void BmpDecoderHelper::DoStandardDecode() {
   272   int row = 0;
   273   uint8 currVal = 0;
   274   for (int h = height_ - 1; h >= 0; h--, row++) {
   275     int realH = h;
   276     if (!inverted_) {
   277       realH = height_ - (h + 1);
   278     }
   279     uint8* line = output_ + (3 * width_ * realH);
   280     for (int w = 0; w < width_; w++) {
   281       if (bpp_ >= 24) {
   282         line[2] = GetByte();
   283         line[1] = GetByte();
   284         line[0] = GetByte();
   285       } else if (bpp_ == 16) {
   286         uint32 val = GetShort();
   287         line[0] = ((val & redBits_) >> redShiftRight_) << redShiftLeft_;
   288         line[1] = ((val & greenBits_) >> greenShiftRight_) << greenShiftLeft_;
   289         line[2] = ((val & blueBits_) >> blueShiftRight_) << blueShiftLeft_;
   290       } else if (bpp_ <= 8) {
   291         uint8 col;
   292         if (bpp_ == 8) {
   293           col = GetByte();
   294         } else if (bpp_ == 4) {
   295           if ((w % 2) == 0) {
   296             currVal = GetByte();
   297             col = currVal >> 4;
   298           } else {
   299             col = currVal & 0xf;
   300           }
   301         } else {
   302           if ((w % 8) == 0) {
   303             currVal = GetByte();
   304           }
   305           int bit = w & 7;
   306           col = ((currVal >> (7 - bit)) & 1);
   307         }
   308         int base = col * 3;
   309         line[0] = colTab_[base];
   310         line[1] = colTab_[base + 1];
   311         line[2] = colTab_[base + 2];
   312       }
   313       line += 3;
   314       for (int i = 0; i < pixelPad_; ++i) {
   315         GetByte();
   316       }
   317     }
   318     for (int i = 0; i < rowPad_; ++i) {
   319       GetByte();
   320     }
   321   }
   322 }
   324 int BmpDecoderHelper::GetInt() {
   325   uint8 b1 = GetByte();
   326   uint8 b2 = GetByte();
   327   uint8 b3 = GetByte();
   328   uint8 b4 = GetByte();
   329   return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
   330 }
   332 int BmpDecoderHelper::GetShort() {
   333   uint8 b1 = GetByte();
   334   uint8 b2 = GetByte();
   335   return b1 | (b2 << 8);
   336 }
   338 uint8 BmpDecoderHelper::GetByte() {
   339   CHECK(pos_ <= len_);
   340   // We deliberately allow this off-by-one access to cater for BMPs with their
   341   // last byte missing.
   342   if (pos_ == len_) {
   343     return 0;
   344   }
   345   return data_[pos_++];
   346 }
   348 int BmpDecoderHelper::CalcShiftRight(uint32 mask) {
   349   int ret = 0;
   350   while (mask != 0 && !(mask & 1)) {
   351     mask >>= 1;
   352     ret++;
   353   }
   354   return ret;
   355 }
   357 int BmpDecoderHelper::CalcShiftLeft(uint32 mask) {
   358   int ret = 0;
   359   while (mask != 0 && !(mask & 1)) {
   360     mask >>= 1;
   361   }
   362   while (mask != 0 && !(mask & 0x80)) {
   363     mask <<= 1;
   364     ret++;
   365   }
   366   return ret;
   367 }
   369 }  // namespace image_codec

mercurial