15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
33a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/ImageBuffer.h"
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/win/TransparencyWin.h"
361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/transforms/AffineTransform.h"
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <windows.h>
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <gtest/gtest.h>
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static FloatRect RECTToFloatRect(const RECT* rect)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return FloatRect(static_cast<float>(rect->left),
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                     static_cast<float>(rect->top),
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                     static_cast<float>(rect->right - rect->left),
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                     static_cast<float>(rect->bottom - rect->top));
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static Color getPixelAt(GraphicsContext* context, int x, int y)
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    const SkBitmap& bitmap = context->layerBitmap();
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return Color(*reinterpret_cast<const RGBA32*>(bitmap.getAddr32(x, y)));
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Resets the top layer's alpha channel to 0 for each pixel. This simulates
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Windows messing it up.
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void clearTopLayerAlphaChannel(GraphicsContext* context)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    SkBitmap& bitmap = const_cast<SkBitmap&>(context->layerBitmap());
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int y = 0; y < bitmap.height(); y++) {
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t* row = bitmap.getAddr32(0, y);
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (int x = 0; x < bitmap.width(); x++)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            row[x] &= 0x00FFFFFF;
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Clears the alpha channel on the specified pixel.
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void clearTopLayerAlphaPixel(GraphicsContext* context, int x, int y)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)    SkBitmap& bitmap = const_cast<SkBitmap&>(context->layerBitmap());
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    *bitmap.getAddr32(x, y) &= 0x00FFFFFF;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static std::ostream& operator<<(std::ostream& out, const Color& c)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    std::ios_base::fmtflags oldFlags = out.flags(std::ios_base::hex |
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                 std::ios_base::showbase);
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    out << c.rgb();
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    out.flags(oldFlags);
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return out;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, NoLayer)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
87a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(17, 16)));
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // KeepTransform
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::NoLayer,
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 12));
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() == helper.context());
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize);
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect());
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Untransform is not allowed for NoLayer.
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ScaleTransform
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->scale(FloatSize(2.0, 0.5));
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::NoLayer,
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::ScaleTransform,
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(2, 2, 6, 6));
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The coordinate system should be based in the upper left of our box.
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // It should be post-transformed.
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() == helper.context());
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(12, 3) == helper.m_layerSize);
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(4, 1, 12, 3) == helper.drawRect());
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, WhiteLayer)
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
126a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // KeepTransform
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::WhiteLayer,
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 12));
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize);
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect());
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Untransform
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::WhiteLayer,
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::Untransform,
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 12));
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(0, 0, 14, 12) == helper.drawRect());
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ScaleTransform
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->scale(FloatSize(2.0, 0.5));
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::WhiteLayer,
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::ScaleTransform,
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(2, 2, 6, 6));
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The coordinate system should be based in the upper left of our box.
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // It should be post-transformed.
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(12, 3) == helper.m_layerSize);
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(0, 0, 12, 3) == helper.drawRect());
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, TextComposite)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
178a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // KeepTransform is the only valid transform mode for TextComposite.
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::TextComposite,
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 12));
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize);
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect());
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, OpaqueCompositeLayer)
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
197a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // KeepTransform
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 12));
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize);
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(1, 1, 14, 12) == helper.drawRect());
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // KeepTransform with scroll applied.
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->translate(0, -1);
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 14));
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 14) == helper.m_layerSize);
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(1, 1, 14, 14) == helper.drawRect());
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Untransform
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::Untransform,
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 12));
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(14, 12) == helper.m_layerSize);
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(0, 0, 14, 12) == helper.drawRect());
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ScaleTransform
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->scale(FloatSize(2.0, 0.5));
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::ScaleTransform,
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(2, 2, 6, 6));
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The coordinate system should be based in the upper left of our box.
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // It should be post-transformed.
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(src->context() != helper.context());
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntSize(12, 3) == helper.m_layerSize);
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(IntRect(0, 0, 12, 3) == helper.drawRect());
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, OpaqueCompositeLayerPixel)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color red(0xFFFF0000), darkRed(0xFFBF0000);
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color green(0xFF00FF00);
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make a red bottom layer, followed by a half green next layer @ 50%.
270a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect fullRect(0, 0, 16, 16);
2735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(fullRect, red);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->beginTransparencyLayer(0.5);
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect rightHalf(8, 0, 8, 16);
2765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(rightHalf, green);
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make a transparency layer inset by one pixel, and fill it inset by
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // another pixel with 50% black.
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 14, 14));
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect inner(2, 2, 12, 12);
2885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(inner, Color(0x7f000000));
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // These coordinates are relative to the layer, whish is inset by 1x1
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // pixels from the top left. So we're actually clearing (2, 2) and
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // (13,13), which are the extreme corners of the black area (and which
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // we check below).
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTopLayerAlphaPixel(helper.context(), 1, 1);
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTopLayerAlphaPixel(helper.context(), 12, 12);
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Finish the compositing.
299c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    src->context()->endLayer();
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check that we got the right values, it should be like the rectangle was
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // drawn with half opacity even though the alpha channel got messed up.
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(red, getPixelAt(src->context(), 0, 0));
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(red, getPixelAt(src->context(), 1, 1));
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(darkRed, getPixelAt(src->context(), 2, 2));
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The dark result is:
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //   (black @ 50% atop green) @ 50% atop red = 0xFF804000
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // which is 0xFFA02000 (Skia computes 0xFFA11F00 due to rounding).
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color darkGreenRed(0xFF803f00);
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(darkGreenRed, getPixelAt(src->context(), 13, 13));
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // 50% green on top of red = FF808000 (rounded to what Skia will produce).
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color greenRed(0xFF807F00);
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(greenRed, getPixelAt(src->context(), 14, 14));
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(greenRed, getPixelAt(src->context(), 15, 15));
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Tests that translations are properly handled when using KeepTransform.
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, TranslateOpaqueCompositeLayer)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fill with white.
323a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color white(0xFFFFFFFF);
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect fullRect(0, 0, 16, 16);
3265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(fullRect, white);
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Scroll down by 8 (coordinate system goes up).
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->translate(0, -8);
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color red(0xFFFF0000);
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color green(0xFF00FF00);
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Make the transparency layer after translation will be @ (0, -8) with
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // size 16x16.
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(0, 0, 16, 16));
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Draw a red pixel at (15, 15). This should be the at (15, 7) after
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // the transform.
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect bottomRight(15, 15, 1, 1);
3465267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(bottomRight, green);
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check the pixel we wrote.
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(green, getPixelAt(src->context(), 15, 7));
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void testClippedLayerKeepTransform(TransparencyWin::LayerMode layerMode)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fill with white.
359a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color white(0xFFFFFFFF);
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect fullRect(0, 0, 16, 16);
3625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(fullRect, white);
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IntRect clipRect(IntPoint(11, 5), IntSize(1, 1));
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->clip(clipRect);
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Scroll down by 6 (coordinate system goes up).
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->translate(0, -6);
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color red(0xFFFF0000);
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color green(0xFF00FF00);
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The transparency layer after translation will be @ (0, -6) with
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // a size that would be too large to handle unclipped.
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    layerMode,
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(0, 0, INT_MAX, INT_MAX));
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Draw a green pixel at (11, 11). This should be within the clip rect
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // and at (11, 5) after the transform.
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect greenRect(11, 11, 1, 1);
3855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(greenRect, green);
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Draw a red pixel at (9, 9). This should be outside the clip rect
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // and not drawn.
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect redRect(9, 9, 1, 1);
3905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(redRect, red);
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify green pixel got drawn in clip rect and red pixel got clipped.
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(green, getPixelAt(src->context(), 11, 5));
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 9, 3));
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, ClippedKeepTransformNoLayer)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    testClippedLayerKeepTransform(TransparencyWin::NoLayer);
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, ClippedKeepTransformOpaqueCompositeLayer)
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    testClippedLayerKeepTransform(TransparencyWin::OpaqueCompositeLayer);
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, ClippedKeepTransformWhiteLayer)
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    testClippedLayerKeepTransform(TransparencyWin::WhiteLayer);
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Same as OpaqueCompositeLayer, but the canvas has a rotation applied. This
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// tests that the propert transform is applied to the copied layer.
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, RotateOpaqueCompositeLayer)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
420a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The background is white.
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color white(0xFFFFFFFF);
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect fullRect(0, 0, 16, 16);
4255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(fullRect, white);
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Rotate the image by 90 degrees. This matrix is the same as
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // cw90.rotate(90); but avoids rounding errors. Rounding errors can cause
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Skia to think that !rectStaysRect() and it will fall through to path
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // drawing mode, which in turn gives us antialiasing. We want no
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // antialiasing or other rounding problems since we're testing exact pixel
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // values.
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform cw90(0, 1, -1, 0, 0, 0);
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->concatCTM(cw90);
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make a transparency layer consisting of a horizontal line of 50% black.
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Since the rotation is applied, this will actually be a vertical line
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // down the middle of the image.
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->beginTransparencyLayer(0.5);
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect blackRect(0, -9, 16, 2);
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color black(0xFF000000);
4435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(blackRect, black);
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Now draw 50% red square.
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Create a transparency helper inset one pixel in the buffer. The
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // coordinates are before transforming into this space, and maps to
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // IntRect(1, 1, 14, 14).
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::Untransform,
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, -15, 14, 14));
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Fill with red.
4575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(helper.drawRect(), Color(0x7f7f0000));
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTopLayerAlphaChannel(helper.context());
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Finish the compositing.
463c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    src->context()->endLayer();
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Top corner should be the original background.
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 0, 0));
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check the stripe down the middle, first at the top...
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color gray(0xFF808080);
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 6, 0));
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(gray, getPixelAt(src->context(), 7, 0));
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(gray, getPixelAt(src->context(), 8, 0));
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 9, 0));
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ...now at the bottom.
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 6, 15));
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(gray, getPixelAt(src->context(), 7, 15));
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(gray, getPixelAt(src->context(), 8, 15));
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 9, 15));
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Our red square should be 25% red over the top of those two.
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color redwhite(0xFFdfbfbf);
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color redgray(0xFF9f8080);
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 0, 1));
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redwhite, getPixelAt(src->context(), 1, 1));
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redwhite, getPixelAt(src->context(), 6, 1));
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redgray, getPixelAt(src->context(), 7, 1));
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redgray, getPixelAt(src->context(), 8, 1));
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redwhite, getPixelAt(src->context(), 9, 1));
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redwhite, getPixelAt(src->context(), 14, 1));
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 15, 1));
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Complete the 50% transparent layer.
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, DISABLED_TranslateScaleOpaqueCompositeLayer)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
499a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The background is white on top with red on bottom.
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color white(0xFFFFFFFF);
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect topRect(0, 0, 16, 8);
5045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(topRect, white);
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color red(0xFFFF0000);
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect bottomRect(0, 8, 16, 8);
5075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(bottomRect, red);
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Translate left by one pixel.
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform left;
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    left.translate(-1, 0);
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Scale by 2x.
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform scale;
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    scale.scale(2.0);
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->concatCTM(scale);
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Then translate up by one pixel (which will actually be 2 due to scaling).
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform up;
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    up.translate(0, -1);
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->concatCTM(up);
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Now draw 50% red square.
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Create a transparency helper inset one pixel in the buffer. The
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // coordinates are before transforming into this space, and maps to
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // IntRect(1, 1, 14, 14).
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, -15, 14, 14));
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Fill with red.
5375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(helper.drawRect(), Color(0x7f7f0000));
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTopLayerAlphaChannel(helper.context());
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Tests scale mode with no additional copy.
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, Scale)
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Create an opaque white buffer.
547a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect fullBuffer(0, 0, 16, 16);
5495267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(fullBuffer, Color::white);
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Scale by 2x.
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform scale;
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    scale.scale(2.0);
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->concatCTM(scale);
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Start drawing a rectangle from 1->4. This should get scaled to 2->8.
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::NoLayer,
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::ScaleTransform,
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 3, 3));
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The context should now have the identity transform and the returned
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // rect should be scaled.
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_TRUE(helper.context()->getCTM().isIdentity());
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_EQ(2, helper.drawRect().x());
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_EQ(2, helper.drawRect().y());
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_EQ(8, helper.drawRect().maxX());
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EXPECT_EQ(8, helper.drawRect().maxY());
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Set the pixel at (2, 2) to be transparent. This should be fixed when
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // the helper goes out of scope. We don't want to call
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // clearTopLayerAlphaChannel because that will actually clear the whole
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // canvas (since we have no extra layer!).
57781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)        SkBitmap& bitmap = const_cast<SkBitmap&>(helper.context()->layerBitmap());
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *bitmap.getAddr32(2, 2) &= 0x00FFFFFF;
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Check the pixel we previously made transparent, it should have gotten
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // fixed back up to white.
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The current version doesn't fixup transparency when there is no layer.
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This seems not to be necessary, so we don't bother, but if it becomes
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // necessary, this line should be uncommented.
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // EXPECT_EQ(Color(Color::white), getPixelAt(src->context(), 2, 2));
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Tests scale mode with an additional copy for transparency. This will happen
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// if we have a scaled textbox, for example. WebKit will create a new
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// transparency layer, draw the text field, then draw the text into it, then
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// composite this down with an opacity.
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, ScaleTransparency)
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Create an opaque white buffer.
600a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect fullBuffer(0, 0, 16, 16);
6025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(fullBuffer, Color::white);
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make another layer (which duplicates how WebKit will make this). We fill
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // the top half with red, and have the layer be 50% opaque.
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->beginTransparencyLayer(0.5);
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect topHalf(0, 0, 16, 8);
6085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    src->context()->fillRect(topHalf, Color(0xFFFF0000));
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Scale by 2x.
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->save();
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform scale;
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    scale.scale(2.0);
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->concatCTM(scale);
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make a layer inset two pixels (because of scaling, this is 2->14). And
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // will it with 50% black.
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::OpaqueCompositeLayer,
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::ScaleTransform,
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(1, 1, 6, 6));
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(helper.drawRect(), Color(0x7f000000));
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTopLayerAlphaChannel(helper.context());
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Finish the layer.
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    src->context()->restore();
632c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    src->context()->endLayer();
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color redBackground(0xFFFF8080); // 50% red composited on white.
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redBackground, getPixelAt(src->context(), 0, 0));
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(redBackground, getPixelAt(src->context(), 1, 1));
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Top half (minus two pixel border) should be 50% gray atop opaque
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // red = 0xFF804141. Then that's composited with 50% transparency on solid
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // white = 0xFFC0A1A1.
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color darkRed(0xFFBF8080);
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(darkRed, getPixelAt(src->context(), 2, 2));
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(darkRed, getPixelAt(src->context(), 7, 7));
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Bottom half (minus a two pixel border) should be a layer with 5% gray
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // with another 50% opacity composited atop white.
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color darkWhite(0xFFBFBFBF);
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(darkWhite, getPixelAt(src->context(), 8, 8));
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(darkWhite, getPixelAt(src->context(), 13, 13));
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color white(0xFFFFFFFF); // Background in the lower-right.
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 14, 14));
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(white, getPixelAt(src->context(), 15, 15));
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TEST(TransparencyWin, Text)
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
658a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBuffer> src(ImageBuffer::create(IntSize(16, 16)));
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Our text should end up 50% transparent blue-green.
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color fullResult(0x80008080);
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        TransparencyWin helper;
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.init(src->context(),
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::TextComposite,
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    TransparencyWin::KeepTransform,
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    IntRect(0, 0, 16, 16));
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.setTextCompositeColor(fullResult);
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Write several different squares to simulate ClearType. These should
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // all reduce to 2/3 coverage.
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect pixel(0, 0, 1, 1);
6745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFFFF0000);
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pixel.move(1.0f, 0.0f);
6765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFF00FF00);
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pixel.move(1.0f, 0.0f);
6785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFF0000FF);
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pixel.move(1.0f, 0.0f);
6805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFF008080);
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pixel.move(1.0f, 0.0f);
6825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFF800080);
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pixel.move(1.0f, 0.0f);
6845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFF808000);
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Try one with 100% coverage (opaque black).
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        pixel.move(1.0f, 0.0f);
6885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        helper.context()->fillRect(pixel, 0xFF000000);
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Now mess with the alpha channel.
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        clearTopLayerAlphaChannel(helper.context());
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        helper.composite();
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Color oneThirdResult(0x55005555); // = fullResult * 2 / 3
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 0, 0));
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 1, 0));
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 2, 0));
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 3, 0));
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 4, 0));
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(oneThirdResult, getPixelAt(src->context(), 5, 0));
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(fullResult, getPixelAt(src->context(), 6, 0));
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPECT_EQ(Color::transparent, getPixelAt(src->context(), 7, 0));
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
707