18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Igalia S.L.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
262bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
272bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "PlatformContextCairo.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
292bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <cairo.h>
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
312bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WebCore {
322bde8e466a4451c7319e3a072d118917957d6554Steve Block
332bde8e466a4451c7319e3a072d118917957d6554Steve BlockPlatformContextCairo::PlatformContextCairo(cairo_t* cr)
342bde8e466a4451c7319e3a072d118917957d6554Steve Block    : m_cr(cr)
352bde8e466a4451c7319e3a072d118917957d6554Steve Block{
362bde8e466a4451c7319e3a072d118917957d6554Steve Block}
372bde8e466a4451c7319e3a072d118917957d6554Steve Block
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid PlatformContextCairo::restore()
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    const ImageMaskInformation& maskInformation = m_maskImageStack.last();
412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (maskInformation.isValid()) {
422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        const FloatRect& maskRect = maskInformation.maskRect();
432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        cairo_pop_group_to_source(m_cr.get());
442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        cairo_mask_surface(m_cr.get(), maskInformation.maskSurface(), maskRect.x(), maskRect.y());
452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_maskImageStack.removeLast();
472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_restore(m_cr.get());
492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid PlatformContextCairo::save()
522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_maskImageStack.append(ImageMaskInformation());
542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_save(m_cr.get());
562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid PlatformContextCairo::pushImageMask(cairo_surface_t* surface, const FloatRect& rect)
592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // We must call savePlatformState at least once before we can use image masking,
612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // since we actually apply the mask in restorePlatformState.
622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(!m_maskImageStack.isEmpty());
632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_maskImageStack.last().update(surface, rect);
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Cairo doesn't support the notion of an image clip, so we push a group here
662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // and then paint it to the surface with an image mask (which is an immediate
672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // operation) during restorePlatformState.
682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // We want to allow the clipped elements to composite with the surface as it
702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // is now, but they are isolated in another group. To make this work, we're
712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // going to blit the current surface contents onto the new group once we push it.
722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_surface_t* currentTarget = cairo_get_target(m_cr.get());
732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_surface_flush(currentTarget);
742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Pushing a new group ensures that only things painted after this point are clipped.
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_push_group(m_cr.get());
772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_set_operator(m_cr.get(), CAIRO_OPERATOR_SOURCE);
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_set_source_surface(m_cr.get(), currentTarget, 0, 0);
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_rectangle(m_cr.get(), rect.x(), rect.y(), rect.width(), rect.height());
812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    cairo_fill(m_cr.get());
822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
852bde8e466a4451c7319e3a072d118917957d6554Steve Block} // namespace WebCore
86