【问题标题】:How is the bgcolor property being calculated? [duplicate]bgcolor 属性是如何计算的? [复制]
【发布时间】:2012-11-03 02:11:00
【问题描述】:

可能重复:
Why does HTML think “chucknorris” is a color?

bgcolor 属性是如何计算的?

当我使用下面的 html 代码时...

<body bgcolor="#Deine Mutter hat eine Farbe und die ist grün."></body>

...我得到的是以下颜色。

顺便说一句:当我尝试在 CSS 中使用它时,它不会工作并且会应用标准颜色:

body{
    color: #IchwillGOLD;
}

为什么?

【问题讨论】:

  • 很明显这句话用英语翻译成绿色!
  • 这是一个有趣的启示(或巧合)...&lt;body bgcolor="#der hintergrund ist gold"&gt; 产生金色(确切地说是#DEE000)。查看文本字符串 (der hintergrund ist gold),如果删除所有非十六进制字符,则会得到:dee。用零填充剩余的字符,得到十六进制颜色 (#DEE000)
  • 问题是,我看不到将 OP 的原始文本字符串转换为适当的绿色十六进制的方法。
  • @Hannes 很遗憾你是对的……巧合而已……谜团还在继续!
  • 必须有一种算法可以计算出合适的 hex-rgb 值

标签: html colors


【解决方案1】:

我的第一次尝试是对错误的一点尝试,虽然我发现了系统的一些有趣的特性,但这还不足以形成一个答案。接下来,我将注意力转向了标准。我认为这是标准的原因是我在三个不同的浏览器上测试了它,它们实际上都做了同样的事情。使用标准我发现会发生什么:

  1. 所有非十六进制字符都被零替换(因此只剩下零、1-9 和 a-e)
  2. 字符串末尾补​​零为三的倍数
  3. 然后将字符串分成三个相等的部分,每个部分代表一种颜色
  4. 如果结果字符串超过 8 个字符,则取每个字符串的最后 8 个字符
  5. 只要每个字符串都以零开头,就会从每个字符串中删除第一个字符(此特定字符串不会发生,因为它以 De 开头
  6. 前两个字符取自这些字符串中的每一个,并转换为一个数字,用作颜色的组成部分之一

这样你会看到你得到00FA00 for Deine Mutter hat eine Farbe und die ist grün.

html5 标准更准确地描述了这个过程,实际上在这里描述了更多的案例:http://www.w3.org/TR/html5/common-microsyntaxes.html#colors 在“解析旧颜色值的规则”下

【讨论】:

  • 反复试验似乎确实突出了对我来说分成三部分的意义......
  • @Ioxxy:我通过反复试验得到了 1,当我决定查看起来。
  • 嗯,除此之外,第一步是匹配关键字 red、blue.. 等
  • @sharethis 因为这是为了让浏览器不遵守标准的时代的现有网站正确呈现。 CSS 是在标准时代发明的,因此它从未遭受过这样的滥用。
  • 此外,这些表现属性最终会被翻译成其相应的 CSS 规则,作者级别的特异性为零,如 w3.org/TR/CSS21/cascade.html#preshint 这就是为什么 WebKit 将生成的颜色值传递给 @ 987654326@结构。
【解决方案2】:

正如我在评论中所说,HTMLParser 将其添加为 CSS 属性, 正如 Jasper 已经回答的那样,它是由规范决定的。

实施

Webkit 解析 HTMLParser.cpp 中的 html,如果 Parser 是 inBody,它会将 bgColor 属性添加为 HTMLBodyElement.cpp 中的 CssColor

// Color parsing that matches HTML's "rules for parsing a legacy color value"
void HTMLElement::addHTMLColorToStyle(StylePropertySet* style, CSSPropertyID propertyID, const String& attributeValue)
{
    // An empty string doesn't apply a color. (One containing only whitespace does, which is why this check occurs before stripping.)
    if (attributeValue.isEmpty())
        return;

    String colorString = attributeValue.stripWhiteSpace();

    // "transparent" doesn't apply a color either.
    if (equalIgnoringCase(colorString, "transparent"))
        return;

    // If the string is a named CSS color or a 3/6-digit hex color, use that.
    Color parsedColor(colorString);
    if (!parsedColor.isValid())
        parsedColor.setRGB(parseColorStringWithCrazyLegacyRules(colorString));

    style->setProperty(propertyID, cssValuePool().createColorValue(parsedColor.rgb()));
}

你很有可能以这种方法结束:

static RGBA32 parseColorStringWithCrazyLegacyRules(const String& colorString)

我认为是支持这样的旧颜色:body bgcolor=ff0000 (Mozilla Gecko Test)。

  1. 跳过前导#
  2. 获取前 128 个字符,将非十六进制字符替换为 0。 第1120章
  3. 非 BMP 字符被替换为“00”,因为它们在字符串中显示为两个“字符”。
  4. 如果没有数字返回颜色黑色
  5. 将数字分成三个部分,然后搜索每个部分的最后 8 位。

Webkit/HTMLElement.cpp:parseColorStringWithCrazyLegacyRules的代码:

static RGBA32 parseColorStringWithCrazyLegacyRules(const String& colorString)
{
    // Per spec, only look at the first 128 digits of the string.
    const size_t maxColorLength = 128;
    // We'll pad the buffer with two extra 0s later, so reserve two more than the max.
    Vector<char, maxColorLength+2> digitBuffer;
    size_t i = 0;
    // Skip a leading #.
    if (colorString[0] == '#')
        i = 1;

    // Grab the first 128 characters, replacing non-hex characters with 0.
    // Non-BMP characters are replaced with "00" due to them appearing as two "characters" in the String.
    for (; i < colorString.length() && digitBuffer.size() < maxColorLength; i++) {
        if (!isASCIIHexDigit(colorString[i]))
            digitBuffer.append('0');
        else
            digitBuffer.append(colorString[i]);
    }

    if (!digitBuffer.size())
        return Color::black;

    // Pad the buffer out to at least the next multiple of three in size.
    digitBuffer.append('0');
    digitBuffer.append('0');

    if (digitBuffer.size() < 6)
        return makeRGB(toASCIIHexValue(digitBuffer[0]), toASCIIHexValue(digitBuffer[1]), toASCIIHexValue(digitBuffer[2]));

    // Split the digits into three components, then search the last 8 digits of each component.
    ASSERT(digitBuffer.size() >= 6);
    size_t componentLength = digitBuffer.size() / 3;
    size_t componentSearchWindowLength = min<size_t>(componentLength, 8);
    size_t redIndex = componentLength - componentSearchWindowLength;
    size_t greenIndex = componentLength * 2 - componentSearchWindowLength;
    size_t blueIndex = componentLength * 3 - componentSearchWindowLength;
    // Skip digits until one of them is non-zero, 
    // or we've only got two digits left in the component.
    while (digitBuffer[redIndex] == '0' && digitBuffer[greenIndex] == '0' 
        && digitBuffer[blueIndex] == '0' && (componentLength - redIndex) > 2) {
        redIndex++;
        greenIndex++;
        blueIndex++;
    }
    ASSERT(redIndex + 1 < componentLength);
    ASSERT(greenIndex >= componentLength);
    ASSERT(greenIndex + 1 < componentLength * 2);
    ASSERT(blueIndex >= componentLength * 2);
    ASSERT(blueIndex + 1 < digitBuffer.size());

    int redValue = toASCIIHexValue(digitBuffer[redIndex], digitBuffer[redIndex + 1]);
    int greenValue = toASCIIHexValue(digitBuffer[greenIndex], digitBuffer[greenIndex + 1]);
    int blueValue = toASCIIHexValue(digitBuffer[blueIndex], digitBuffer[blueIndex + 1]);
    return makeRGB(redValue, greenValue, blueValue);
}

【讨论】:

  • 仅供澄清,@Soluter 应该接受您的回答。
  • 我不是故意为了积分什么的。只是说它没有任何不同。但这实际上是一个(可能)有用的澄清,所以我删除了评论。
猜你喜欢
  • 1970-01-01
  • 2010-11-23
  • 2013-05-14
  • 2016-08-05
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-31
相关资源
最近更新 更多