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