summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cairo/ImageCairo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/cairo/ImageCairo.cpp')
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
new file mode 100644
index 0000000..0a35cf2
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * 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
+ * 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
+ * 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
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BitmapImage.h"
+
+#if PLATFORM(CAIRO)
+
+#include "AffineTransform.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "ImageObserver.h"
+#include <cairo.h>
+#include <math.h>
+
+namespace WebCore {
+
+void FrameData::clear()
+{
+ if (m_frame) {
+ cairo_surface_destroy(m_frame);
+ m_frame = 0;
+ // NOTE: We purposefully don't reset metadata here, so that even if we
+ // throw away previously-decoded data, animation loops can still access
+ // properties like frame durations without re-decoding.
+ }
+}
+
+BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer)
+ : Image(observer)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(cAnimationNone)
+ , m_repetitionCountStatus(Unknown)
+ , m_repetitionsComplete(0)
+ , m_isSolidColor(false)
+ , m_animationFinished(true)
+ , m_allDataReceived(true)
+ , m_haveSize(true)
+ , m_sizeAvailable(true)
+ , m_decodedSize(0)
+ , m_haveFrameCount(true)
+ , m_frameCount(1)
+{
+ initPlatformData();
+
+ // TODO: check to be sure this is an image surface
+
+ int width = cairo_image_surface_get_width(surface);
+ int height = cairo_image_surface_get_height(surface);
+ m_decodedSize = width * height * 4;
+ m_size = IntSize(width, height);
+
+ m_frames.grow(1);
+ m_frames[0].m_frame = surface;
+ m_frames[0].m_hasAlpha = cairo_surface_get_content(surface) != CAIRO_CONTENT_COLOR;
+ m_frames[0].m_haveMetadata = true;
+ checkForSolidColor();
+}
+
+void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+{
+ startAnimation();
+
+ cairo_surface_t* image = frameAtIndex(m_currentFrame);
+ if (!image) // If it's too early we won't have an image yet.
+ return;
+
+ FloatRect srcRect(src);
+ FloatRect dstRect(dst);
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(context, dstRect, solidColor(), op);
+ return;
+ }
+
+ IntSize selfSize = size();
+
+ cairo_t* cr = context->platformContext();
+ cairo_save(cr);
+
+ // Set the compositing operation.
+ if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
+ context->setCompositeOperation(CompositeCopy);
+ else
+ context->setCompositeOperation(op);
+
+ // If we're drawing a sub portion of the image or scaling then create
+ // a pattern transformation on the image and draw the transformed pattern.
+ // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
+
+ // To avoid the unwanted gradient effect (#14017) we use
+ // CAIRO_FILTER_NEAREST now, but the real fix will be to have
+ // CAIRO_EXTEND_PAD implemented for surfaces in Cairo allowing us to still
+ // use bilinear filtering
+ cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+
+ float scaleX = srcRect.width() / dstRect.width();
+ float scaleY = srcRect.height() / dstRect.height();
+ cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
+ cairo_pattern_set_matrix(pattern, &matrix);
+
+ // Draw the image.
+ cairo_translate(cr, dstRect.x(), dstRect.y());
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, 0, 0, dstRect.width(), dstRect.height());
+ cairo_clip(cr);
+ cairo_paint_with_alpha(cr, context->getAlpha());
+
+ cairo_restore(cr);
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ cairo_surface_t* image = nativeImageForCurrentFrame();
+ if (!image) // If it's too early we won't have an image yet.
+ return;
+
+ cairo_t* cr = context->platformContext();
+ context->save();
+
+ // TODO: Make use of tileRect.
+
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+
+ // Workaround to avoid the unwanted gradient effect (#14017)
+ cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+
+ cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
+ cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x(), phase.y()};
+ cairo_matrix_t combined;
+ cairo_matrix_multiply(&combined, &pattern_matrix, &phase_matrix);
+ cairo_matrix_invert(&combined);
+ cairo_pattern_set_matrix(pattern, &combined);
+
+ context->setCompositeOperation(op);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height());
+ cairo_fill(cr);
+
+ context->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+void BitmapImage::checkForSolidColor()
+{
+ // FIXME: It's easy to implement this optimization. Just need to check the RGBA32 buffer to see if it is 1x1.
+ m_isSolidColor = false;
+}
+
+}
+
+#endif // PLATFORM(CAIRO)