float SVGLengthContext::convertValueToUserUnits(float value, SVGLengthMode mode, CSSPrimitiveValue::UnitType fromUnit) const { float userUnits = value; switch (fromUnit) { case CSSPrimitiveValue::UnitType::Pixels: case CSSPrimitiveValue::UnitType::Number: case CSSPrimitiveValue::UnitType::UserUnits: userUnits = value; break; case CSSPrimitiveValue::UnitType::Percentage: { FloatSize viewportSize; if (!determineViewport(viewportSize)) return 0; userUnits = value * dimensionForLengthMode(mode, viewportSize) / 100; break; } case CSSPrimitiveValue::UnitType::Ems: userUnits = convertValueFromEMSToUserUnits(computedStyleForLengthResolving(m_context), value); break; case CSSPrimitiveValue::UnitType::Exs: userUnits = convertValueFromEXSToUserUnits(value); break; case CSSPrimitiveValue::UnitType::Centimeters: userUnits = value * cssPixelsPerCentimeter; break; case CSSPrimitiveValue::UnitType::Millimeters: userUnits = value * cssPixelsPerMillimeter; break; case CSSPrimitiveValue::UnitType::Inches: userUnits = value * cssPixelsPerInch; break; case CSSPrimitiveValue::UnitType::Points: userUnits = value * cssPixelsPerPoint; break; case CSSPrimitiveValue::UnitType::Picas: userUnits = value * cssPixelsPerPica; break; case CSSPrimitiveValue::UnitType::Rems: userUnits = convertValueFromEMSToUserUnits(rootElementStyle(m_context), value); break; case CSSPrimitiveValue::UnitType::Chs: userUnits = convertValueFromCHSToUserUnits(value); break; case CSSPrimitiveValue::UnitType::ViewportWidth: case CSSPrimitiveValue::UnitType::ViewportHeight: case CSSPrimitiveValue::UnitType::ViewportMin: case CSSPrimitiveValue::UnitType::ViewportMax: userUnits = value * dimensionForViewportUnit(m_context, fromUnit); break; default: ASSERT_NOT_REACHED(); break; } // Since we mix css <length> values with svg's length values we need to // clamp values to the narrowest range, otherwise it can result in // rendering issues. return CSSPrimitiveValue::clampToCSSLengthRange(userUnits); }
float SVGLengthContext::valueForLength(const Length& length, float zoom, SVGLengthMode mode) const { float dimension = 0; if (length.hasPercent()) { FloatSize viewportSize; determineViewport(viewportSize); // The viewport will be unaffected by zoom. dimension = dimensionForLengthMode(mode, viewportSize); } return valueForLength(length, zoom, dimension); }
float SVGLengthContext::convertValueToUserUnits(float value, SVGLengthMode mode, SVGLengthType fromUnit) const { float userUnits = value; switch (fromUnit) { case LengthTypeUnknown: return 0; case LengthTypePX: case LengthTypeNumber: userUnits = value; break; case LengthTypePercentage: { FloatSize viewportSize; if (!determineViewport(viewportSize)) return 0; userUnits = value * dimensionForLengthMode(mode, viewportSize) / 100; break; } case LengthTypeEMS: userUnits = convertValueFromEMSToUserUnits(computedStyleForLengthResolving(m_context), value); break; case LengthTypeEXS: userUnits = convertValueFromEXSToUserUnits(value); break; case LengthTypeCM: userUnits = value * cssPixelsPerCentimeter; break; case LengthTypeMM: userUnits = value * cssPixelsPerMillimeter; break; case LengthTypeIN: userUnits = value * cssPixelsPerInch; break; case LengthTypePT: userUnits = value * cssPixelsPerPoint; break; case LengthTypePC: userUnits = value * cssPixelsPerPica; break; case LengthTypeREMS: userUnits = convertValueFromEMSToUserUnits(rootElementStyle(m_context), value); break; case LengthTypeCHS: userUnits = convertValueFromCHSToUserUnits(value); break; default: ASSERT_NOT_REACHED(); break; } // Since we mix css <length> values with svg's length values we need to // clamp values to the narrowest range, otherwise it can result in // rendering issues. return CSSPrimitiveValue::clampToCSSLengthRange(userUnits); }
float SVGLengthContext::convertValueFromUserUnits( float value, SVGLengthMode mode, CSSPrimitiveValue::UnitType toUnit) const { switch (toUnit) { case CSSPrimitiveValue::UnitType::Pixels: case CSSPrimitiveValue::UnitType::Number: case CSSPrimitiveValue::UnitType::Integer: case CSSPrimitiveValue::UnitType::UserUnits: return value; case CSSPrimitiveValue::UnitType::Percentage: { FloatSize viewportSize; if (!determineViewport(viewportSize)) return 0; float dimension = dimensionForLengthMode(mode, viewportSize); if (!dimension) return 0; // LengthTypePercentage is represented with 100% = 100.0. // Good for accuracy but could eventually be changed. return value * 100 / dimension; } case CSSPrimitiveValue::UnitType::Ems: return convertValueFromUserUnitsToEMS( computedStyleForLengthResolving(m_context), value); case CSSPrimitiveValue::UnitType::Exs: return convertValueFromUserUnitsToEXS(value); case CSSPrimitiveValue::UnitType::Rems: return convertValueFromUserUnitsToEMS(rootElementStyle(m_context), value); case CSSPrimitiveValue::UnitType::Chs: return convertValueFromUserUnitsToCHS(value); case CSSPrimitiveValue::UnitType::Centimeters: return value / cssPixelsPerCentimeter; case CSSPrimitiveValue::UnitType::Millimeters: return value / cssPixelsPerMillimeter; case CSSPrimitiveValue::UnitType::Inches: return value / cssPixelsPerInch; case CSSPrimitiveValue::UnitType::Points: return value / cssPixelsPerPoint; case CSSPrimitiveValue::UnitType::Picas: return value / cssPixelsPerPica; case CSSPrimitiveValue::UnitType::ViewportWidth: case CSSPrimitiveValue::UnitType::ViewportHeight: case CSSPrimitiveValue::UnitType::ViewportMin: case CSSPrimitiveValue::UnitType::ViewportMax: return value / dimensionForViewportUnit(m_context, toUnit); default: break; } ASSERT_NOT_REACHED(); return 0; }
ExceptionOr<float> SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode mode) const { FloatSize viewportSize; if (!determineViewport(viewportSize)) return Exception { NOT_SUPPORTED_ERR }; switch (mode) { case LengthModeWidth: return value * viewportSize.width(); case LengthModeHeight: return value * viewportSize.height(); case LengthModeOther: return value * std::sqrt(viewportSize.diagonalLengthSquared() / 2); }; ASSERT_NOT_REACHED(); return 0; }
float SVGLengthContext::convertValueFromUserUnits(float value, SVGLengthMode mode, SVGLengthType toUnit) const { switch (toUnit) { case LengthTypeUnknown: return 0; case LengthTypeNumber: return value; case LengthTypePercentage: { FloatSize viewportSize; if (!determineViewport(viewportSize)) return 0; float dimension = dimensionForLengthMode(mode, viewportSize); if (!dimension) return 0; // LengthTypePercentage is represented with 100% = 100.0. // Good for accuracy but could eventually be changed. return value * 100 / dimension; } case LengthTypeEMS: return convertValueFromUserUnitsToEMS(computedStyleForLengthResolving(m_context), value); case LengthTypeEXS: return convertValueFromUserUnitsToEXS(value); case LengthTypeREMS: return convertValueFromUserUnitsToEMS(rootElementStyle(m_context), value); case LengthTypeCHS: return convertValueFromUserUnitsToCHS(value); case LengthTypePX: return value; case LengthTypeCM: return value / cssPixelsPerCentimeter; case LengthTypeMM: return value / cssPixelsPerMillimeter; case LengthTypeIN: return value / cssPixelsPerInch; case LengthTypePT: return value / cssPixelsPerPoint; case LengthTypePC: return value / cssPixelsPerPica; } ASSERT_NOT_REACHED(); return 0; }
float SVGLengthContext::valueForLength(const Length& length, SVGLengthMode mode) { if (length.isPercent()) return convertValueFromPercentageToUserUnits(length.value() / 100, mode, IGNORE_EXCEPTION); if (length.isAuto() || !length.isSpecified()) return 0; FloatSize viewportSize; determineViewport(viewportSize); switch (mode) { case LengthModeWidth: return floatValueForLength(length, viewportSize.width()); case LengthModeHeight: return floatValueForLength(length, viewportSize.height()); case LengthModeOther: return floatValueForLength(length, sqrtf(viewportSize.diagonalLengthSquared() / 2)); }; return 0; }
float SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLengthMode mode, ExceptionCode& ec) const { FloatSize viewportSize; if (!determineViewport(viewportSize)) { ec = NOT_SUPPORTED_ERR; return 0; } switch (mode) { case LengthModeWidth: return value / viewportSize.width() * 100; case LengthModeHeight: return value / viewportSize.height() * 100; case LengthModeOther: return value / (sqrtf(viewportSize.diagonalLengthSquared() / 2)) * 100; }; ASSERT_NOT_REACHED(); return 0; }
float SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode mode, ExceptionState& exceptionState) const { FloatSize viewportSize; if (!determineViewport(viewportSize)) { exceptionState.throwDOMException(NotSupportedError, "The viewport could not be determined."); return 0; } switch (mode) { case LengthModeWidth: return value * viewportSize.width(); case LengthModeHeight: return value * viewportSize.height(); case LengthModeOther: return value * sqrtf(viewportSize.diagonalLengthSquared() / 2); }; ASSERT_NOT_REACHED(); return 0; }
float SVGLength::convertValueFromPercentageToUserUnits(float value, const SVGElement* context, ExceptionCode& ec) const { float width = 0; float height = 0; if (!determineViewport(context, width, height)) { ec = NOT_SUPPORTED_ERR; return 0; } switch (extractMode(m_unit)) { case LengthModeWidth: return value * width; case LengthModeHeight: return value * height; case LengthModeOther: return value * sqrtf((width * width + height * height) / 2); }; ASSERT_NOT_REACHED(); return 0; }
float SVGLengthContext::convertValueFromPercentageToUserUnits(float value, SVGLengthMode mode, ExceptionState& es) const { float width = 0; float height = 0; if (!determineViewport(width, height)) { es.throwDOMException(NotSupportedError); return 0; } switch (mode) { case LengthModeWidth: return value * width; case LengthModeHeight: return value * height; case LengthModeOther: return value * sqrtf((width * width + height * height) / 2); }; ASSERT_NOT_REACHED(); return 0; }
float SVGLengthContext::convertValueFromUserUnitsToPercentage(float value, SVGLengthMode mode, ExceptionCode& ec) const { float width = 0; float height = 0; if (!determineViewport(width, height)) { ec = NOT_SUPPORTED_ERR; return 0; } switch (mode) { case LengthModeWidth: return value / width * 100; case LengthModeHeight: return value / height * 100; case LengthModeOther: return value / (sqrtf((width * width + height * height) / 2)) * 100; }; ASSERT_NOT_REACHED(); return 0; }
float SVGLengthContext::valueForLength(const Length& length, SVGLengthMode mode) { if (length.isPercent()) { auto result = convertValueFromPercentageToUserUnits(length.value() / 100, mode); if (result.hasException()) return 0; return result.releaseReturnValue(); } if (length.isAuto() || !length.isSpecified()) return 0; FloatSize viewportSize; determineViewport(viewportSize); switch (mode) { case LengthModeWidth: return floatValueForLength(length, viewportSize.width()); case LengthModeHeight: return floatValueForLength(length, viewportSize.height()); case LengthModeOther: return floatValueForLength(length, std::sqrt(viewportSize.diagonalLengthSquared() / 2)); }; return 0; }