Commit 39665f62 authored by tony@chromium.org's avatar tony@chromium.org

2011-04-07 Tony Chang <tony@chromium.org>

        Reviewed by Eric Seidel.

        update DRT to embed checksums in png files
        https://bugs.webkit.org/show_bug.cgi?id=57871

        We insert the bytes for the comment in printPNG rather than at encode
        time because each platform does its own PNG encoding (either using CG
        or cairo).  Putting this in pringPNG avoids having to duplicate this
        code, although it's not as clean as doing it at encoding time.

        We insert the comment right after the IHDR chunk of the PNG.

        * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
        * DumpRenderTree/CyclicRedundancyCheck.cpp: Added.
        (makeCrcTable): Ported from LayoutTests/fast/canvas/webgl/resources/pnglib.js
        (computeCrc): Ported from LayoutTests/fast/canvas/webgl/resources/pnglib.js
        * DumpRenderTree/CyclicRedundancyCheck.h: Added.
        * DumpRenderTree/PixelDumpSupport.cpp:
        (dumpWebViewAsPixelsAndCompareWithExpected):
        (convertChecksumToPNGComment): Generate the bytes to insert.
        (printPNG): Insert the png comment before the first IDAT section.
        * DumpRenderTree/PixelDumpSupport.h:
        * DumpRenderTree/cairo/PixelDumpSupportCairo.cpp:
        (printPNG):
        (dumpBitmap):
        * DumpRenderTree/cg/PixelDumpSupportCG.cpp:
        (printPNG):
        (dumpBitmap):
        * DumpRenderTree/win/DumpRenderTree.vcproj:
        * GNUmakefile.am:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@83219 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9cf9ca28
2011-04-07 Tony Chang <tony@chromium.org>
Reviewed by Eric Seidel.
update DRT to embed checksums in png files
https://bugs.webkit.org/show_bug.cgi?id=57871
We insert the bytes for the comment in printPNG rather than at encode
time because each platform does its own PNG encoding (either using CG
or cairo). Putting this in pringPNG avoids having to duplicate this
code, although it's not as clean as doing it at encoding time.
We insert the comment right after the IHDR chunk of the PNG.
* DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
* DumpRenderTree/CyclicRedundancyCheck.cpp: Added.
(makeCrcTable): Ported from LayoutTests/fast/canvas/webgl/resources/pnglib.js
(computeCrc): Ported from LayoutTests/fast/canvas/webgl/resources/pnglib.js
* DumpRenderTree/CyclicRedundancyCheck.h: Added.
* DumpRenderTree/PixelDumpSupport.cpp:
(dumpWebViewAsPixelsAndCompareWithExpected):
(convertChecksumToPNGComment): Generate the bytes to insert.
(printPNG): Insert the png comment before the first IDAT section.
* DumpRenderTree/PixelDumpSupport.h:
* DumpRenderTree/cairo/PixelDumpSupportCairo.cpp:
(printPNG):
(dumpBitmap):
* DumpRenderTree/cg/PixelDumpSupportCG.cpp:
(printPNG):
(dumpBitmap):
* DumpRenderTree/win/DumpRenderTree.vcproj:
* GNUmakefile.am:
2011-04-07 Jeff Miller <jeffm@apple.com>
Reviewed by Adam Roben.
......
/*
* Copyright (C) 2010, Robert Eisele <robert@xarg.org> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "CyclicRedundancyCheck.h"
#include <wtf/Vector.h>
static void makeCrcTable(unsigned long crcTable[256])
{
for (unsigned long i = 0; i < 256; i++) {
unsigned long c = i;
for (int k = 0; k < 8; k++) {
if (c & 1)
c = -306674912 ^ ((c >> 1) & 0x7fffffff);
else
c = c >> 1;
}
crcTable[i] = c;
}
}
unsigned long computeCrc(const Vector<unsigned char>& buffer)
{
static unsigned long crcTable[256];
static bool crcTableComputed = false;
if (!crcTableComputed) {
makeCrcTable(crcTable);
crcTableComputed = true;
}
unsigned long crc = 0xffffffffL;
for (size_t i = 0; i < buffer.size(); ++i)
crc = crcTable[(crc ^ buffer[i]) & 0xff] ^ ((crc >> 8) & 0x00ffffffL);
return crc ^ 0xffffffffL;
}
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CyclicRedundancyCheck_h
#define CyclicRedundancyCheck_h
#include <wtf/Vector.h>
unsigned long computeCrc(const Vector<unsigned char>&);
#endif
......@@ -59,6 +59,8 @@
4437730F125CBC4D00AAE02C /* WebArchiveDumpSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 44A997820FCDE86400580F10 /* WebArchiveDumpSupport.h */; };
5185F6B210714E07007AA393 /* HistoryDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5185F69F10714A57007AA393 /* HistoryDelegate.mm */; };
5185F6B310714E12007AA393 /* HistoryDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5185F69E10714A57007AA393 /* HistoryDelegate.h */; };
53CBB832134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53CBB830134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp */; };
53CBB833134E42F3001CE6A4 /* CyclicRedundancyCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CBB831134E42F3001CE6A4 /* CyclicRedundancyCheck.h */; };
5DB9AC970F722C3600684641 /* AHEM____.TTF in Copy Font Files */ = {isa = PBXBuildFile; fileRef = AA7F10C20CB3C1030003BDC9 /* AHEM____.TTF */; };
5DB9AC980F722C3600684641 /* WebKitWeightWatcher100.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 375F09710DAC3CB600C8B4E5 /* WebKitWeightWatcher100.ttf */; };
5DB9AC990F722C3600684641 /* WebKitWeightWatcher200.ttf in Copy Font Files */ = {isa = PBXBuildFile; fileRef = 375F09720DAC3CB600C8B4E5 /* WebKitWeightWatcher200.ttf */; };
......@@ -243,6 +245,8 @@
44A997830FCDE86400580F10 /* WebArchiveDumpSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebArchiveDumpSupport.cpp; path = cf/WebArchiveDumpSupport.cpp; sourceTree = "<group>"; };
5185F69E10714A57007AA393 /* HistoryDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryDelegate.h; path = mac/HistoryDelegate.h; sourceTree = "<group>"; };
5185F69F10714A57007AA393 /* HistoryDelegate.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; name = HistoryDelegate.mm; path = mac/HistoryDelegate.mm; sourceTree = "<group>"; };
53CBB830134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CyclicRedundancyCheck.cpp; sourceTree = "<group>"; };
53CBB831134E42F3001CE6A4 /* CyclicRedundancyCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CyclicRedundancyCheck.h; sourceTree = "<group>"; };
8465E2C60FFA8DF2003B8342 /* PixelDumpSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PixelDumpSupport.cpp; sourceTree = "<group>"; };
9335435F03D75502008635CE /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = WebKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
933BF5A90F93FA5C000F0441 /* PlainTextController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlainTextController.h; path = mac/PlainTextController.h; sourceTree = "<group>"; };
......@@ -581,6 +585,8 @@
BCB284870CFA81ED007E533E /* PixelDump */ = {
isa = PBXGroup;
children = (
53CBB830134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp */,
53CBB831134E42F3001CE6A4 /* CyclicRedundancyCheck.h */,
BCB284F30CFA84F2007E533E /* ImageDiffCG.cpp */,
8465E2C60FFA8DF2003B8342 /* PixelDumpSupport.cpp */,
BCB2848A0CFA820F007E533E /* PixelDumpSupport.h */,
......@@ -611,6 +617,7 @@
BC0E24E00E2D9451001B6BC2 /* AccessibilityUIElement.h in Headers */,
BCA18B380C9B021900114369 /* AppleScriptController.h in Headers */,
A8B91BFF0CF522B4008F91FF /* CheckedMalloc.h in Headers */,
53CBB833134E42F3001CE6A4 /* CyclicRedundancyCheck.h in Headers */,
BCA18B7A0C9B08F100114369 /* DumpRenderTreeDraggingInfo.h in Headers */,
A8D79CEA0FC28B2C004AC8FE /* DumpRenderTreeFileDraggingSource.h in Headers */,
BCA18C0B0C9B59EF00114369 /* DumpRenderTreeMac.h in Headers */,
......@@ -799,6 +806,7 @@
BC0E26150E2DA4C6001B6BC2 /* AccessibilityUIElementMac.mm in Sources */,
BCA18B390C9B021900114369 /* AppleScriptController.m in Sources */,
A8B91BFD0CF522B4008F91FF /* CheckedMalloc.cpp in Sources */,
53CBB832134E42F3001CE6A4 /* CyclicRedundancyCheck.cpp in Sources */,
BCA18C470C9B5B9400114369 /* DumpRenderTree.mm in Sources */,
BCA18B7B0C9B08F100114369 /* DumpRenderTreeDraggingInfo.mm in Sources */,
A8D79CEB0FC28B2C004AC8FE /* DumpRenderTreeFileDraggingSource.m in Sources */,
......
......@@ -29,11 +29,13 @@
#include "config.h"
#include "PixelDumpSupport.h"
#include "CyclicRedundancyCheck.h"
#include "DumpRenderTree.h"
#include "LayoutTestController.h"
#include <cstdio>
#include <wtf/Assertions.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
#if PLATFORM(CG)
#include "PixelDumpSupportCG.h"
......@@ -69,16 +71,60 @@ void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash)
}
if (dumpImage)
dumpBitmap(context.get());
dumpBitmap(context.get(), actualHash);
}
void printPNG(const unsigned char* data, const size_t dataLength)
static void appendIntToVector(int number, Vector<unsigned char>& vector)
{
size_t offset = vector.size();
vector.grow(offset + 4);
vector[offset] = ((number >> 24) & 0xff);
vector[offset + 1] = ((number >> 16) & 0xff);
vector[offset + 2] = ((number >> 8) & 0xff);
vector[offset + 3] = (number & 0xff);
}
static void convertChecksumToPNGComment(const char* checksum, Vector<unsigned char>& bytesToAdd)
{
// Chunks of PNG files are <length>, <type>, <data>, <crc>.
static const char textCommentPrefix[] = "\x00\x00\x00\x29tEXtchecksum\x00";
static const size_t prefixLength = sizeof(textCommentPrefix) - 1; // The -1 is for the null at the end of the char[].
static const size_t checksumLength = 32;
bytesToAdd.append(textCommentPrefix, prefixLength);
bytesToAdd.append(checksum, checksumLength);
Vector<unsigned char> dataToCrc;
dataToCrc.append(textCommentPrefix + 4, prefixLength - 4); // Don't include the chunk length in the crc.
dataToCrc.append(checksum, checksumLength);
unsigned long crc32 = computeCrc(dataToCrc);
appendIntToVector(crc32, bytesToAdd);
}
static size_t offsetAfterIHDRChunk(const unsigned char* data, const size_t dataLength)
{
const int pngHeaderLength = 8;
const int pngIHDRChunkLength = 25; // chunk length + "IHDR" + 13 bytes of data + checksum
return pngHeaderLength + pngIHDRChunkLength;
}
void printPNG(const unsigned char* data, const size_t dataLength, const char* checksum)
{
Vector<unsigned char> bytesToAdd;
convertChecksumToPNGComment(checksum, bytesToAdd);
printf("Content-Type: %s\n", "image/png");
printf("Content-Length: %lu\n", static_cast<unsigned long>(dataLength));
printf("Content-Length: %lu\n", static_cast<unsigned long>(dataLength + bytesToAdd.size()));
size_t insertOffset = offsetAfterIHDRChunk(data, dataLength);
fwrite(data, 1, insertOffset, stdout);
fwrite(bytesToAdd.data(), 1, bytesToAdd.size(), stdout);
const size_t bytesToWriteInOneChunk = 1 << 15;
size_t dataRemainingToWrite = dataLength;
data += insertOffset;
size_t dataRemainingToWrite = dataLength - insertOffset;
while (dataRemainingToWrite) {
size_t bytesToWriteInThisChunk = std::min(dataRemainingToWrite, bytesToWriteInOneChunk);
size_t bytesWritten = fwrite(data, 1, bytesToWriteInThisChunk, stdout);
......
......@@ -38,9 +38,9 @@ class BitmapContext;
void computeMD5HashStringForBitmapContext(BitmapContext*, char hashString[33]);
PassRefPtr<BitmapContext> createPagedBitmapContext();
PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool onscreen, bool incrementalRepaint, bool sweepHorizontally, bool drawSelectionRect);
void dumpBitmap(BitmapContext*);
void dumpBitmap(BitmapContext*, const char* checksum);
void dumpWebViewAsPixelsAndCompareWithExpected(const std::string& expectedHash);
void printPNG(const unsigned char* data, const size_t dataLength);
void printPNG(const unsigned char* data, const size_t dataLength, const char* checksum);
#if PLATFORM(MAC)
......
......@@ -49,7 +49,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un
return CAIRO_STATUS_SUCCESS;
}
static void printPNG(cairo_surface_t* image)
static void printPNG(cairo_surface_t* image, const char* checksum)
{
Vector<unsigned char> pixelData;
// Only PNG output is supported for now.
......@@ -58,7 +58,7 @@ static void printPNG(cairo_surface_t* image)
const size_t dataLength = pixelData.size();
const unsigned char* data = pixelData.data();
printPNG(data, dataLength);
printPNG(data, dataLength, checksum);
}
void computeMD5HashStringForBitmapContext(BitmapContext* context, char hashString[33])
......@@ -86,8 +86,8 @@ void computeMD5HashStringForBitmapContext(BitmapContext* context, char hashStrin
hash[8], hash[9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);
}
void dumpBitmap(BitmapContext* context)
void dumpBitmap(BitmapContext* context, const char* checksum)
{
cairo_surface_t* surface = cairo_get_target(context->cairoContext());
printPNG(surface);
printPNG(surface, checksum);
}
......@@ -55,7 +55,7 @@ using namespace std;
static const CFStringRef kUTTypePNG = CFSTR("public.png");
#endif
static void printPNG(CGImageRef image)
static void printPNG(CGImageRef image, const char* checksum)
{
RetainPtr<CFMutableDataRef> imageData(AdoptCF, CFDataCreateMutable(0, 0));
RetainPtr<CGImageDestinationRef> imageDest(AdoptCF, CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
......@@ -65,7 +65,7 @@ static void printPNG(CGImageRef image)
const UInt8* data = CFDataGetBytePtr(imageData.get());
CFIndex dataLength = CFDataGetLength(imageData.get());
printPNG(static_cast<const unsigned char*>(data), static_cast<size_t>(dataLength));
printPNG(static_cast<const unsigned char*>(data), static_cast<size_t>(dataLength), checksum);
}
void computeMD5HashStringForBitmapContext(BitmapContext* context, char hashString[33])
......@@ -106,8 +106,8 @@ void computeMD5HashStringForBitmapContext(BitmapContext* context, char hashStrin
snprintf(hashString, 33, "%s%02x", hashString, hash[i]);
}
void dumpBitmap(BitmapContext* context)
void dumpBitmap(BitmapContext* context, const char* checksum)
{
RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context->cgContext()));
printPNG(image.get());
printPNG(image.get(), checksum);
}
......@@ -514,6 +514,14 @@
RelativePath=".\AccessibilityUIElementWin.cpp"
>
</File>
<File
RelativePath="..\CyclicRedundancyCheck.cpp"
>
</File>
<File
RelativePath="..\CyclicRedundancyCheck.h"
>
</File>
<File
RelativePath=".\DraggingInfo.h"
>
......
......@@ -56,6 +56,8 @@ Programs_DumpRenderTree_SOURCES = \
Tools/DumpRenderTree/AccessibilityTextMarker.h \
Tools/DumpRenderTree/AccessibilityUIElement.cpp \
Tools/DumpRenderTree/AccessibilityUIElement.h \
Tools/DumpRenderTree/CyclicRedundancyCheck.cpp \
Tools/DumpRenderTree/CyclicRedundancyCheck.h \
Tools/DumpRenderTree/GCController.cpp \
Tools/DumpRenderTree/GCController.h \
Tools/DumpRenderTree/JavaScriptThreading.h \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment