gfx/src/nsColor.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/ArrayUtils.h"         // for ArrayLength
     7 #include "mozilla/mozalloc.h"           // for operator delete, etc
     9 #include "nsColor.h"
    10 #include <sys/types.h>                  // for int32_t
    11 #include "nsColorNames.h"               // for nsColorNames
    12 #include "nsDebug.h"                    // for NS_ASSERTION, etc
    13 #include "nsStaticNameTable.h"
    14 #include "nsString.h"                   // for nsAutoCString, nsString, etc
    15 #include "nscore.h"                     // for nsAString, etc
    17 using namespace mozilla;
    19 // define an array of all color names
    20 #define GFX_COLOR(_name, _value) #_name,
    21 static const char* const kColorNames[] = {
    22 #include "nsColorNameList.h"
    23 };
    24 #undef GFX_COLOR
    26 // define an array of all color name values
    27 #define GFX_COLOR(_name, _value) _value,
    28 static const nscolor kColors[] = {
    29 #include "nsColorNameList.h"
    30 };
    31 #undef GFX_COLOR
    33 #define eColorName_COUNT (ArrayLength(kColorNames))
    34 #define eColorName_UNKNOWN (-1)
    36 static nsStaticCaseInsensitiveNameTable* gColorTable = nullptr;
    38 void nsColorNames::AddRefTable(void) 
    39 {
    40   NS_ASSERTION(!gColorTable, "pre existing array!");
    41   if (!gColorTable) {
    42     gColorTable = new nsStaticCaseInsensitiveNameTable();
    43     if (gColorTable) {
    44 #ifdef DEBUG
    45     {
    46       // let's verify the table...
    47       for (uint32_t index = 0; index < eColorName_COUNT; ++index) {
    48         nsAutoCString temp1(kColorNames[index]);
    49         nsAutoCString temp2(kColorNames[index]);
    50         ToLowerCase(temp1);
    51         NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
    52       }
    53     }
    54 #endif      
    55       gColorTable->Init(kColorNames, eColorName_COUNT); 
    56     }
    57   }
    58 }
    60 void nsColorNames::ReleaseTable(void)
    61 {
    62   if (gColorTable) {
    63     delete gColorTable;
    64     gColorTable = nullptr;
    65   }
    66 }
    68 static int ComponentValue(const char16_t* aColorSpec, int aLen, int color, int dpc)
    69 {
    70   int component = 0;
    71   int index = (color * dpc);
    72   if (2 < dpc) {
    73     dpc = 2;
    74   }
    75   while (--dpc >= 0) {
    76     char16_t ch = ((index < aLen) ? aColorSpec[index++] : '0');
    77     if (('0' <= ch) && (ch <= '9')) {
    78       component = (component * 16) + (ch - '0');
    79     } else if ((('a' <= ch) && (ch <= 'f')) || 
    80                (('A' <= ch) && (ch <= 'F'))) {
    81       // "ch&7" handles lower and uppercase hex alphabetics
    82       component = (component * 16) + (ch & 7) + 9;
    83     }
    84     else {  // not a hex digit, treat it like 0
    85       component = (component * 16);
    86     }
    87   }
    88   return component;
    89 }
    91 NS_GFX_(bool) NS_HexToRGB(const nsAString& aColorSpec,
    92                                        nscolor* aResult)
    93 {
    94   const char16_t* buffer = aColorSpec.BeginReading();
    96   int nameLen = aColorSpec.Length();
    97   if ((nameLen == 3) || (nameLen == 6)) {
    98     // Make sure the digits are legal
    99     for (int i = 0; i < nameLen; i++) {
   100       char16_t ch = buffer[i];
   101       if (((ch >= '0') && (ch <= '9')) ||
   102           ((ch >= 'a') && (ch <= 'f')) ||
   103           ((ch >= 'A') && (ch <= 'F'))) {
   104         // Legal character
   105         continue;
   106       }
   107       // Whoops. Illegal character.
   108       return false;
   109     }
   111     // Convert the ascii to binary
   112     int dpc = ((3 == nameLen) ? 1 : 2);
   113     // Translate components from hex to binary
   114     int r = ComponentValue(buffer, nameLen, 0, dpc);
   115     int g = ComponentValue(buffer, nameLen, 1, dpc);
   116     int b = ComponentValue(buffer, nameLen, 2, dpc);
   117     if (dpc == 1) {
   118       // Scale single digit component to an 8 bit value. Replicate the
   119       // single digit to compute the new value.
   120       r = (r << 4) | r;
   121       g = (g << 4) | g;
   122       b = (b << 4) | b;
   123     }
   124     NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
   125     NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
   126     NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
   127     *aResult = NS_RGB(r, g, b);
   128     return true;
   129   }
   131   // Improperly formatted color value
   132   return false;
   133 }
   135 // This implements part of the algorithm for legacy behavior described in
   136 // http://www.whatwg.org/specs/web-apps/current-work/complete/common-microsyntaxes.html#rules-for-parsing-a-legacy-color-value
   137 NS_GFX_(bool) NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult)
   138 {
   139   if (aColorSpec.EqualsLiteral("transparent")) {
   140     return false;
   141   }
   143   int nameLen = aColorSpec.Length();
   144   const char16_t* colorSpec = aColorSpec.get();
   145   if (nameLen > 128) {
   146     nameLen = 128;
   147   }
   149   if ('#' == colorSpec[0]) {
   150     ++colorSpec;
   151     --nameLen;
   152   }
   154   // digits per component
   155   int dpc = (nameLen + 2) / 3;
   156   int newdpc = dpc;
   158   // Use only the rightmost 8 characters of each component.
   159   if (newdpc > 8) {
   160     nameLen -= newdpc - 8;
   161     colorSpec += newdpc - 8;
   162     newdpc = 8;
   163   }
   165   // And then keep trimming characters at the left until we'd trim one
   166   // that would leave a nonzero value, but not past 2 characters per
   167   // component.
   168   while (newdpc > 2) {
   169     bool haveNonzero = false;
   170     for (int c = 0; c < 3; ++c) {
   171       NS_ABORT_IF_FALSE(c * dpc < nameLen,
   172                         "should not pass end of string while newdpc > 2");
   173       char16_t ch = colorSpec[c * dpc];
   174       if (('1' <= ch && ch <= '9') ||
   175           ('A' <= ch && ch <= 'F') ||
   176           ('a' <= ch && ch <= 'f')) {
   177         haveNonzero = true;
   178         break;
   179       }
   180     }
   181     if (haveNonzero) {
   182       break;
   183     }
   184     --newdpc;
   185     --nameLen;
   186     ++colorSpec;
   187   }
   189   // Translate components from hex to binary
   190   int r = ComponentValue(colorSpec, nameLen, 0, dpc);
   191   int g = ComponentValue(colorSpec, nameLen, 1, dpc);
   192   int b = ComponentValue(colorSpec, nameLen, 2, dpc);
   193   NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
   194   NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
   195   NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
   197   *aResult = NS_RGB(r, g, b);
   198   return true;
   199 }
   201 NS_GFX_(bool) NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
   202 {
   203   if (!gColorTable) return false;
   205   int32_t id = gColorTable->Lookup(aColorName);
   206   if (eColorName_UNKNOWN < id) {
   207     NS_ASSERTION(uint32_t(id) < eColorName_COUNT,
   208                  "gColorTable->Lookup messed up");
   209     if (aResult) {
   210       *aResult = kColors[id];
   211     }
   212     return true;
   213   }
   214   return false;
   215 }
   217 // Returns kColorNames, an array of all possible color names, and sets
   218 // *aSizeArray to the size of that array. Do NOT call free() on this array.
   219 NS_GFX_(const char * const *) NS_AllColorNames(size_t *aSizeArray)
   220 {
   221   *aSizeArray = ArrayLength(kColorNames);
   222   return kColorNames;
   223 }
   225 // Macro to blend two colors
   226 //
   227 // equivalent to target = (bg*(255-fgalpha) + fg*fgalpha)/255
   228 #define MOZ_BLEND(target, bg, fg, fgalpha)       \
   229   FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha))
   231 NS_GFX_(nscolor)
   232 NS_ComposeColors(nscolor aBG, nscolor aFG)
   233 {
   234   // This function uses colors that are non premultiplied alpha.
   235   int r, g, b, a;
   237   int bgAlpha = NS_GET_A(aBG);
   238   int fgAlpha = NS_GET_A(aFG);
   240   // Compute the final alpha of the blended color
   241   // a = fgAlpha + bgAlpha*(255 - fgAlpha)/255;
   242   FAST_DIVIDE_BY_255(a, bgAlpha*(255-fgAlpha));
   243   a = fgAlpha + a;
   244   int blendAlpha;
   245   if (a == 0) {
   246     // In this case the blended color is totally trasparent,
   247     // we preserve the color information of the foreground color.
   248     blendAlpha = 255;
   249   } else {
   250     blendAlpha = (fgAlpha*255)/a;
   251   }
   252   MOZ_BLEND(r, NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
   253   MOZ_BLEND(g, NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
   254   MOZ_BLEND(b, NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
   256   return NS_RGBA(r, g, b, a);
   257 }
   259 // Functions to convert from HSL color space to RGB color space.
   260 // This is the algorithm described in the CSS3 specification
   262 // helper
   263 static float
   264 HSL_HueToRGB(float m1, float m2, float h)
   265 {
   266   if (h < 0.0f)
   267     h += 1.0f;
   268   if (h > 1.0f)
   269     h -= 1.0f;
   270   if (h < (float)(1.0/6.0))
   271     return m1 + (m2 - m1)*h*6.0f;
   272   if (h < (float)(1.0/2.0))
   273     return m2;
   274   if (h < (float)(2.0/3.0))
   275     return m1 + (m2 - m1)*((float)(2.0/3.0) - h)*6.0f;
   276   return m1;      
   277 }
   279 // The float parameters are all expected to be in the range 0-1
   280 NS_GFX_(nscolor)
   281 NS_HSL2RGB(float h, float s, float l)
   282 {
   283   uint8_t r, g, b;
   284   float m1, m2;
   285   if (l <= 0.5f) {
   286     m2 = l*(s+1);
   287   } else {
   288     m2 = l + s - l*s;
   289   }
   290   m1 = l*2 - m2;
   291   r = uint8_t(255 * HSL_HueToRGB(m1, m2, h + 1.0f/3.0f));
   292   g = uint8_t(255 * HSL_HueToRGB(m1, m2, h));
   293   b = uint8_t(255 * HSL_HueToRGB(m1, m2, h - 1.0f/3.0f));
   294   return NS_RGB(r, g, b);  
   295 }
   297 NS_GFX_(const char*)
   298 NS_RGBToColorName(nscolor aColor)
   299 {
   300   for (size_t idx = 0; idx < ArrayLength(kColors); ++idx) {
   301     if (kColors[idx] == aColor) {
   302       return kColorNames[idx];
   303     }
   304   }
   306   return nullptr;
   307 }

mercurial