summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/canvas/CanvasStyle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/canvas/CanvasStyle.cpp')
-rw-r--r--Source/WebCore/html/canvas/CanvasStyle.cpp304
1 files changed, 113 insertions, 191 deletions
diff --git a/Source/WebCore/html/canvas/CanvasStyle.cpp b/Source/WebCore/html/canvas/CanvasStyle.cpp
index 8b0883951..052fa3164 100644
--- a/Source/WebCore/html/canvas/CanvasStyle.cpp
+++ b/Source/WebCore/html/canvas/CanvasStyle.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
@@ -13,10 +13,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -43,260 +43,182 @@
namespace WebCore {
-enum ColorParseResult { ParsedRGBA, ParsedCurrentColor, ParsedSystemColor, ParseFailed };
+static bool isCurrentColorString(const String& colorString)
+{
+ return equalLettersIgnoringASCIICase(colorString, "currentcolor");
+}
-static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString, Document* document = 0)
+static Color parseColor(const String& colorString, Document* document = nullptr)
{
- if (equalIgnoringCase(colorString, "currentcolor"))
- return ParsedCurrentColor;
- if (CSSParser::parseColor(parsedColor, colorString))
- return ParsedRGBA;
- if (CSSParser::parseSystemColor(parsedColor, colorString, document))
- return ParsedSystemColor;
- return ParseFailed;
+ Color color = CSSParser::parseColor(colorString);
+ if (color.isValid())
+ return color;
+ return CSSParser::parseSystemColor(colorString, document);
}
-RGBA32 currentColor(HTMLCanvasElement* canvas)
+Color currentColor(HTMLCanvasElement* canvas)
{
- if (!canvas || !canvas->inDocument() || !canvas->inlineStyle())
+ if (!canvas || !canvas->isConnected() || !canvas->inlineStyle())
return Color::black;
- RGBA32 rgba = Color::black;
- CSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor));
- return rgba;
+ Color color = CSSParser::parseColor(canvas->inlineStyle()->getPropertyValue(CSSPropertyColor));
+ if (!color.isValid())
+ return Color::black;
+ return color;
}
-bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement* canvas)
+Color parseColorOrCurrentColor(const String& colorString, HTMLCanvasElement* canvas)
{
- ColorParseResult parseResult = parseColor(parsedColor, colorString, canvas ? &canvas->document() : 0);
- switch (parseResult) {
- case ParsedRGBA:
- case ParsedSystemColor:
- return true;
- case ParsedCurrentColor:
- parsedColor = currentColor(canvas);
- return true;
- case ParseFailed:
- return false;
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ if (isCurrentColorString(colorString))
+ return currentColor(canvas);
+
+ return parseColor(colorString, canvas ? &canvas->document() : nullptr);
}
-CanvasStyle::CanvasStyle(RGBA32 rgba)
- : m_rgba(rgba)
- , m_type(RGBA)
+CanvasStyle::CanvasStyle(Color color)
+ : m_style(color)
{
}
CanvasStyle::CanvasStyle(float grayLevel, float alpha)
- : m_rgba(makeRGBA32FromFloats(grayLevel, grayLevel, grayLevel, alpha))
- , m_type(RGBA)
+ : m_style(Color { grayLevel, grayLevel, grayLevel, alpha })
{
}
CanvasStyle::CanvasStyle(float r, float g, float b, float a)
- : m_rgba(makeRGBA32FromFloats(r, g, b, a))
- , m_type(RGBA)
+ : m_style(Color { r, g, b, a })
{
}
CanvasStyle::CanvasStyle(float c, float m, float y, float k, float a)
- : m_cmyka(new CMYKAValues(makeRGBAFromCMYKA(c, m, y, k, a), c, m, y, k, a))
- , m_type(CMYKA)
+ : m_style(CMYKAColor { Color { c, m, y, k, a }, c, m, y, k, a })
{
}
-CanvasStyle::CanvasStyle(PassRefPtr<CanvasGradient> gradient)
- : m_gradient(gradient.leakRef())
- , m_type(Gradient)
+CanvasStyle::CanvasStyle(CanvasGradient& gradient)
+ : m_style(makeRefPtr(gradient))
{
- if (!m_gradient)
- m_type = Invalid;
}
-CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern)
- : m_pattern(pattern.leakRef())
- , m_type(ImagePattern)
+CanvasStyle::CanvasStyle(CanvasPattern& pattern)
+ : m_style(makeRefPtr(pattern))
{
- if (!m_pattern)
- m_type = Invalid;
}
-CanvasStyle::~CanvasStyle()
+inline CanvasStyle::CanvasStyle(CurrentColor color)
+ : m_style(color)
{
- if (m_type == Gradient)
- m_gradient->deref();
- else if (m_type == ImagePattern)
- m_pattern->deref();
- else if (m_type == CMYKA)
- delete m_cmyka;
}
-CanvasStyle CanvasStyle::createFromString(const String& color, Document* document)
+CanvasStyle CanvasStyle::createFromString(const String& colorString, Document* document)
{
- RGBA32 rgba;
- ColorParseResult parseResult = parseColor(rgba, color, document);
- switch (parseResult) {
- case ParsedRGBA:
- case ParsedSystemColor:
- return CanvasStyle(rgba);
- case ParsedCurrentColor:
- return CanvasStyle(ConstructCurrentColor);
- case ParseFailed:
- return CanvasStyle();
- default:
- ASSERT_NOT_REACHED();
- return CanvasStyle();
- }
+ if (isCurrentColorString(colorString))
+ return CurrentColor { std::nullopt };
+
+ Color color = parseColor(colorString, document);
+ if (!color.isValid())
+ return { };
+
+ return color;
}
-CanvasStyle CanvasStyle::createFromStringWithOverrideAlpha(const String& color, float alpha)
+CanvasStyle CanvasStyle::createFromStringWithOverrideAlpha(const String& colorString, float alpha)
{
- RGBA32 rgba;
- ColorParseResult parseResult = parseColor(rgba, color);
- switch (parseResult) {
- case ParsedRGBA:
- return CanvasStyle(colorWithOverrideAlpha(rgba, alpha));
- case ParsedCurrentColor:
- return CanvasStyle(CurrentColorWithOverrideAlpha, alpha);
- case ParseFailed:
- return CanvasStyle();
- default:
- ASSERT_NOT_REACHED();
- return CanvasStyle();
- }
+ if (isCurrentColorString(colorString))
+ return CurrentColor { alpha };
+
+ Color color = parseColor(colorString);
+ if (!color.isValid())
+ return { };
+
+ return Color { colorWithOverrideAlpha(color.rgb(), alpha) };
}
bool CanvasStyle::isEquivalentColor(const CanvasStyle& other) const
{
- if (m_type != other.m_type)
- return false;
+ if (WTF::holds_alternative<Color>(m_style) && WTF::holds_alternative<Color>(other.m_style))
+ return WTF::get<Color>(m_style) == WTF::get<Color>(other.m_style);
- switch (m_type) {
- case RGBA:
- return m_rgba == other.m_rgba;
- case CMYKA:
- return m_cmyka->c == other.m_cmyka->c
- && m_cmyka->m == other.m_cmyka->m
- && m_cmyka->y == other.m_cmyka->y
- && m_cmyka->k == other.m_cmyka->k
- && m_cmyka->a == other.m_cmyka->a;
- case Gradient:
- case ImagePattern:
- case CurrentColor:
- case CurrentColorWithOverrideAlpha:
- return false;
- case Invalid:
- break;
+ if (WTF::holds_alternative<CMYKAColor>(m_style) && WTF::holds_alternative<CMYKAColor>(other.m_style)) {
+ auto& a = WTF::get<CMYKAColor>(m_style);
+ auto& b = WTF::get<CMYKAColor>(other.m_style);
+ return a.c == b.c && a.m == b.m && a.y == b.y && a.k == b.k && a.a == b.a;
}
- ASSERT_NOT_REACHED();
return false;
}
bool CanvasStyle::isEquivalentRGBA(float r, float g, float b, float a) const
{
- if (m_type != RGBA)
- return false;
-
- return m_rgba == makeRGBA32FromFloats(r, g, b, a);
+ return WTF::holds_alternative<Color>(m_style) && WTF::get<Color>(m_style) == Color { r, g, b, a };
}
bool CanvasStyle::isEquivalentCMYKA(float c, float m, float y, float k, float a) const
{
- if (m_type != CMYKA)
+ if (!WTF::holds_alternative<CMYKAColor>(m_style))
return false;
- return c == m_cmyka->c
- && m == m_cmyka->m
- && y == m_cmyka->y
- && k == m_cmyka->k
- && a == m_cmyka->a;
-}
-
-CanvasStyle::CanvasStyle(const CanvasStyle& other)
-{
- memcpy(this, &other, sizeof(CanvasStyle));
- if (m_type == Gradient)
- m_gradient->ref();
- else if (m_type == ImagePattern)
- m_pattern->ref();
- else if (m_type == CMYKA)
- m_cmyka = new CMYKAValues(other.m_cmyka->rgba, other.m_cmyka->c, other.m_cmyka->m, other.m_cmyka->y, other.m_cmyka->k, other.m_cmyka->a);
-}
-
-CanvasStyle& CanvasStyle::operator=(const CanvasStyle& other)
-{
- if (this != &other) {
- this->~CanvasStyle();
- new (this) CanvasStyle(other);
- }
- return *this;
+ auto& channels = WTF::get<CMYKAColor>(m_style);
+ return c == channels.c && m == channels.m && y == channels.y && k == channels.k && a == channels.a;
}
-void CanvasStyle::applyStrokeColor(GraphicsContext* context) const
+void CanvasStyle::applyStrokeColor(GraphicsContext& context) const
{
- if (!context)
- return;
- switch (m_type) {
- case RGBA:
- context->setStrokeColor(m_rgba, ColorSpaceDeviceRGB);
- break;
- case CMYKA: {
- // FIXME: Do this through platform-independent GraphicsContext API.
- // We'll need a fancier Color abstraction to support CMYKA correctly
+ WTF::switchOn(m_style,
+ [&context] (const Color& color) {
+ context.setStrokeColor(color);
+ },
+ [&context] (const CMYKAColor& color) {
+ // FIXME: Do this through platform-independent GraphicsContext API.
+ // We'll need a fancier Color abstraction to support CMYKA correctly
#if USE(CG)
- CGContextSetCMYKStrokeColor(context->platformContext(), m_cmyka->c, m_cmyka->m, m_cmyka->y, m_cmyka->k, m_cmyka->a);
+ CGContextSetCMYKStrokeColor(context.platformContext(), color.c, color.m, color.y, color.k, color.a);
#else
- context->setStrokeColor(m_cmyka->rgba, ColorSpaceDeviceRGB);
+ context.setStrokeColor(color.color);
#endif
- break;
- }
- case Gradient:
- context->setStrokeGradient(canvasGradient()->gradient());
- break;
- case ImagePattern:
- context->setStrokePattern(canvasPattern()->pattern());
- break;
- case CurrentColor:
- case CurrentColorWithOverrideAlpha:
- case Invalid:
- ASSERT_NOT_REACHED();
- break;
- }
-}
-
-void CanvasStyle::applyFillColor(GraphicsContext* context) const
-{
- if (!context)
- return;
- switch (m_type) {
- case RGBA:
- context->setFillColor(m_rgba, ColorSpaceDeviceRGB);
- break;
- case CMYKA: {
- // FIXME: Do this through platform-independent GraphicsContext API.
- // We'll need a fancier Color abstraction to support CMYKA correctly
+ },
+ [&context] (const RefPtr<CanvasGradient>& gradient) {
+ context.setStrokeGradient(gradient->gradient());
+ },
+ [&context] (const RefPtr<CanvasPattern>& pattern) {
+ context.setStrokePattern(pattern->pattern());
+ },
+ [] (const CurrentColor&) {
+ ASSERT_NOT_REACHED();
+ },
+ [] (const Invalid&) {
+ ASSERT_NOT_REACHED();
+ }
+ );
+}
+
+void CanvasStyle::applyFillColor(GraphicsContext& context) const
+{
+ WTF::switchOn(m_style,
+ [&context] (const Color& color) {
+ context.setFillColor(color);
+ },
+ [&context] (const CMYKAColor& color) {
+ // FIXME: Do this through platform-independent GraphicsContext API.
+ // We'll need a fancier Color abstraction to support CMYKA correctly
#if USE(CG)
- CGContextSetCMYKFillColor(context->platformContext(), m_cmyka->c, m_cmyka->m, m_cmyka->y, m_cmyka->k, m_cmyka->a);
+ CGContextSetCMYKFillColor(context.platformContext(), color.c, color.m, color.y, color.k, color.a);
#else
- context->setFillColor(m_cmyka->rgba, ColorSpaceDeviceRGB);
+ context.setFillColor(color.color);
#endif
- break;
- }
- case Gradient:
- context->setFillGradient(canvasGradient()->gradient());
- break;
- case ImagePattern:
- context->setFillPattern(canvasPattern()->pattern());
- break;
- case CurrentColor:
- case CurrentColorWithOverrideAlpha:
- case Invalid:
- ASSERT_NOT_REACHED();
- break;
- }
+ },
+ [&context] (const RefPtr<CanvasGradient>& gradient) {
+ context.setFillGradient(gradient->gradient());
+ },
+ [&context] (const RefPtr<CanvasPattern>& pattern) {
+ context.setFillPattern(pattern->pattern());
+ },
+ [] (const CurrentColor&) {
+ ASSERT_NOT_REACHED();
+ },
+ [] (const Invalid&) {
+ ASSERT_NOT_REACHED();
+ }
+ );
}
}