String CSSPrimitiveValue::cssText() const { // FIXME: return the original value instead of a generated one (e.g. color // name if it was specified) - check what spec says about this String text; switch (m_type) { case CSS_UNKNOWN: // FIXME break; case CSS_NUMBER: case CSS_PARSER_INTEGER: text = String::number(m_value.num); break; case CSS_PERCENTAGE: text = String::format("%.6lg%%", m_value.num); break; case CSS_EMS: text = String::format("%.6lgem", m_value.num); break; case CSS_EXS: text = String::format("%.6lgex", m_value.num); break; case CSS_PX: text = String::format("%.6lgpx", m_value.num); break; case CSS_CM: text = String::format("%.6lgcm", m_value.num); break; case CSS_MM: text = String::format("%.6lgmm", m_value.num); break; case CSS_IN: text = String::format("%.6lgin", m_value.num); break; case CSS_PT: text = String::format("%.6lgpt", m_value.num); break; case CSS_PC: text = String::format("%.6lgpc", m_value.num); break; case CSS_DEG: text = String::format("%.6lgdeg", m_value.num); break; case CSS_RAD: text = String::format("%.6lgrad", m_value.num); break; case CSS_GRAD: text = String::format("%.6lggrad", m_value.num); break; case CSS_MS: text = String::format("%.6lgms", m_value.num); break; case CSS_S: text = String::format("%.6lgs", m_value.num); break; case CSS_HZ: text = String::format("%.6lghz", m_value.num); break; case CSS_KHZ: text = String::format("%.6lgkhz", m_value.num); break; case CSS_DIMENSION: // FIXME break; case CSS_STRING: text = quoteStringIfNeeded(m_value.string); break; case CSS_URI: text = "url(" + quoteURLIfNeeded(m_value.string) + ")"; break; case CSS_IDENT: text = valueOrPropertyName(m_value.ident); break; case CSS_ATTR: // FIXME break; case CSS_COUNTER: text = "counter("; text += String::number(m_value.num); text += ")"; // FIXME: Add list-style and separator break; case CSS_RECT: { Rect* rectVal = getRectValue(); text = "rect("; text += rectVal->top()->cssText() + " "; text += rectVal->right()->cssText() + " "; text += rectVal->bottom()->cssText() + " "; text += rectVal->left()->cssText() + ")"; break; } case CSS_RGBCOLOR: case CSS_PARSER_HEXCOLOR: { RGBA32 rgbColor = m_value.rgbcolor; if (m_type == CSS_PARSER_HEXCOLOR) Color::parseHexColor(m_value.string, rgbColor); Color color(rgbColor); text = (color.alpha() < 0xFF) ? "rgba(" : "rgb("; text += String::number(color.red()) + ", "; text += String::number(color.green()) + ", "; text += String::number(color.blue()); if (color.alpha() < 0xFF) text += ", " + String::number(static_cast<float>(color.alpha()) / 0xFF); text += ")"; break; } case CSS_PAIR: text = m_value.pair->first()->cssText(); text += " "; text += m_value.pair->second()->cssText(); break; #if ENABLE(DASHBOARD_SUPPORT) case CSS_DASHBOARD_REGION: for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { if (!text.isEmpty()) text.append(' '); text += "dashboard-region("; text += region->m_label; if (region->m_isCircle) text += " circle"; else if (region->m_isRectangle) text += " rectangle"; else break; if (region->top()->m_type == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) { ASSERT(region->right()->m_type == CSS_IDENT); ASSERT(region->bottom()->m_type == CSS_IDENT); ASSERT(region->left()->m_type == CSS_IDENT); ASSERT(region->right()->getIdent() == CSSValueInvalid); ASSERT(region->bottom()->getIdent() == CSSValueInvalid); ASSERT(region->left()->getIdent() == CSSValueInvalid); } else { text.append(' '); text += region->top()->cssText() + " "; text += region->right()->cssText() + " "; text += region->bottom()->cssText() + " "; text += region->left()->cssText(); } text += ")"; } break; #endif case CSS_PARSER_VARIABLE_FUNCTION_SYNTAX: text = "-webkit-var("; text += m_value.string; text += ")"; break; case CSS_PARSER_VARIABLE_EQUALS_SYNTAX: text = "="; text += m_value.string; text += "="; break; case CSS_PARSER_VARIABLE_DOLLAR_SYNTAX: text = "$"; text += m_value.string; break; case CSS_PARSER_OPERATOR: char c = static_cast<char>(m_value.ident); text = String(&c, 1U); break; } return text; }
ALWAYS_INLINE String CSSPrimitiveValue::formatNumberForcustomCSSText() const { switch (m_primitiveUnitType) { case CSS_UNKNOWN: return String(); case CSS_NUMBER: case CSS_PARSER_INTEGER: return formatNumberValue(""); case CSS_PERCENTAGE: return formatNumberValue("%"); case CSS_EMS: return formatNumberValue("em"); case CSS_EXS: return formatNumberValue("ex"); case CSS_REMS: return formatNumberValue("rem"); case CSS_CHS: return formatNumberValue("ch"); case CSS_PX: return formatNumberValue("px"); case CSS_CM: return formatNumberValue("cm"); #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSS_DPPX: return formatNumberValue("dppx"); case CSS_DPI: return formatNumberValue("dpi"); case CSS_DPCM: return formatNumberValue("dpcm"); #endif case CSS_MM: return formatNumberValue("mm"); case CSS_IN: return formatNumberValue("in"); case CSS_PT: return formatNumberValue("pt"); case CSS_PC: return formatNumberValue("pc"); case CSS_DEG: return formatNumberValue("deg"); case CSS_RAD: return formatNumberValue("rad"); case CSS_GRAD: return formatNumberValue("grad"); case CSS_MS: return formatNumberValue("ms"); case CSS_S: return formatNumberValue("s"); case CSS_HZ: return formatNumberValue("hz"); case CSS_KHZ: return formatNumberValue("khz"); case CSS_TURN: return formatNumberValue("turn"); case CSS_FR: return formatNumberValue("fr"); case CSS_DIMENSION: // FIXME: We currently don't handle CSS_DIMENSION properly as we don't store // the actual dimension, just the numeric value as a string. case CSS_STRING: return quoteCSSStringIfNeeded(m_value.string); case CSS_URI: return "url(" + quoteCSSURLIfNeeded(m_value.string) + ')'; case CSS_VALUE_ID: return valueName(m_value.valueID); case CSS_PROPERTY_ID: return propertyName(m_value.propertyID); case CSS_ATTR: { StringBuilder result; result.reserveCapacity(6 + m_value.string->length()); result.appendLiteral("attr("); result.append(m_value.string); result.append(')'); return result.toString(); } case CSS_COUNTER_NAME: return "counter(" + String(m_value.string) + ')'; case CSS_COUNTER: { StringBuilder result; String separator = m_value.counter->separator(); if (separator.isEmpty()) result.appendLiteral("counter("); else result.appendLiteral("counters("); result.append(m_value.counter->identifier()); if (!separator.isEmpty()) { result.appendLiteral(", "); result.append(quoteCSSStringIfNeeded(separator)); } String listStyle = m_value.counter->listStyle(); if (!listStyle.isEmpty()) { result.appendLiteral(", "); result.append(listStyle); } result.append(')'); return result.toString(); } case CSS_RECT: return getRectValue()->cssText(); case CSS_QUAD: return getQuadValue()->cssText(); case CSS_RGBCOLOR: case CSS_PARSER_HEXCOLOR: { RGBA32 rgbColor = m_value.rgbcolor; if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR) Color::parseHexColor(m_value.string, rgbColor); Color color(rgbColor); Vector<LChar> result; result.reserveInitialCapacity(32); bool colorHasAlpha = color.hasAlpha(); if (colorHasAlpha) result.append("rgba(", 5); else result.append("rgb(", 4); appendNumber(result, static_cast<unsigned char>(color.red())); result.append(", ", 2); appendNumber(result, static_cast<unsigned char>(color.green())); result.append(", ", 2); appendNumber(result, static_cast<unsigned char>(color.blue())); if (colorHasAlpha) { result.append(", ", 2); NumberToStringBuffer buffer; const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true); result.append(alphaString, strlen(alphaString)); } result.append(')'); return String::adopt(result); } case CSS_PAIR: return getPairValue()->cssText(); #if ENABLE(DASHBOARD_SUPPORT) case CSS_DASHBOARD_REGION: { StringBuilder result; for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { if (!result.isEmpty()) result.append(' '); result.appendLiteral("dashboard-region("); result.append(region->m_label); if (region->m_isCircle) result.appendLiteral(" circle"); else if (region->m_isRectangle) result.appendLiteral(" rectangle"); else break; if (region->top()->m_primitiveUnitType == CSS_VALUE_ID && region->top()->getValueID() == CSSValueInvalid) { ASSERT(region->right()->m_primitiveUnitType == CSS_VALUE_ID); ASSERT(region->bottom()->m_primitiveUnitType == CSS_VALUE_ID); ASSERT(region->left()->m_primitiveUnitType == CSS_VALUE_ID); ASSERT(region->right()->getValueID() == CSSValueInvalid); ASSERT(region->bottom()->getValueID() == CSSValueInvalid); ASSERT(region->left()->getValueID() == CSSValueInvalid); } else { result.append(' '); result.append(region->top()->cssText()); result.append(' '); result.append(region->right()->cssText()); result.append(' '); result.append(region->bottom()->cssText()); result.append(' '); result.append(region->left()->cssText()); } result.append(')'); } return result.toString(); } #endif case CSS_PARSER_OPERATOR: { char c = static_cast<char>(m_value.parserOperator); return String(&c, 1U); } case CSS_PARSER_IDENTIFIER: return quoteCSSStringIfNeeded(m_value.string); case CSS_CALC: return m_value.calc->cssText(); case CSS_SHAPE: return m_value.shape->cssText(); case CSS_VW: return formatNumberValue("vw"); case CSS_VH: return formatNumberValue("vh"); case CSS_VMIN: return formatNumberValue("vmin"); case CSS_VMAX: return formatNumberValue("vmax"); } return String(); }
String CSSPrimitiveValue::customCSSText() const { if (m_hasCachedCSSText) { ASSERT(cssTextCache().contains(this)); return cssTextCache().get(this); } String text; switch (type()) { case UnitType::Unknown: // FIXME break; case UnitType::Integer: text = String::format("%d", getIntValue()); break; case UnitType::Number: case UnitType::Percentage: case UnitType::Ems: case UnitType::Exs: case UnitType::Rems: case UnitType::Chs: case UnitType::Pixels: case UnitType::Centimeters: case UnitType::DotsPerPixel: case UnitType::DotsPerInch: case UnitType::DotsPerCentimeter: case UnitType::Millimeters: case UnitType::Inches: case UnitType::Points: case UnitType::Picas: case UnitType::Degrees: case UnitType::Radians: case UnitType::Gradians: case UnitType::Milliseconds: case UnitType::Seconds: case UnitType::Hertz: case UnitType::Kilohertz: case UnitType::Turns: case UnitType::Fraction: case UnitType::ViewportWidth: case UnitType::ViewportHeight: case UnitType::ViewportMin: case UnitType::ViewportMax: text = formatNumber(m_value.num, unitTypeToString(type())); break; case UnitType::CustomIdentifier: text = quoteCSSStringIfNeeded(m_value.string); break; case UnitType::String: { text = serializeString(m_value.string); break; } case UnitType::URI: text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")"; break; case UnitType::ValueID: text = valueName(m_value.valueID); break; case UnitType::PropertyID: text = propertyName(m_value.propertyID); break; case UnitType::Attribute: { StringBuilder result; result.reserveCapacity(6 + m_value.string->length()); result.appendLiteral("attr("); result.append(m_value.string); result.append(')'); text = result.toString(); break; } case UnitType::Counter: { StringBuilder result; String separator = m_value.counter->separator(); if (separator.isEmpty()) result.appendLiteral("counter("); else result.appendLiteral("counters("); result.append(m_value.counter->identifier()); if (!separator.isEmpty()) { result.appendLiteral(", "); result.append(serializeString(separator)); } String listStyle = m_value.counter->listStyle(); bool isDefaultListStyle = m_value.counter->listStyleIdent() == CSSValueDecimal; if (!listStyle.isEmpty() && !isDefaultListStyle) { result.appendLiteral(", "); result.append(listStyle); } result.append(')'); text = result.toString(); break; } case UnitType::Rect: text = getRectValue()->cssText(); break; case UnitType::Quad: text = getQuadValue()->cssText(); break; case UnitType::RGBColor: { text = Color(m_value.rgbcolor).serializedAsCSSComponentValue(); break; } case UnitType::Pair: text = getPairValue()->cssText(); break; case UnitType::Calc: text = m_value.calc->customCSSText(); break; case UnitType::Shape: text = m_value.shape->cssText(); break; case UnitType::CalcPercentageWithNumber: case UnitType::CalcPercentageWithLength: case UnitType::QuirkyEms: ASSERT_NOT_REACHED(); break; } ASSERT(!cssTextCache().contains(this)); cssTextCache().set(this, text); m_hasCachedCSSText = true; return text; }
String CSSPrimitiveValue::cssText() const { // ### return the original value instead of a generated one (e.g. color // name if it was specified) - check what spec says about this String text; switch ( m_type ) { case CSS_UNKNOWN: // ### break; case CSS_NUMBER: text = String::number(m_value.num); break; case CSS_PERCENTAGE: text = String::number(m_value.num) + "%"; break; case CSS_EMS: text = String::number(m_value.num) + "em"; break; case CSS_EXS: text = String::number(m_value.num) + "ex"; break; case CSS_PX: text = String::number(m_value.num) + "px"; break; case CSS_CM: text = String::number(m_value.num) + "cm"; break; case CSS_MM: text = String::number(m_value.num) + "mm"; break; case CSS_IN: text = String::number(m_value.num) + "in"; break; case CSS_PT: text = String::number(m_value.num) + "pt"; break; case CSS_PC: text = String::number(m_value.num) + "pc"; break; case CSS_DEG: text = String::number(m_value.num) + "deg"; break; case CSS_RAD: text = String::number(m_value.num) + "rad"; break; case CSS_GRAD: text = String::number(m_value.num) + "grad"; break; case CSS_MS: text = String::number(m_value.num) + "ms"; break; case CSS_S: text = String::number(m_value.num) + "s"; break; case CSS_HZ: text = String::number(m_value.num) + "hz"; break; case CSS_KHZ: text = String::number(m_value.num) + "khz"; break; case CSS_DIMENSION: // ### break; case CSS_STRING: text = quoteStringIfNeeded(m_value.string); break; case CSS_URI: text = "url(" + String(m_value.string) + ")"; break; case CSS_IDENT: text = getValueName(m_value.ident); break; case CSS_ATTR: // ### break; case CSS_COUNTER: // ### break; case CSS_RECT: { RectImpl* rectVal = getRectValue(); text = "rect("; text += rectVal->top()->cssText() + " "; text += rectVal->right()->cssText() + " "; text += rectVal->bottom()->cssText() + " "; text += rectVal->left()->cssText() + ")"; break; } case CSS_RGBCOLOR: { Color color(m_value.rgbcolor); if (color.alpha() < 0xFF) text = "rgba("; else text = "rgb("; text += String::number(color.red()) + ", "; text += String::number(color.green()) + ", "; text += String::number(color.blue()); if (color.alpha() < 0xFF) text += ", " + String::number((float)color.alpha() / 0xFF); text += ")"; break; } case CSS_PAIR: text = m_value.pair->first()->cssText(); text += " "; text += m_value.pair->second()->cssText(); break; #if __APPLE__ case CSS_DASHBOARD_REGION: for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) { text = "dashboard-region("; text += region->m_label; if (region->m_isCircle) text += " circle "; else if (region->m_isRectangle) text += " rectangle "; else break; text += region->top()->cssText() + " "; text += region->right()->cssText() + " "; text += region->bottom()->cssText() + " "; text += region->left()->cssText(); text += ")"; } break; #endif } return text; }