LCOV - app.info - gfx/src/nsColor.cpp

LCOV - code coverage report
| Current view: | directory - gfx/src - nsColor.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 132 | 17 | 12.9 %
| Date: | 2012-07-07 | Functions: | 9 | 2 | 22.2 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "mozilla/Util.h"
          39                 :
          40                 : #include "plstr.h"
          41                 : #include "nsColor.h"
          42                 : #include "nsColorNames.h"
          43                 : #include "nsString.h"
          44                 : #include "nscore.h"
          45                 : #include "nsCoord.h"
          46                 : #include "nsCOMPtr.h"
          47                 : #include "nsIServiceManager.h"
          48                 : #include <math.h>
          49                 : #include "prprf.h"
          50                 : #include "nsStaticNameTable.h"
          51                 :
          52                 : using namespace mozilla;
          53                 :
          54                 : // define an array of all color names
          55                 : #define GFX_COLOR(_name, _value) #_name,
          56                 : static const char* const kColorNames[] = {
          57                 : #include "nsColorNameList.h"
          58                 : };
          59                 : #undef GFX_COLOR
          60                 :
          61                 : // define an array of all color name values
          62                 : #define GFX_COLOR(_name, _value) _value,
          63                 : static const nscolor kColors[] = {
          64                 : #include "nsColorNameList.h"
          65                 : };
          66                 : #undef GFX_COLOR
          67                 :
          68                 : #define eColorName_COUNT (ArrayLength(kColorNames))
          69                 : #define eColorName_UNKNOWN (-1)
          70                 :
          71                 : static nsStaticCaseInsensitiveNameTable* gColorTable = nsnull;
          72                 :
          73            1404 : void nsColorNames::AddRefTable(void)
          74                 : {
          75            1404 :   NS_ASSERTION(!gColorTable, "pre existing array!");
          76            1404 :   if (!gColorTable) {
          77            1404 :     gColorTable = new nsStaticCaseInsensitiveNameTable();
          78            1404 :     if (gColorTable) {
          79                 : #ifdef DEBUG
          80                 :     {
          81                 :       // let's verify the table...
          82          209196 :       for (PRUint32 index = 0; index < eColorName_COUNT; ++index) {
          83          415584 :         nsCAutoString temp1(kColorNames[index]);
          84          415584 :         nsCAutoString temp2(kColorNames[index]);
          85          207792 :         ToLowerCase(temp1);
          86          207792 :         NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
          87                 :       }
          88                 :     }
          89                 : #endif
          90            1404 :       gColorTable->Init(kColorNames, eColorName_COUNT);
          91                 :     }
          92                 :   }
          93            1404 : }
          94                 :
          95            1403 : void nsColorNames::ReleaseTable(void)
          96                 : {
          97            1403 :   if (gColorTable) {
          98            1403 :     delete gColorTable;
          99            1403 :     gColorTable = nsnull;
         100                 :   }
         101            1403 : }
         102                 :
         103               0 : static int ComponentValue(const PRUnichar* aColorSpec, int aLen, int color, int dpc)
         104                 : {
         105               0 :   int component = 0;
         106               0 :   int index = (color * dpc);
         107               0 :   if (2 < dpc) {
         108               0 :     dpc = 2;
         109                 :   }
         110               0 :   while (--dpc >= 0) {
         111               0 :     PRUnichar ch = ((index < aLen) ? aColorSpec[index++] : '0');
         112               0 :     if (('0' <= ch) && (ch <= '9')) {
         113               0 :       component = (component * 16) + (ch - '0');
         114               0 :     } else if ((('a' <= ch) && (ch <= 'f')) ||
         115                 :                (('A' <= ch) && (ch <= 'F'))) {
         116                 :       // "ch&7" handles lower and uppercase hex alphabetics
         117               0 :       component = (component * 16) + (ch & 7) + 9;
         118                 :     }
         119                 :     else {  // not a hex digit, treat it like 0
         120               0 :       component = (component * 16);
         121                 :     }
         122                 :   }
         123               0 :   return component;
         124                 : }
         125                 :
         126               0 : NS_GFX_(bool) NS_HexToRGB(const nsString& aColorSpec,
         127                 :                                        nscolor* aResult)
         128                 : {
         129               0 :   const PRUnichar* buffer = aColorSpec.get();
         130                 :
         131               0 :   int nameLen = aColorSpec.Length();
         132               0 :   if ((nameLen == 3) || (nameLen == 6)) {
         133                 :     // Make sure the digits are legal
         134               0 :     for (int i = 0; i < nameLen; i++) {
         135               0 :       PRUnichar ch = buffer[i];
         136               0 :       if (((ch >= '0') && (ch <= '9')) ||
         137                 :           ((ch >= 'a') && (ch <= 'f')) ||
         138                 :           ((ch >= 'A') && (ch <= 'F'))) {
         139                 :         // Legal character
         140               0 :         continue;
         141                 :       }
         142                 :       // Whoops. Illegal character.
         143               0 :       return false;
         144                 :     }
         145                 :
         146                 :     // Convert the ascii to binary
         147               0 :     int dpc = ((3 == nameLen) ? 1 : 2);
         148                 :     // Translate components from hex to binary
         149               0 :     int r = ComponentValue(buffer, nameLen, 0, dpc);
         150               0 :     int g = ComponentValue(buffer, nameLen, 1, dpc);
         151               0 :     int b = ComponentValue(buffer, nameLen, 2, dpc);
         152               0 :     if (dpc == 1) {
         153                 :       // Scale single digit component to an 8 bit value. Replicate the
         154                 :       // single digit to compute the new value.
         155               0 :       r = (r << 4) | r;
         156               0 :       g = (g << 4) | g;
         157               0 :       b = (b << 4) | b;
         158                 :     }
         159               0 :     NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
         160               0 :     NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
         161               0 :     NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
         162               0 :     *aResult = NS_RGB(r, g, b);
         163               0 :     return true;
         164                 :   }
         165                 :
         166                 :   // Improperly formatted color value
         167               0 :   return false;
         168                 : }
         169                 :
         170                 : // This implements part of the algorithm for legacy behavior described in
         171                 : // http://www.whatwg.org/specs/web-apps/current-work/complete/common-microsyntaxes.html#rules-for-parsing-a-legacy-color-value
         172               0 : NS_GFX_(bool) NS_LooseHexToRGB(const nsString& aColorSpec, nscolor* aResult)
         173                 : {
         174               0 :   if (aColorSpec.EqualsLiteral("transparent")) {
         175               0 :     return false;
         176                 :   }
         177                 :
         178               0 :   int nameLen = aColorSpec.Length();
         179               0 :   const PRUnichar* colorSpec = aColorSpec.get();
         180               0 :   if (nameLen > 128) {
         181               0 :     nameLen = 128;
         182                 :   }
         183                 :
         184               0 :   if ('#' == colorSpec[0]) {
         185               0 :     ++colorSpec;
         186               0 :     --nameLen;
         187                 :   }
         188                 :
         189                 :   // digits per component
         190               0 :   int dpc = (nameLen + 2) / 3;
         191               0 :   int newdpc = dpc;
         192                 :
         193                 :   // Use only the rightmost 8 characters of each component.
         194               0 :   if (newdpc > 8) {
         195               0 :     nameLen -= newdpc - 8;
         196               0 :     colorSpec += newdpc - 8;
         197               0 :     newdpc = 8;
         198                 :   }
         199                 :
         200                 :   // And then keep trimming characters at the left until we'd trim one
         201                 :   // that would leave a nonzero value, but not past 2 characters per
         202                 :   // component.
         203               0 :   while (newdpc > 2) {
         204               0 :     bool haveNonzero = false;
         205               0 :     for (int c = 0; c < 3; ++c) {
         206               0 :       NS_ABORT_IF_FALSE(c * dpc < nameLen,
         207                 :                         "should not pass end of string while newdpc > 2");
         208               0 :       PRUnichar ch = colorSpec[c * dpc];
         209               0 :       if (('1' <= ch && ch <= '9') ||
         210                 :           ('A' <= ch && ch <= 'F') ||
         211                 :           ('a' <= ch && ch <= 'f')) {
         212               0 :         haveNonzero = true;
         213               0 :         break;
         214                 :       }
         215                 :     }
         216               0 :     if (haveNonzero) {
         217               0 :       break;
         218                 :     }
         219               0 :     --newdpc;
         220               0 :     --nameLen;
         221               0 :     ++colorSpec;
         222                 :   }
         223                 :
         224                 :   // Translate components from hex to binary
         225               0 :   int r = ComponentValue(colorSpec, nameLen, 0, dpc);
         226               0 :   int g = ComponentValue(colorSpec, nameLen, 1, dpc);
         227               0 :   int b = ComponentValue(colorSpec, nameLen, 2, dpc);
         228               0 :   NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
         229               0 :   NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
         230               0 :   NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
         231                 :
         232               0 :   *aResult = NS_RGB(r, g, b);
         233               0 :   return true;
         234                 : }
         235                 :
         236               0 : NS_GFX_(bool) NS_ColorNameToRGB(const nsAString& aColorName, nscolor* aResult)
         237                 : {
         238               0 :   if (!gColorTable) return false;
         239                 :
         240               0 :   PRInt32 id = gColorTable->Lookup(aColorName);
         241               0 :   if (eColorName_UNKNOWN < id) {
         242               0 :     NS_ASSERTION(PRUint32(id) < eColorName_COUNT,
         243                 :                  "gColorTable->Lookup messed up");
         244               0 :     if (aResult) {
         245               0 :       *aResult = kColors[id];
         246                 :     }
         247               0 :     return true;
         248                 :   }
         249               0 :   return false;
         250                 : }
         251                 :
         252                 : // Macro to blend two colors
         253                 : //
         254                 : // equivalent to target = (bg*(255-fgalpha) + fg*fgalpha)/255
         255                 : #define MOZ_BLEND(target, bg, fg, fgalpha)       \
         256                 :   FAST_DIVIDE_BY_255(target, (bg)*(255-fgalpha) + (fg)*(fgalpha))
         257                 :
         258                 : NS_GFX_(nscolor)
         259               0 : NS_ComposeColors(nscolor aBG, nscolor aFG)
         260                 : {
         261                 :   // This function uses colors that are non premultiplied alpha.
         262                 :   PRIntn r, g, b, a;
         263                 :
         264               0 :   PRIntn bgAlpha = NS_GET_A(aBG);
         265               0 :   PRIntn fgAlpha = NS_GET_A(aFG);
         266                 :
         267                 :   // Compute the final alpha of the blended color
         268                 :   // a = fgAlpha + bgAlpha*(255 - fgAlpha)/255;
         269               0 :   FAST_DIVIDE_BY_255(a, bgAlpha*(255-fgAlpha));
         270               0 :   a = fgAlpha + a;
         271                 :   PRIntn blendAlpha;
         272               0 :   if (a == 0) {
         273                 :     // In this case the blended color is totally trasparent,
         274                 :     // we preserve the color information of the foreground color.
         275               0 :     blendAlpha = 255;
         276                 :   } else {
         277               0 :     blendAlpha = (fgAlpha*255)/a;
         278                 :   }
         279               0 :   MOZ_BLEND(r, NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
         280               0 :   MOZ_BLEND(g, NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
         281               0 :   MOZ_BLEND(b, NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
         282                 :
         283               0 :   return NS_RGBA(r, g, b, a);
         284                 : }
         285                 :
         286                 : // Functions to convert from HSL color space to RGB color space.
         287                 : // This is the algorithm described in the CSS3 specification
         288                 :
         289                 : // helper
         290                 : static float
         291               0 : HSL_HueToRGB(float m1, float m2, float h)
         292                 : {
         293               0 :   if (h < 0.0f)
         294               0 :     h += 1.0f;
         295               0 :   if (h > 1.0f)
         296               0 :     h -= 1.0f;
         297               0 :   if (h < (float)(1.0/6.0))
         298               0 :     return m1 + (m2 - m1)*h*6.0f;
         299               0 :   if (h < (float)(1.0/2.0))
         300               0 :     return m2;
         301               0 :   if (h < (float)(2.0/3.0))
         302               0 :     return m1 + (m2 - m1)*((float)(2.0/3.0) - h)*6.0f;
         303               0 :   return m1;
         304                 : }
         305                 :
         306                 : // The float parameters are all expected to be in the range 0-1
         307                 : NS_GFX_(nscolor)
         308               0 : NS_HSL2RGB(float h, float s, float l)
         309                 : {
         310                 :   PRUint8 r, g, b;
         311                 :   float m1, m2;
         312               0 :   if (l <= 0.5f) {
         313               0 :     m2 = l*(s+1);
         314                 :   } else {
         315               0 :     m2 = l + s - l*s;
         316                 :   }
         317               0 :   m1 = l*2 - m2;
         318               0 :   r = PRUint8(255 * HSL_HueToRGB(m1, m2, h + 1.0f/3.0f));
         319               0 :   g = PRUint8(255 * HSL_HueToRGB(m1, m2, h));
         320               0 :   b = PRUint8(255 * HSL_HueToRGB(m1, m2, h - 1.0f/3.0f));
         321               0 :   return NS_RGB(r, g, b);
         322                 : }

Generated by: LCOV version 1.7