10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch/* 20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Apple, Inc. All rights reserved. 30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Redistribution and use in source and binary forms, with or without 50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * modification, are permitted provided that the following conditions 60bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * are met: 70bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 80bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 1. Redistributions of source code must retain the above copyright 90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * notice, this list of conditions and the following disclaimer. 100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright 110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * notice, this list of conditions and the following disclaimer in the 120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * documentation and/or other materials provided with the distribution. 130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * its contributors may be used to endorse or promote products derived 150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * from this software without specific prior written permission. 160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch */ 280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "config.h" 30e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "PixelDumpSupport.h" 31e14391e94c850b8bd03680c23b38978db68687a8John Reck 322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "CyclicRedundancyCheck.h" 330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "DumpRenderTree.h" 340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "LayoutTestController.h" 35e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include <cstdio> 360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <wtf/Assertions.h> 370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <wtf/RefPtr.h> 382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <wtf/Vector.h> 390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if USE(CG) 410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "PixelDumpSupportCG.h" 422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#elif USE(CAIRO) 430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "PixelDumpSupportCairo.h" 440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash) 470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 48967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch RefPtr<BitmapContext> context; 49967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#if PLATFORM(MAC) 50967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch if (gLayoutTestController->isPrinting()) 51967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch context = createPagedBitmapContext(); 52967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch else 53967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#endif 54967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch context = createBitmapContextFromWebView(gLayoutTestController->testOnscreen(), gLayoutTestController->testRepaint(), gLayoutTestController->testRepaintSweepHorizontally(), gLayoutTestController->dumpSelectionRect()); 550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(context); 560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Compute the hash of the bitmap context pixels 580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch char actualHash[33]; 590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch computeMD5HashStringForBitmapContext(context.get(), actualHash); 600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch printf("\nActualHash: %s\n", actualHash); 610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Check the computed hash against the expected one and dump image on mismatch 630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch bool dumpImage = true; 640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (expectedHash.length() > 0) { 650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT(expectedHash.length() == 32); 660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch printf("\nExpectedHash: %s\n", expectedHash.c_str()); 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (expectedHash == actualHash) // FIXME: do case insensitive compare 700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch dumpImage = false; 710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (dumpImage) 742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch dumpBitmap(context.get(), actualHash); 750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void appendIntToVector(unsigned number, Vector<unsigned char>& vector) 780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch size_t offset = vector.size(); 802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch vector.grow(offset + 4); 812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch vector[offset] = ((number >> 24) & 0xff); 822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch vector[offset + 1] = ((number >> 16) & 0xff); 832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch vector[offset + 2] = ((number >> 8) & 0xff); 842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch vector[offset + 3] = (number & 0xff); 852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic void convertChecksumToPNGComment(const char* checksum, Vector<unsigned char>& bytesToAdd) 882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch // Chunks of PNG files are <length>, <type>, <data>, <crc>. 902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static const char textCommentPrefix[] = "\x00\x00\x00\x29tEXtchecksum\x00"; 912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static const size_t prefixLength = sizeof(textCommentPrefix) - 1; // The -1 is for the null at the end of the char[]. 922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch static const size_t checksumLength = 32; 932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bytesToAdd.append(textCommentPrefix, prefixLength); 952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch bytesToAdd.append(checksum, checksumLength); 962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Vector<unsigned char> dataToCrc; 982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch dataToCrc.append(textCommentPrefix + 4, prefixLength - 4); // Don't include the chunk length in the crc. 992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch dataToCrc.append(checksum, checksumLength); 1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch unsigned crc32 = computeCrc(dataToCrc); 1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch appendIntToVector(crc32, bytesToAdd); 1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochstatic size_t offsetAfterIHDRChunk(const unsigned char* data, const size_t dataLength) 1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch const int pngHeaderLength = 8; 1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch const int pngIHDRChunkLength = 25; // chunk length + "IHDR" + 13 bytes of data + checksum 1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch return pngHeaderLength + pngIHDRChunkLength; 1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch} 1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid printPNG(const unsigned char* data, const size_t dataLength, const char* checksum) 1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{ 1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch Vector<unsigned char> bytesToAdd; 1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch convertChecksumToPNGComment(checksum, bytesToAdd); 1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch printf("Content-Type: %s\n", "image/png"); 1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch printf("Content-Length: %lu\n", static_cast<unsigned long>(dataLength + bytesToAdd.size())); 1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch size_t insertOffset = offsetAfterIHDRChunk(data, dataLength); 1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fwrite(data, 1, insertOffset, stdout); 1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fwrite(bytesToAdd.data(), 1, bytesToAdd.size(), stdout); 1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch const size_t bytesToWriteInOneChunk = 1 << 15; 1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch data += insertOffset; 1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch size_t dataRemainingToWrite = dataLength - insertOffset; 1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (dataRemainingToWrite) { 1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t bytesToWriteInThisChunk = std::min(dataRemainingToWrite, bytesToWriteInOneChunk); 1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, stdout); 1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (bytesWritten != bytesToWriteInThisChunk) 1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch break; 1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch dataRemainingToWrite -= bytesWritten; 1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch data += bytesWritten; 1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 137