diff options
Diffstat (limited to 'WebCore/platform/graphics')
46 files changed, 1342 insertions, 160 deletions
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h index b265121..2b23576 100644 --- a/WebCore/platform/graphics/FloatRect.h +++ b/WebCore/platform/graphics/FloatRect.h @@ -143,6 +143,7 @@ public: #if PLATFORM(QT) FloatRect(const QRectF&); operator QRectF() const; + FloatRect normalized() const; #endif #if PLATFORM(WX) && USE(WXGC) diff --git a/WebCore/platform/graphics/GlyphMetricsMap.h b/WebCore/platform/graphics/GlyphMetricsMap.h index 5e13afe..82e234b 100644 --- a/WebCore/platform/graphics/GlyphMetricsMap.h +++ b/WebCore/platform/graphics/GlyphMetricsMap.h @@ -29,6 +29,7 @@ #ifndef GlyphMetricsMap_h #define GlyphMetricsMap_h +#include <wtf/FixedArray.h> #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/unicode/Unicode.h> @@ -61,7 +62,7 @@ public: private: struct GlyphMetricsPage { static const size_t size = 256; // Usually covers Latin-1 in a single page. - T m_metrics[size]; + FixedArray<T, size> m_metrics; T metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; } void setMetricsForGlyph(Glyph glyph, const T& metrics) diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index b526e51..c4ac01b 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -94,7 +94,7 @@ namespace WebCore { void getColor(float value, float* r, float* g, float* b, float* a) const; bool isRadial() const { return m_radial; } - bool isZeroSize() const { return m_p0.x() == m_p1.x() && m_p0.y() == m_p1.y(); } + bool isZeroSize() const { return m_p0.x() == m_p1.x() && m_p0.y() == m_p1.y() && (!m_radial || m_r0 == m_r1); } #if OS(WINCE) && !PLATFORM(QT) const FloatPoint& p0() const { return m_p0; } diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index 8bcfc06..457368b 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -274,6 +274,7 @@ namespace WebCore { void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight); void clipPath(WindRule); void clipToImageBuffer(const FloatRect&, const ImageBuffer*); + void clipConvexPolygon(size_t numPoints, const FloatPoint*); int textDrawingMode(); void setTextDrawingMode(int); diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index dc70734..79f6ecf 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -30,6 +30,7 @@ #include "GraphicsContext3D.h" +#include "ArrayBufferView.h" #include "Image.h" #include "ImageData.h" @@ -118,6 +119,7 @@ bool GraphicsContext3D::extractImageData(ImageData* imageData, kSourceFormatRGBA8, width, height, + 0, format, type, premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing, @@ -138,6 +140,72 @@ bool GraphicsContext3D::extractImageData(ImageData* imageData, return true; } +bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int height, + unsigned int format, unsigned int type, + unsigned int unpackAlignment, + bool flipY, bool premultiplyAlpha, + ArrayBufferView* pixels, + Vector<uint8_t>& data) +{ + // Assumes format, type, etc. have already been validated. + SourceDataFormat sourceDataFormat = kSourceFormatRGBA8; + switch (type) { + case UNSIGNED_BYTE: + switch (format) { + case RGBA: + sourceDataFormat = kSourceFormatRGBA8; + break; + case RGB: + sourceDataFormat = kSourceFormatRGB8; + break; + case ALPHA: + sourceDataFormat = kSourceFormatA8; + break; + case LUMINANCE: + sourceDataFormat = kSourceFormatR8; + break; + case LUMINANCE_ALPHA: + sourceDataFormat = kSourceFormatRA8; + break; + default: + ASSERT_NOT_REACHED(); + } + break; + case UNSIGNED_SHORT_5_5_5_1: + sourceDataFormat = kSourceFormatRGBA5551; + break; + case UNSIGNED_SHORT_4_4_4_4: + sourceDataFormat = kSourceFormatRGBA4444; + break; + case UNSIGNED_SHORT_5_6_5: + sourceDataFormat = kSourceFormatRGB565; + break; + default: + ASSERT_NOT_REACHED(); + } + + // Resize the output buffer. + unsigned long componentsPerPixel, bytesPerComponent; + if (!computeFormatAndTypeParameters(format, type, + &componentsPerPixel, + &bytesPerComponent)) + return false; + unsigned long bytesPerPixel = componentsPerPixel * bytesPerComponent; + data.resize(width * height * bytesPerPixel); + + if (!packPixels(static_cast<uint8_t*>(pixels->baseAddress()), + sourceDataFormat, + width, height, unpackAlignment, + format, type, + (premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing), + data.data())) + return false; + // The pixel data is now tightly packed. + if (flipY) + flipVertically(data.data(), width, height, bytesPerPixel, 1); + return true; +} + void GraphicsContext3D::flipVertically(void* imageData, unsigned int width, unsigned int height, @@ -150,7 +218,7 @@ void GraphicsContext3D::flipVertically(void* imageData, unsigned int totalRowBytes = validRowBytes; unsigned int remainder = validRowBytes % unpackAlignment; if (remainder) - totalRowBytes += remainder; + totalRowBytes += (unpackAlignment - remainder); uint8_t* tempRow = new uint8_t[validRowBytes]; uint8_t* data = static_cast<uint8_t*>(imageData); for (unsigned i = 0; i < height / 2; i++) { @@ -171,6 +239,14 @@ namespace { //---------------------------------------------------------------------- // Pixel unpacking routines. +void unpackRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[1]; + destination[2] = source[2]; + destination[3] = source[3]; +} + void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination) { destination[0] = source[0]; @@ -187,6 +263,67 @@ void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination) destination[3] = source[3]; } +void unpackRGBA5551ToRGBA8(const uint16_t* source, uint8_t* destination) +{ + uint16_t packedValue = source[0]; + uint8_t r = packedValue >> 11; + uint8_t g = (packedValue >> 6) & 0x1F; + uint8_t b = (packedValue >> 1) & 0x1F; + destination[0] = (r << 3) | (r & 0x7); + destination[1] = (g << 3) | (g & 0x7); + destination[2] = (b << 3) | (b & 0x7); + destination[3] = (packedValue & 0x1) ? 0xFF : 0x0; +} + +void unpackRGBA4444ToRGBA8(const uint16_t* source, uint8_t* destination) +{ + uint16_t packedValue = source[0]; + uint8_t r = packedValue >> 12; + uint8_t g = (packedValue >> 8) & 0x0F; + uint8_t b = (packedValue >> 4) & 0x0F; + uint8_t a = packedValue & 0x0F; + destination[0] = r << 4 | r; + destination[1] = g << 4 | g; + destination[2] = b << 4 | b; + destination[3] = a << 4 | a; +} + +void unpackRGB565ToRGBA8(const uint16_t* source, uint8_t* destination) +{ + uint16_t packedValue = source[0]; + uint8_t r = packedValue >> 11; + uint8_t g = (packedValue >> 5) & 0x3F; + uint8_t b = packedValue & 0x1F; + destination[0] = (r << 3) | (r & 0x7); + destination[1] = (g << 2) | (g & 0x3); + destination[2] = (b << 3) | (b & 0x7); + destination[3] = 0xFF; +} + +void unpackR8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[0]; + destination[2] = source[0]; + destination[3] = 0xFF; +} + +void unpackRA8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[0]; + destination[2] = source[0]; + destination[3] = source[1]; +} + +void unpackA8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = 0x0; + destination[1] = 0x0; + destination[2] = 0x0; + destination[3] = source[0]; +} + //---------------------------------------------------------------------- // Pixel packing routines. // @@ -401,51 +538,141 @@ void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* dest } // anonymous namespace // This is used whenever unpacking is necessary; i.e., the source data -// is not in RGBA8 format. +// is not in RGBA8 format, or the unpack alignment specifies that rows +// are not tightly packed. template<typename SourceType, typename DestType, void unpackingFunc(const SourceType*, uint8_t*), void packingFunc(const uint8_t*, DestType*)> static void doUnpackingAndPacking(const SourceType* sourceData, - unsigned int numElements, + unsigned int width, + unsigned int height, unsigned int sourceElementsPerPixel, + unsigned int sourceElementsPerRow, DestType* destinationData, unsigned int destinationElementsPerPixel) { - const SourceType* endPointer = sourceData + numElements; - uint8_t temporaryRGBAData[4]; - while (sourceData < endPointer) { - unpackingFunc(sourceData, temporaryRGBAData); - packingFunc(temporaryRGBAData, destinationData); - sourceData += sourceElementsPerPixel; - destinationData += destinationElementsPerPixel; + if (!sourceElementsPerRow) { + unsigned int numElements = width * height * sourceElementsPerPixel; + const SourceType* endPointer = sourceData + numElements; + uint8_t temporaryRGBAData[4]; + while (sourceData < endPointer) { + unpackingFunc(sourceData, temporaryRGBAData); + packingFunc(temporaryRGBAData, destinationData); + sourceData += sourceElementsPerPixel; + destinationData += destinationElementsPerPixel; + } + } else { + uint8_t temporaryRGBAData[4]; + for (unsigned int y = 0; y < height; ++y) { + const SourceType* currentSource = sourceData; + for (unsigned int x = 0; x < width; ++x) { + unpackingFunc(currentSource, temporaryRGBAData); + packingFunc(temporaryRGBAData, destinationData); + currentSource += sourceElementsPerPixel; + destinationData += destinationElementsPerPixel; + } + sourceData += sourceElementsPerRow; + } + } +} + +template<typename SourceType> +static void computeIncrementParameters(unsigned int width, + unsigned int bytesPerPixel, + unsigned int unpackAlignment, + unsigned int* sourceElementsPerPixel, + unsigned int* sourceElementsPerRow) +{ + unsigned int elementSizeInBytes = sizeof(SourceType); + ASSERT(elementSizeInBytes <= bytesPerPixel); + unsigned int validRowBytes = width * bytesPerPixel; + unsigned int totalRowBytes = validRowBytes; + if (unpackAlignment) { + unsigned int remainder = validRowBytes % unpackAlignment; + if (remainder) + totalRowBytes += (unpackAlignment - remainder); } + *sourceElementsPerPixel = bytesPerPixel / elementSizeInBytes; + if (validRowBytes == totalRowBytes) + *sourceElementsPerRow = 0; + else + *sourceElementsPerRow = totalRowBytes / elementSizeInBytes; } -// This handles all conversions with a faster path for RGBA8 source data. -template<typename SourceType, typename DestType, void packingFunc(const SourceType*, DestType*)> -static void doPacking(const SourceType* sourceData, +// This handles all conversions with a faster path for tightly packed RGBA8 source data. +template<typename DestType, void packingFunc(const uint8_t*, DestType*)> +static void doPacking(const void* sourceData, GraphicsContext3D::SourceDataFormat sourceDataFormat, - unsigned int numElements, - unsigned int sourceElementsPerPixel, + unsigned int width, + unsigned int height, + unsigned int sourceUnpackAlignment, DestType* destinationData, unsigned int destinationElementsPerPixel) { switch (sourceDataFormat) { case GraphicsContext3D::kSourceFormatRGBA8: { - const SourceType* endPointer = sourceData + numElements; - while (sourceData < endPointer) { - packingFunc(sourceData, destinationData); - sourceData += sourceElementsPerPixel; - destinationData += destinationElementsPerPixel; + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + if (!sourceElementsPerRow) { + const uint8_t* source = static_cast<const uint8_t*>(sourceData); + unsigned int numElements = width * height * 4; + const uint8_t* endPointer = source + numElements; + while (source < endPointer) { + packingFunc(source, destinationData); + source += sourceElementsPerPixel; + destinationData += destinationElementsPerPixel; + } + } else { + doUnpackingAndPacking<uint8_t, DestType, unpackRGBA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); } break; } case GraphicsContext3D::kSourceFormatRGB8: { - doUnpackingAndPacking<SourceType, DestType, unpackRGB8ToRGBA8, packingFunc>(sourceData, numElements, sourceElementsPerPixel, destinationData, destinationElementsPerPixel); + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } case GraphicsContext3D::kSourceFormatBGRA8: { - doUnpackingAndPacking<SourceType, DestType, unpackBGRA8ToRGBA8, packingFunc>(sourceData, numElements, sourceElementsPerPixel, destinationData, destinationElementsPerPixel); + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackBGRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatRGBA5551: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint16_t, DestType, unpackRGBA5551ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatRGBA4444: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint16_t, DestType, unpackRGBA4444ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatRGB565: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint16_t, DestType, unpackRGB565ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatR8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatRA8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatA8: { + unsigned int sourceElementsPerPixel, sourceElementsPerRow; + computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow); + doUnpackingAndPacking<uint8_t, DestType, unpackA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel); break; } } @@ -455,46 +682,45 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, GraphicsContext3D::SourceDataFormat sourceDataFormat, unsigned int width, unsigned int height, + unsigned int sourceUnpackAlignment, unsigned int destinationFormat, unsigned int destinationType, AlphaOp alphaOp, void* destinationData) { - unsigned int sourceElementsPerPixel = 4; - unsigned int numElements = width * height * sourceElementsPerPixel; switch (destinationType) { case UNSIGNED_BYTE: { uint8_t* destination = static_cast<uint8_t*>(destinationData); - if (sourceDataFormat == kSourceFormatRGBA8 && destinationFormat == RGBA && alphaOp == kAlphaDoNothing) { + if (sourceDataFormat == kSourceFormatRGBA8 && destinationFormat == RGBA && sourceUnpackAlignment <= 4 && alphaOp == kAlphaDoNothing) { // No conversion necessary. - memcpy(destinationData, sourceData, numElements); + memcpy(destinationData, sourceData, width * height * 4); break; } switch (destinationFormat) { case RGB: switch (alphaOp) { case kAlphaDoNothing: - doPacking<uint8_t, uint8_t, packRGBA8ToRGB8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 3); + doPacking<uint8_t, packRGBA8ToRGB8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToRGB8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 3); + doPacking<uint8_t, packRGBA8ToRGB8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToRGB8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 3); + doPacking<uint8_t, packRGBA8ToRGB8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3); break; } break; case RGBA: switch (alphaOp) { case kAlphaDoNothing: - ASSERT(sourceDataFormat != kSourceFormatRGBA8); // Handled above with fast case. - doPacking<uint8_t, uint8_t, packRGBA8ToRGBA8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 4); + ASSERT(sourceDataFormat != kSourceFormatRGBA8 || sourceUnpackAlignment > 4); // Handled above with fast case. + doPacking<uint8_t, packRGBA8ToRGBA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToRGBA8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 4); + doPacking<uint8_t, packRGBA8ToRGBA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToRGBA8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 4); + doPacking<uint8_t, packRGBA8ToRGBA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4); break; default: ASSERT_NOT_REACHED(); @@ -504,7 +730,7 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, // From the desktop OpenGL conversion rules (OpenGL 2.1 // specification, Table 3.15), the alpha channel is chosen // from the RGBA data. - doPacking<uint8_t, uint8_t, packRGBA8ToA8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint8_t, packRGBA8ToA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case LUMINANCE: // From the desktop OpenGL conversion rules (OpenGL 2.1 @@ -512,13 +738,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, // from the RGBA data. switch (alphaOp) { case kAlphaDoNothing: - doPacking<uint8_t, uint8_t, packRGBA8ToR8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint8_t, packRGBA8ToR8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToR8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint8_t, packRGBA8ToR8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToR8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint8_t, packRGBA8ToR8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } break; @@ -528,13 +754,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, // are chosen from the RGBA data. switch (alphaOp) { case kAlphaDoNothing: - doPacking<uint8_t, uint8_t, packRGBA8ToRA8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 2); + doPacking<uint8_t, packRGBA8ToRA8>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToRA8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 2); + doPacking<uint8_t, packRGBA8ToRA8Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint8_t, packRGBA8ToRA8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 2); + doPacking<uint8_t, packRGBA8ToRA8Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2); break; } break; @@ -545,13 +771,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, uint16_t* destination = static_cast<uint16_t*>(destinationData); switch (alphaOp) { case kAlphaDoNothing: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort4444>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort4444>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort4444Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort4444Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort4444Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort4444Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } break; @@ -560,13 +786,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, uint16_t* destination = static_cast<uint16_t*>(destinationData); switch (alphaOp) { case kAlphaDoNothing: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort5551>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort5551>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort5551Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort5551Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort5551Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort5551Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } break; @@ -575,13 +801,13 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData, uint16_t* destination = static_cast<uint16_t*>(destinationData); switch (alphaOp) { case kAlphaDoNothing: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort565>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort565>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoPremultiply: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort565Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort565Premultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; case kAlphaDoUnmultiply: - doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort565Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + doPacking<uint16_t, packRGBA8ToUnsignedShort565Unmultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1); break; } break; diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 981459f..882362f 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -436,9 +436,7 @@ namespace WebCore { PlatformGraphicsContext3D platformGraphicsContext3D() const; Platform3DObject platformTexture() const; #if USE(ACCELERATED_COMPOSITING) - // FIXME: Stubbed out for now. Must be implemented to get WebGL working with - // accelerated compositing. - PlatformLayer* platformLayer() const { return 0; } + PlatformLayer* platformLayer() const; #endif #elif PLATFORM(QT) PlatformGraphicsContext3D platformGraphicsContext3D(); @@ -455,7 +453,7 @@ namespace WebCore { #endif void makeContextCurrent(); -#if PLATFORM(MAC) +#if PLATFORM(MAC) || PLATFORM(CHROMIUM) // With multisampling on, blit from multisampleFBO to regular FBO. void prepareTexture(); #endif @@ -500,6 +498,18 @@ namespace WebCore { bool premultiplyAlpha, Vector<uint8_t>& data); + // Helper function which extracts the user-supplied texture + // data, applying the flipY and premultiplyAlpha parameters. + // If the data is not tightly packed according to the passed + // unpackAlignment, the output data will be tightly packed. + // Returns true if successful, false if any error occurred. + bool extractTextureData(unsigned int width, unsigned int height, + unsigned int format, unsigned int type, + unsigned int unpackAlignment, + bool flipY, bool premultiplyAlpha, + ArrayBufferView* pixels, + Vector<uint8_t>& data); + // Flips the given image data vertically, in-place. void flipVertically(void* imageData, unsigned int width, @@ -514,7 +524,13 @@ namespace WebCore { enum SourceDataFormat { kSourceFormatRGBA8, kSourceFormatRGB8, - kSourceFormatBGRA8 + kSourceFormatBGRA8, + kSourceFormatRGBA5551, + kSourceFormatRGBA4444, + kSourceFormatRGB565, + kSourceFormatR8, + kSourceFormatRA8, + kSourceFormatA8 }; //---------------------------------------------------------------------- @@ -573,6 +589,8 @@ namespace WebCore { bool getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo&); bool getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo&); + void getAttachedShaders(WebGLProgram* program, int maxCount, int* count, unsigned int* shaders); + int getAttribLocation(WebGLProgram*, const String& name); void getBooleanv(unsigned long pname, unsigned char* value); @@ -758,12 +776,14 @@ namespace WebCore { // Helper for getImageData which implements packing of pixel // data into the specified OpenGL destination format and type. - // Source data must be in RGBA format with no gaps between - // rows. Destination data will have no gaps between rows. + // A sourceUnpackAlignment of zero indicates that the source + // data is tightly packed. Non-zero values may take a slow path. + // Destination data will have no gaps between rows. bool packPixels(const uint8_t* sourceData, SourceDataFormat sourceDataFormat, unsigned int width, unsigned int height, + unsigned int sourceUnpackAlignment, unsigned int destinationFormat, unsigned int destinationType, AlphaOp alphaOp, diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 4338d89..b5797fd 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -343,8 +343,10 @@ public: virtual float accumulatedOpacity() const; // Some compositing systems may do internal batching to synchronize compositing updates - // with updates drawn into the window. This is a signal to flush any internal batched state. + // with updates drawn into the window. These methods flush internal batched state on this layer + // and descendant layers, and this layer only. virtual void syncCompositingState() { } + virtual void syncCompositingStateForThisLayerOnly() { } // Return a string with a human readable form of the layer tree, If debug is true // pointers for the layers and timing data will be included in the returned string. diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h index ad90dd9..c5990ef 100644 --- a/WebCore/platform/graphics/IntRect.h +++ b/WebCore/platform/graphics/IntRect.h @@ -48,7 +48,12 @@ QT_BEGIN_NAMESPACE class QRect; QT_END_NAMESPACE #elif PLATFORM(GTK) +#ifdef GTK_API_VERSION_2 typedef struct _GdkRectangle GdkRectangle; +#else +typedef struct _cairo_rectangle_int cairo_rectangle_int_t; +typedef cairo_rectangle_int_t GdkRectangle; +#endif #elif PLATFORM(HAIKU) class BRect; #endif diff --git a/WebCore/platform/graphics/TextRun.h b/WebCore/platform/graphics/TextRun.h index b5cd42a..79b6cb3 100644 --- a/WebCore/platform/graphics/TextRun.h +++ b/WebCore/platform/graphics/TextRun.h @@ -39,7 +39,9 @@ public: , m_len(len) , m_xpos(xpos) , m_padding(padding) - , m_glyphScale(1.0f) +#if ENABLE(SVG) + , m_horizontalGlyphStretch(1) +#endif , m_allowTabs(allowTabs) , m_rtl(rtl) , m_directionalOverride(directionalOverride) @@ -59,7 +61,9 @@ public: , m_len(s.length()) , m_xpos(xpos) , m_padding(padding) - , m_glyphScale(1.0f) +#if ENABLE(SVG) + , m_horizontalGlyphStretch(1) +#endif , m_allowTabs(allowTabs) , m_rtl(rtl) , m_directionalOverride(directionalOverride) @@ -81,8 +85,10 @@ public: void setText(const UChar* c, int len) { m_characters = c; m_len = len; } - float glyphScale() const { return m_glyphScale; } - void setGlyphScale(float scale) { m_glyphScale = scale; } +#if ENABLE(SVG) + float horizontalGlyphStretch() const { return m_horizontalGlyphStretch; } + void setHorizontalGlyphStretch(float scale) { m_horizontalGlyphStretch = scale; } +#endif bool allowTabs() const { return m_allowTabs; } int xPos() const { return m_xpos; } @@ -93,7 +99,6 @@ public: bool applyRunRounding() const { return m_applyRunRounding; } bool applyWordRounding() const { return m_applyWordRounding; } bool spacingDisabled() const { return m_disableSpacing; } - bool applyGlyphScaling() const { return m_glyphScale != 1.0f; } void disableSpacing() { m_disableSpacing = true; } void disableRoundingHacks() { m_applyRunRounding = m_applyWordRounding = false; } @@ -114,7 +119,9 @@ private: int m_xpos; int m_padding; - float m_glyphScale; +#if ENABLE(SVG) + float m_horizontalGlyphStretch; +#endif bool m_allowTabs; bool m_rtl; bool m_directionalOverride; diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp index 0814d48..827cd10 100644 --- a/WebCore/platform/graphics/WidthIterator.cpp +++ b/WebCore/platform/graphics/WidthIterator.cpp @@ -135,9 +135,10 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) } else { width = fontData->widthForGlyph(glyph); - // SVG uses glyphScale(), when textLength is used to stretch/squeeze text. - if (m_run.applyGlyphScaling()) - width *= m_run.glyphScale(); +#if ENABLE(SVG) + // SVG uses horizontalGlyphStretch(), when textLength is used to stretch/squeeze text. + width *= m_run.horizontalGlyphStretch(); +#endif // We special case spaces in two ways when applying word rounding. // First, we round spaces to an adjusted width in all fonts. diff --git a/WebCore/platform/graphics/cairo/DrawErrorUnderline.h b/WebCore/platform/graphics/cairo/DrawErrorUnderline.h new file mode 100644 index 0000000..9776853 --- /dev/null +++ b/WebCore/platform/graphics/cairo/DrawErrorUnderline.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2004 Red Hat, Inc. + * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org> + * + * Based on Pango sources (see pangocairo-render.c) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#if PLATFORM(CAIRO) + +#include <cairo.h> + +// +// Draws an error underline that looks like one of: +// +// H E H +// /\ /\ /\ /\ /\ - +// A/ \ / \ / \ A/ \ / \ | +// \ \ / \ / /D \ \ / \ | +// \ \/ C \/ / \ \/ C \ | height = heightSquares * square +// \ /\ F / \ F /\ \ | +// \ / \ / \ / \ \G | +// \ / \ / \ / \ / | +// \/ \/ \/ \/ - +// B B +// |---| +// unitWidth = (heightSquares - 1) * square +// +// The x, y, width, height passed in give the desired bounding box; +// x/width are adjusted to make the underline a integer number of units +// wide. +// +static inline void drawErrorUnderline(cairo_t* cr, double x, double y, double width, double height) +{ + static const double heightSquares = 2.5; + + double square = height / heightSquares; + double halfSquare = 0.5 * square; + + double unitWidth = (heightSquares - 1.0) * square; + int widthUnits = static_cast<int>(0.5 * (width + unitWidth) / unitWidth); + + x += 0.5 * (width - widthUnits * unitWidth); + width = widthUnits * unitWidth; + + double bottom = y + height; + double top = y; + + // Bottom of squiggle + cairo_move_to(cr, x - halfSquare, top + halfSquare); // A + + int i = 0; + for (i = 0; i < widthUnits; i += 2) { + double middle = x + (i + 1) * unitWidth; + double right = x + (i + 2) * unitWidth; + + cairo_line_to(cr, middle, bottom); // B + + if (i + 2 == widthUnits) + cairo_line_to(cr, right + halfSquare, top + halfSquare); // D + else if (i + 1 != widthUnits) + cairo_line_to(cr, right, top + square); // C + } + + // Top of squiggle + for (i -= 2; i >= 0; i -= 2) { + double left = x + i * unitWidth; + double middle = x + (i + 1) * unitWidth; + double right = x + (i + 2) * unitWidth; + + if (i + 1 == widthUnits) + cairo_line_to(cr, middle + halfSquare, bottom - halfSquare); // G + else { + if (i + 2 == widthUnits) + cairo_line_to(cr, right, top); // E + + cairo_line_to(cr, middle, bottom - halfSquare); // F + } + + cairo_line_to(cr, left, top); // H + } +} + +#endif diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 50564c5..e8324a3 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -504,6 +504,17 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points cairo_restore(cr); } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT! +} + void GraphicsContext::fillPath() { if (paintingDisabled()) @@ -632,13 +643,27 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int cairo_new_path(cr); #if PLATFORM(GTK) +#ifdef GTK_API_VERSION_2 GdkRegion* reg = gdk_region_new(); +#else + cairo_region_t* reg = cairo_region_create(); +#endif + for (unsigned i = 0; i < rectCount; i++) { +#ifdef GTK_API_VERSION_2 GdkRectangle rect = rects[i]; gdk_region_union_with_rect(reg, &rect); +#else + cairo_rectangle_int_t rect = rects[i]; + cairo_region_union_rectangle(reg, &rect); +#endif } gdk_cairo_region(cr, reg); +#ifdef GTK_API_VERSION_2 gdk_region_destroy(reg); +#else + cairo_region_destroy(reg); +#endif setColor(cr, color); cairo_set_line_width(cr, 2.0f); @@ -683,6 +708,10 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr setStrokeStyle(savedStrokeStyle); } +#if !PLATFORM(GTK) +#include "DrawErrorUnderline.h" +#endif + void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar) { if (paintingDisabled()) @@ -702,7 +731,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, // We ignore most of the provided constants in favour of the platform style pango_cairo_show_error_underline(cr, origin.x(), origin.y(), width, cMisspellingLineThickness); #else - notImplemented(); + drawErrorUnderline(cr, origin.x(), origin.y(), width, cMisspellingLineThickness); #endif cairo_restore(cr); diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index 5c03a86..9f0f353 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -100,7 +100,7 @@ bool GraphicsContext3D::getImageData(Image* image, if (!premultiplyAlpha && hasAlphaChannel) // FIXME: must fetch the image data before the premultiplication step. neededAlphaOp = kAlphaDoUnmultiply; - return packPixels(tempVector.data(), kSourceFormatRGBA8, width, height, + return packPixels(tempVector.data(), kSourceFormatRGBA8, width, height, 0, format, type, neededAlphaOp, outputVector.data()); } diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 5a903dc..a65874c 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -440,6 +440,15 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp CGContextRestoreGState(context); } +static void addConvexPolygonToContext(CGContextRef context, size_t numPoints, const FloatPoint* points) +{ + CGContextBeginPath(context); + CGContextMoveToPoint(context, points[0].x(), points[0].y()); + for (size_t i = 1; i < numPoints; i++) + CGContextAddLineToPoint(context, points[i].x(), points[i].y()); + CGContextClosePath(context); +} + void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool antialiased) { if (paintingDisabled()) @@ -453,18 +462,25 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points if (antialiased != shouldAntialias()) CGContextSetShouldAntialias(context, antialiased); - CGContextBeginPath(context); - CGContextMoveToPoint(context, points[0].x(), points[0].y()); - for (size_t i = 1; i < npoints; i++) - CGContextAddLineToPoint(context, points[i].x(), points[i].y()); - CGContextClosePath(context); - + addConvexPolygonToContext(context, npoints, points); drawPath(); if (antialiased != shouldAntialias()) CGContextSetShouldAntialias(context, shouldAntialias()); } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + addConvexPolygonToContext(platformContext(), numPoints, points); + clipPath(RULE_NONZERO); +} + void GraphicsContext::applyStrokePattern() { CGContextRef cgContext = platformContext(); diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm new file mode 100644 index 0000000..41f684e --- /dev/null +++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm @@ -0,0 +1,447 @@ +/* + * This file is part of the internal font implementation. + * + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +// This file is a clone of platform/graphics/mac/FontPlatformDataMac.mm. +// Because we want to support loading fonts between processes in the face of +// font loading being blocked by the sandbox, we must maintain a fork. +// Please maintain this file by performing parallel changes to it. +// +// The only changes from FontPlatformDataMac should be: +// - The functions at the top of this file for loading and caching fonts +// cross-process. +// - Changes to FontPlatformData::FontPlatformData(NSFont,bool,bool) +// - Changes to FontPlatformData::setFont() +// - Changes to FontPlatformData::~FontPlatformData() +// - Calls to refMemoryFont() in FontPlatformData::operator= and copy +// constructor. +// +// All changes are marked with "Start/End Chromium Change" +// +// For all other differences, if it was introduced in this file, then the +// maintainer forgot to include it in the list; otherwise it is an update that +// should have been applied to this file but was not. + + +// Start Chromium Change +#import "config.h" +#import "../graphics/mac/FontPlatformData.h" + +#import "ChromiumBridge.h" +#import "PlatformString.h" +#import "WebCoreSystemInterface.h" +#import <AppKit/NSFont.h> +#import <wtf/HashMap.h> +#import <wtf/RefCounted.h> +#import <wtf/RetainPtr.h> +#import <wtf/Vector.h> + +namespace WebCore { + +namespace { + +class MemoryActivatedFont; +typedef HashMap<ATSFontRef, MemoryActivatedFont*> FontRefMemoryFontHash; +typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash; + +// On 10.5, font loading is not blocked by the sandbox and thus there is no +// need for the cross-process font loading mechanim. +// On system versions >=10.6 cross-process font loading is required. +bool OutOfProcessFontLoadingEnabled() +{ + static SInt32 systemVersion = 0; + if (!systemVersion) { + if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr) + return false; + } + + return systemVersion >= 0x1060; +} + +FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef() +{ + DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ()); + return srcFontRefCache; +} + +FontRefMemoryFontHash& fontCacheByActualFontRef() +{ + DEFINE_STATIC_LOCAL(FontRefMemoryFontHash, realFontRefCache, ()); + return realFontRefCache; +} + +ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont) +{ + ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0); + if (!fontRef) + return kATSFontContainerRefUnspecified; + ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified; + if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr) + return kATSFontContainerRefUnspecified; + return fontContainer; +} + +// MemoryActivatedFont encapsulates a font loaded from another process and +// activated from memory. +// +// Responsibilities: +// * Holder for the CGFontRef & ATSFontRef belonging to the activated font. +// * Responsible for unloading the font container when done. +// +// Memory Management: +// The class is reference counted, with each instance of FontPlatformData that +// uses this class holding a reference to it. +// Entries in 2 hashes are maintained internally to allow quick lookup +// of existing instances for reuse: +// - fontCacheBySrcFontContainerRef() - key is the ATSFontContainerRef +// corresponding to the *original in-process NSFont* whose loading was blocked +// by the sandbox. +// This is needed to allow lookup of a pre-existing MemoryActivatedFont when +// creating a new FontPlatformData object. +// - fontCacheByActualFontRef() - key is the ATSFontRef corresponding to the +// *new in-memory font* that we got from the browser process. +// This is needed so that a FontPlatformData object can refer back to the +// MemoryActivatedFont it's using. Currently this is only needed to release +// the font on FontPlatformData destruction. +// +// Assumptions: +// This code assumes that an ATSFontRef is a unique identifier tied to an +// activated font. i.e. After we activate a font, its ATSFontRef doesn't +// change. +// It also assumes that the ATSFoncontainerRef for two in-memory NSFonts that +// correspond to the same on-disk font file are always the same and don't change +// with time. +// +// Flushing caches: +// When the system notifies us of a system font cache flush, all FontDataCache +// objects are destroyed. This should in turn dereference all +// MemoryActivatedFonts and thus unload all in-memory fonts. +class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> { +public: + // srcFontRef - ATSFontRef belonging to the NSFont object that failed to + // load in-process. + // container - a font container corresponding to an identical font that + // we loaded cross-process. + MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container) + : m_fontContainer(container) + , m_atsFontRef(kATSFontRefUnspecified) + , m_srcFontContainerRef(srcFontContainerRef) + { + if (!container) + return; + + // Count the number of fonts in the container. + ItemCount fontCount = 0; + OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0, 0, &fontCount); + if (err != noErr || fontCount < 1) + return; + + // For now always assume that we want the first font in the container. + ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef, 0); + + if (!m_atsFontRef) + return; + + // Cache CGFont representation of the font. + m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef)); + + if (!m_cgFont.get()) + return; + + // Add ourselves to caches. + fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this); + fontCacheByActualFontRef().add(m_atsFontRef, this); + } + + // Get cached CGFontRef corresponding to the in-memory font. + CGFontRef cgFont() + { + return m_cgFont.get(); + } + + // Get cached ATSFontRef corresponding to the in-memory font. + ATSFontRef atsFontRef() + { + return m_atsFontRef; + } + + // Destructor - Unload font container from memory and remove ourselves + // from hashes. + ~MemoryActivatedFont() + { + if (m_cgFont.get()) { // Object construction succeeded. + // First remove ourselves from the caches. + ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef)); + ASSERT(fontCacheByActualFontRef().contains(m_atsFontRef)); + + fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef); + fontCacheByActualFontRef().remove(m_atsFontRef); + + // Make sure the CGFont is destroyed before its font container. + m_cgFont.releaseRef(); + } + + if (m_fontContainer != kATSFontContainerRefUnspecified) + ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault); + } + +private: + ATSFontContainerRef m_fontContainer; + WTF::RetainPtr<CGFontRef> m_cgFont; + ATSFontRef m_atsFontRef; + ATSFontContainerRef m_srcFontContainerRef; +}; + +// The only way we can tell that an in-process font has failed to load +// is if CTFontCopyGraphicsFont() returns the LastResort font. +bool isLastResortFont(CGFontRef cgFont) +{ + NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont); + return [fontName isEqualToString:@"LastResort"]; +} + +// Given an in-process font which has failed to load, return a +// MemoryActivatedFont* corresponding to an in-memory representation of the +// same font loaded from the browser process. +// The caller is responsbile for calling derefMemoryFont() on the ATSFontRef +// of the returned font. +// On failure this function returns 0, in which case the caller doesn't need +// to perform any additional cleanup. +MemoryActivatedFont* loadFontFromBrowserProcess(NSFont* nsFont) +{ + ATSFontContainerRef container; + // Send cross-process request to load font. + if (!ChromiumBridge::loadFont(nsFont, &container)) + return 0; + + ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont); + if (!srcFontContainerRef) { + ATSFontDeactivate(container, 0, kATSOptionFlagsDefault); + return 0; + } + + MemoryActivatedFont* font = fontCacheBySrcFontContainerRef().get(srcFontContainerRef); + if (!font) { + font = new MemoryActivatedFont(srcFontContainerRef, container); + if (!font->cgFont()) { + delete font; + return 0; + } + } else { + font->ref(); + } + + return font; +} + +// deref() the MemoryActivatedFont corresponding to the given ATSFontRef. If no +// corresponding MemoryActivatedFont object exists, no action is performed. +void derefMemoryFont(ATSFontRef fontRef) +{ + if (fontRef == kATSFontRefUnspecified) + return; + MemoryActivatedFont* font = fontCacheByActualFontRef().get(fontRef); + if (font) + font->deref(); +} + +// ref() the MemoryActivatedFont corresponding to the given ATSFontRef. If no +// corresponding MemoryActivatedFont object exists, no action is performed. +void refMemoryFont(ATSFontRef fontRef) +{ + if (fontRef == kATSFontRefUnspecified) + return; + MemoryActivatedFont* font = fontCacheByActualFontRef().get(fontRef); + if (font) + font->ref(); +} + +// Given an NSFont, try to load a representation of that font into the cgFont +// parameter. If loading is blocked by the sandbox, the font may be loaded +// cross-process. +// If sandbox loading also fails, a fallback font is loaded. +// +// Considerations: +// * cgFont must be CFReleas()ed by the caller when done. +// +// Parameters: +// * nsFont - The font we wish to load. +// * fontSize - point size of the font we wish to load. +// * outNSFont - The font that was actually loaded, may be different from nsFont +// if a fallback font was used. +// * cgFont - on output this contains the CGFontRef corresponding to the NSFont +// that was picked in the end. The caller is responsible for calling +// CFRelease() on this parameter when done with it. +// * fontID - on output, the ID corresponding to nsFont. +void loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont, ATSUFontID& fontID) +{ + outNSFont = nsFont; + cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); + MemoryActivatedFont* memFont = 0; + if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortFont(cgFont)) { + // Release old CGFontRef since it points at the LastResort font which we don't want. + CFRelease(cgFont); + cgFont = 0; + + // Font loading was blocked by the Sandbox. + memFont = loadFontFromBrowserProcess(outNSFont); + if (memFont) { + cgFont = memFont->cgFont(); + + // Need to add an extra retain so output semantics of this function + // are consistent. + CFRetain(cgFont); + } else { + // If we still can't load the font, then return Times, + // rather than the LastResort font. + outNSFont = [NSFont fontWithName:@"Times" size:fontSize]; + cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); + } + } + + if (memFont) { + fontID = memFont->atsFontRef(); + } else { + fontID = CTFontGetPlatformFont(toCTFontRef(outNSFont), 0); + } +} + +} // namespace +// End Chromium Change + +FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool syntheticOblique) + : m_syntheticBold(syntheticBold) + , m_syntheticOblique(syntheticOblique) + , m_font(nsFont) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait) +#else + , m_isColorBitmapFont(false) +#endif +{ +// Start Chromium Change + m_size = nsFont ? [nsFont pointSize] : 0.0f; + CGFontRef cgFont = 0; + NSFont* loadedFont = 0; + loadFont(nsFont, m_size, loadedFont, cgFont, m_atsuFontID); + m_font = loadedFont; + if (m_font) + CFRetain(m_font); + m_cgFont.adoptCF(cgFont); +// End Chromium Change +} + +FontPlatformData::FontPlatformData(const FontPlatformData& f) +{ + m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font; + + m_syntheticBold = f.m_syntheticBold; + m_syntheticOblique = f.m_syntheticOblique; + m_size = f.m_size; + m_cgFont = f.m_cgFont; + m_atsuFontID = f.m_atsuFontID; + m_isColorBitmapFont = f.m_isColorBitmapFont; + // Start Chromium Change + refMemoryFont(m_atsuFontID); + // End Chromium Change +} + +FontPlatformData::~FontPlatformData() +{ + if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) + CFRelease(m_font); + + // Start Chromium Change + derefMemoryFont(m_atsuFontID); + // End Chromium Change +} + +const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) +{ + m_syntheticBold = f.m_syntheticBold; + m_syntheticOblique = f.m_syntheticOblique; + m_size = f.m_size; + m_cgFont = f.m_cgFont; + m_atsuFontID = f.m_atsuFontID; + if (m_font == f.m_font) + return *this; + if (f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1)) + CFRetain(f.m_font); + if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) + CFRelease(m_font); + m_font = f.m_font; + m_isColorBitmapFont = f.m_isColorBitmapFont; + // Start Chromium Change + refMemoryFont(m_atsuFontID); + // End Chromium Change + return *this; +} + +void FontPlatformData::setFont(NSFont *font) +{ + if (m_font == font) + return; + if (font) + CFRetain(font); + if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) + CFRelease(m_font); + m_font = font; + m_size = font ? [font pointSize] : 0.0f; + + // Start Chromium Change + CGFontRef cgFont = 0; + NSFont* loadedFont = 0; + loadFont(m_font, m_size, loadedFont, cgFont, m_atsuFontID); + + // If loadFont replaced m_font with a fallback font, then release the + // previous font to counter the retain above. Then retain the new font. + if (loadedFont != m_font) { + CFRelease(m_font); + m_font = loadedFont; + CFRetain(m_font); + } + m_cgFont.adoptCF(cgFont); +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait; +#endif + // End Chromium Change +} + +bool FontPlatformData::roundsGlyphAdvances() const +{ + return [m_font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode; +} + +bool FontPlatformData::allowsLigatures() const +{ + return ![[m_font coveredCharacterSet] characterIsMember:'a']; +} + +#ifndef NDEBUG +String FontPlatformData::description() const +{ + RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont())); + return String(cgFontDescription.get()) + " " + String::number(m_size) + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " synthetic oblique" : ""); +} +#endif + +} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 0a5aec5..dda10b7 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -148,6 +148,7 @@ void FontPlatformData::setupPaint(SkPaint* paint) const paint->setTypeface(m_typeface); paint->setFakeBoldText(m_fakeBold); paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0); + paint->setAutohinted(m_style.useAutoHint); if (m_style.useAntiAlias == 1 || (m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias)) paint->setLCDRenderText(m_style.useSubpixel == FontRenderStyle::NoPreference ? isSkiaSubpixelGlyphs : m_style.useSubpixel); @@ -175,7 +176,8 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const return typefacesEqual && m_textSize == a.m_textSize && m_fakeBold == a.m_fakeBold - && m_fakeItalic == a.m_fakeItalic; + && m_fakeItalic == a.m_fakeItalic + && m_style == a.m_style; } unsigned FontPlatformData::hash() const diff --git a/WebCore/platform/graphics/chromium/FontRenderStyle.h b/WebCore/platform/graphics/chromium/FontRenderStyle.h index 1a3c736..6e2ae54 100644 --- a/WebCore/platform/graphics/chromium/FontRenderStyle.h +++ b/WebCore/platform/graphics/chromium/FontRenderStyle.h @@ -39,6 +39,24 @@ struct FontRenderStyle { NoPreference = 2, }; + FontRenderStyle() + : useBitmaps(0), + useAutoHint(0), + useHinting(0), + hintStyle(0), + useAntiAlias(0), + useSubpixel(0) { } + + bool operator==(const FontRenderStyle& a) const + { + return useBitmaps == a.useBitmaps + && useAutoHint == a.useAutoHint + && useHinting == a.useHinting + && hintStyle == a.hintStyle + && useAntiAlias == a.useAntiAlias + && useSubpixel == a.useSubpixel; + } + // Each of the use* members below can take one of three values: // 0: off // 1: on diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index b26565c..9b65346 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -53,6 +53,7 @@ #include "PlatformString.h" #include "SystemTime.h" #include "TransformLayerChromium.h" +#include "WebGLLayerChromium.h" #include <wtf/CurrentTime.h> #include <wtf/StringExtras.h> #include <wtf/text/CString.h> @@ -333,6 +334,35 @@ void GraphicsLayerChromium::setContentsToImage(Image* image) updateSublayerList(); } +#if ENABLE(3D_CANVAS) +void GraphicsLayerChromium::setContentsToWebGL(PlatformLayer* platformLayer) +{ + bool childrenChanged = false; + if (platformLayer) { + if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForWebGL) { + WebGLLayerChromium* webGLLayer = static_cast<WebGLLayerChromium*>(platformLayer); + setupContentsLayer(webGLLayer); + m_contentsLayer = webGLLayer; + m_contentsLayerPurpose = ContentsLayerForWebGL; + childrenChanged = true; + } + platformLayer->setOwner(this); + platformLayer->setNeedsDisplay(); + updateContentsRect(); + } else { + if (m_contentsLayer) { + childrenChanged = true; + + // The old contents layer will be removed via updateSublayerList. + m_contentsLayer = 0; + } + } + + if (childrenChanged) + updateSublayerList(); +} +#endif + void GraphicsLayerChromium::setContentsToVideo(PlatformLayer* videoLayer) { // FIXME: Implement diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h index 0c84c80..ccd02eb 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h @@ -86,6 +86,7 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsToVideo(PlatformLayer*); + virtual void setContentsToWebGL(PlatformLayer*); virtual PlatformLayer* platformLayer() const; diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index e3209a7..3119dd6 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -136,11 +136,14 @@ void LayerChromium::updateTextureContents(unsigned textureId) canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); skiaContext.set(new PlatformContextSkia(canvas.get())); +#if OS(WINDOWS) // This is needed to get text to show up correctly. Without it, // GDI renders with zero alpha and the text becomes invisible. // Unfortunately, setting this to true disables cleartype. // FIXME: Does this take us down a very slow text rendering path? + // FIXME: why is this is a windows-only call ? skiaContext->setDrawingToImageBuffer(true); +#endif graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); @@ -296,7 +299,6 @@ void LayerChromium::removeAllSublayers() ASSERT(layer->superlayer()); layer->removeFromSuperlayer(); } - setNeedsCommit(); } void LayerChromium::setSublayers(const Vector<RefPtr<LayerChromium> >& sublayers) diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index f19baea..ebb4504 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -172,6 +172,8 @@ public: static void setShaderProgramId(unsigned shaderProgramId) { m_shaderProgramId = shaderProgramId; } virtual unsigned shaderProgramId() { return m_shaderProgramId; } + void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; } + protected: GraphicsLayerChromium* m_owner; LayerChromium(GraphicsLayerChromium* owner); diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index dc587dd..59da9ae 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -241,7 +241,10 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) // the old ones. m_rootLayerCanvas = new skia::PlatformCanvas(size.width(), size.height(), false); m_rootLayerSkiaContext = new PlatformContextSkia(m_rootLayerCanvas.get()); +#if OS(WINDOWS) + // FIXME: why is this is a windows-only call ? m_rootLayerSkiaContext->setDrawingToImageBuffer(true); +#endif m_rootLayerGraphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_rootLayerSkiaContext.get())); #else #error "Need to implement for your platform." @@ -623,11 +626,6 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) layer->updateTextureContents(textureId); } - // FIXME: This is temporary until WebGL layers stop changing the current - // context. - if (layer->ownsTexture()) - makeContextCurrent(); - if (layer->doubleSided()) glDisable(GL_CULL_FACE); else diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp index 6b49b9a..ebd9ebe 100644 --- a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp @@ -34,10 +34,18 @@ #include "WebGLLayerChromium.h" +#include "GraphicsContext3D.h" +#include <GLES2/gl2.h> + namespace WebCore { unsigned WebGLLayerChromium::m_shaderProgramId = 0; +PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(GraphicsLayerChromium* owner) +{ + return adoptRef(new WebGLLayerChromium(owner)); +} + WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner) : LayerChromium(owner) , m_context(0) @@ -53,12 +61,33 @@ unsigned WebGLLayerChromium::textureId() void WebGLLayerChromium::updateTextureContents(unsigned textureId) { - // FIXME: Implement + ASSERT(textureId == m_textureId); + ASSERT(m_context); + if (m_textureChanged) { + glBindTexture(GL_TEXTURE_2D, m_textureId); + // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE + // to get around NPOT texture limitations of GLES. + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_textureChanged = false; + } + // Update the contents of the texture used by the compositor. + if (m_contentsDirty) { + m_context->prepareTexture(); + m_contentsDirty = false; + } } void WebGLLayerChromium::setContext(const GraphicsContext3D* context) { - // FIXME: Implement + m_context = const_cast<GraphicsContext3D*>(context); + + unsigned int textureId = m_context->platformTexture(); + if (textureId != m_textureId) + m_textureChanged = true; + m_textureId = textureId; } } diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index fae84cb..92f8816 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -181,6 +181,29 @@ bool Font::canReturnFallbackFontsForComplexText() return false; } +#ifndef GTK_API_VERSION_2 +static void cairo_region_shrink(cairo_region_t* region, int dx, int dy) +{ + int nRects = cairo_region_num_rectangles(region); + // Clear region. + cairo_region_subtract(region, region); + + for (int i = 0; i < nRects; i++) { + cairo_rectangle_int_t rect; + cairo_region_get_rectangle(region, i, &rect); + + if (rect.width <= 2 * dx || rect.height <= 2 * dy) + continue; + + rect.x += dx; + rect.y += dy; + rect.width -= 2 * dx; + rect.height -= 2 * dy; + cairo_region_union_rectangle(region, &rect); + } +} +#endif + void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { cairo_t* cr = context->platformContext(); @@ -196,14 +219,22 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); - GdkRegion* partialRegion = NULL; +#ifdef GTK_API_VERSION_2 + GdkRegion* partialRegion = 0; +#else + cairo_region_t* partialRegion = 0; +#endif if (to - from != run.length()) { // Clip the region of the run to be rendered char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); int ranges[] = {start - utf8, end - utf8}; partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); +#ifdef GTK_API_VERSION_2 gdk_region_shrink(partialRegion, 0, -pixelSize()); +#else + cairo_region_shrink(partialRegion, 0, -pixelSize()); +#endif } Color fillColor = context->fillColor(); @@ -265,7 +296,11 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F cairo_new_path(cr); if (partialRegion) +#ifdef GTK_API_VERSION_2 gdk_region_destroy(partialRegion); +#else + cairo_region_destroy(partialRegion); +#endif g_free(utf8); g_object_unref(layout); diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 2f02f31..f9e1980 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -152,6 +152,17 @@ void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* p m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle()); } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT!! +} + void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm index e2ab405..aebd9f7 100644 --- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm +++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm @@ -123,7 +123,7 @@ bool FontPlatformData::allowsLigatures() const String FontPlatformData::description() const { RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont())); - return String(cgFontDescription.get()) + " " + String::number(m_size) + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " syntheitic oblique" : ""); + return String(cgFontDescription.get()) + " " + String::number(m_size) + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " synthetic oblique" : ""); } #endif diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 6457e4f..961ec45 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -736,6 +736,16 @@ bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long in return true; } +void GraphicsContext3D::getAttachedShaders(WebGLProgram* program, int maxCount, int* count, unsigned int* shaders) +{ + if (!program || !program->object()) { + synthesizeGLError(INVALID_VALUE); + return; + } + ensureContext(m_contextObj); + ::glGetAttachedShaders(static_cast<GLuint>(program->object()), maxCount, count, shaders); +} + int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name) { if (!program) @@ -1103,10 +1113,8 @@ void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* a void GraphicsContext3D::useProgram(WebGLProgram* program) { - ASSERT(program); - ensureContext(m_contextObj); - ::glUseProgram((GLuint) program->object()); + ::glUseProgram(program ? ((GLuint) program->object()) : 0); } void GraphicsContext3D::validateProgram(WebGLProgram* program) diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index c17204f..7d78dee 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -119,6 +119,7 @@ public: void recursiveCommitChanges(); virtual void syncCompositingState(); + virtual void syncCompositingStateForThisLayerOnly(); protected: virtual void setOpacityInternal(float); diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index 355c023..852bdb0 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -868,6 +868,12 @@ void GraphicsLayerCA::syncCompositingState() recursiveCommitChanges(); } +void GraphicsLayerCA::syncCompositingStateForThisLayerOnly() +{ + commitLayerChangesBeforeSublayers(); + commitLayerChangesAfterSublayers(); +} + void GraphicsLayerCA::recursiveCommitChanges() { commitLayerChangesBeforeSublayers(); diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index c73eeea..5c327f9 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -1299,11 +1299,17 @@ static HashSet<String> mimeModernTypesCache() return cache; } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types) +void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& supportedTypes) { + supportedTypes = mimeModernTypesCache(); + // Note: this method starts QTKitServer if it isn't already running when in 64-bit because it has to return the list // of every MIME type supported by QTKit. - types = mimeCommonTypesCache(); + HashSet<String> commonTypes = mimeCommonTypesCache(); + HashSet<String>::const_iterator it = commonTypes.begin(); + HashSet<String>::const_iterator end = commonTypes.end(); + for (; it != end; ++it) + supportedTypes.add(*it); } MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index bddb2ad..126ef2d 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -280,7 +280,7 @@ void SimpleFontData::platformInit() } } -static CFDataRef copyFontTableForTag(FontPlatformData platformData, FourCharCode tableName) +static CFDataRef copyFontTableForTag(FontPlatformData& platformData, FourCharCode tableName) { #ifdef BUILDING_ON_TIGER ATSFontRef atsFont = FMGetATSFontRefFromFont(platformData.m_atsuFontID); diff --git a/WebCore/platform/graphics/qt/FloatRectQt.cpp b/WebCore/platform/graphics/qt/FloatRectQt.cpp index 1c918e3..063876b 100644 --- a/WebCore/platform/graphics/qt/FloatRectQt.cpp +++ b/WebCore/platform/graphics/qt/FloatRectQt.cpp @@ -44,6 +44,21 @@ FloatRect::operator QRectF() const return QRectF(x(), y(), width(), height()); } +FloatRect FloatRect::normalized() const +{ + FloatRect normalizedRect = *this; + + if (width() < 0) { + normalizedRect.setX(x() + width()); + normalizedRect.setWidth(-width()); + } + if (height() < 0) { + normalizedRect.setY(y() + height()); + normalizedRect.setHeight(-height()); + } + return normalizedRect; +} + } // vim: ts=4 sw=4 et diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 0c1d271..59320cb 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -234,7 +234,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return 0; if (run.length() == 1 && treatAsSpace(run[0])) - return QFontMetrics(font()).width(run[0]) + run.padding(); + return QFontMetrics(font()).width(space) + run.padding(); String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp index 8b9e2d7..1f05a15 100644 --- a/WebCore/platform/graphics/qt/GradientQt.cpp +++ b/WebCore/platform/graphics/qt/GradientQt.cpp @@ -51,6 +51,8 @@ QGradient* Gradient::platformGradient() else m_gradient = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y()); + m_gradient->setInterpolationMode(QGradient::ComponentInterpolation); + sortStopsIfNecessary(); QColor stopColor; @@ -65,7 +67,7 @@ QGradient* Gradient::platformGradient() lastStop = stopIterator->stop; if (m_radial && m_r0) lastStop = m_r0 / m_r1 + lastStop * (1.0f - m_r0 / m_r1); - m_gradient->setColorAt(lastStop, stopColor); + m_gradient->setColorAt(qMin(lastStop, qreal(1.0f)), stopColor); // Keep the lastStop as orginal value, since the following stopColor depend it lastStop = stopIterator->stop; ++stopIterator; diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 1a51910..002765f 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -1637,7 +1637,7 @@ bool GraphicsContext3D::getImageData(Image* image, neededAlphaOp = kAlphaDoUnmultiply; QImage nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32); outputVector.resize(nativeImage.byteCount()); - return packPixels(nativeImage.rgbSwapped().bits(), kSourceFormatRGBA8, image->width(), image->height(), + return packPixels(nativeImage.rgbSwapped().bits(), kSourceFormatRGBA8, image->width(), image->height(), 0, format, type, neededAlphaOp, outputVector.data()); } diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 13608b2..9d23340 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -528,6 +528,17 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points p->restore(); } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT!! +} + QPen GraphicsContext::pen() { if (paintingDisabled()) @@ -1056,7 +1067,12 @@ void GraphicsContext::clip(const Path& path) void GraphicsContext::canvasClip(const Path& path) { - clip(path); + if (paintingDisabled()) + return; + + QPainterPath clipPath = path.platformPath(); + clipPath.setFillRule(Qt::WindingFill); + m_data->p()->setClipPath(clipPath, Qt::IntersectClip); } void GraphicsContext::clipOut(const Path& path) diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 8ed0d89..226f1fb 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -41,6 +41,10 @@ #include <QtGui/qpixmapcache.h> #include <QtGui/qstyleoption.h> + +#define QT_DEBUG_RECACHE 0 +#define QT_DEBUG_CACHEDUMP 0 + namespace WebCore { #ifndef QT_NO_GRAPHICSEFFECT @@ -225,7 +229,10 @@ public: int m_changeMask; QSizeF m_size; - QPixmapCache::Key m_backingStoreKey; + struct { + QPixmapCache::Key key; + QSizeF size; + } m_backingStore; #ifndef QT_NO_ANIMATION QList<QWeakPointer<QAbstractAnimation> > m_animations; #endif @@ -283,7 +290,6 @@ inline GraphicsLayerQtImpl* toGraphicsLayerQtImpl(QGraphicsItem* item) inline GraphicsLayerQtImpl* toGraphicsLayerQtImpl(QGraphicsObject* item) { - ASSERT(item); return qobject_cast<GraphicsLayerQtImpl*>(item); } @@ -339,36 +345,109 @@ const GraphicsLayerQtImpl* GraphicsLayerQtImpl::rootLayer() const QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) { - if (!m_layer->drawsContent() || m_size.isEmpty() ||!m_size.isValid()) + if (!m_layer->drawsContent() || m_size.isEmpty() || !m_size.isValid()) return QPixmap(); - QRegion region = regionToUpdate; QPixmap pixmap; + QRegion region = regionToUpdate; + if (QPixmapCache::find(m_backingStore.key, &pixmap)) { + if (region.isEmpty()) + return pixmap; + QPixmapCache::remove(m_backingStore.key); // Remove the reference to the pixmap in the cache to avoid a detach. + } - // We might be drawing into an existing cache. - if (!QPixmapCache::find(m_backingStoreKey, &pixmap)) - region = QRegion(QRect(0, 0, m_size.width(), m_size.height())); + { + bool erased = false; - if (m_size != pixmap.size()) { - pixmap = QPixmap(m_size.toSize()); - if (!m_layer->contentsOpaque()) - pixmap.fill(Qt::transparent); - m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), m_size.toSize())); - } + // If the pixmap is not in the cache or the view has grown since last cached. + if (pixmap.isNull() || m_size != m_backingStore.size) { +#if QT_DEBUG_RECACHE + if (pixmap.isNull()) + qDebug() << "CacheMiss" << this << m_size; +#endif + bool fill = true; + QRegion newRegion; + QPixmap oldPixmap = pixmap; + + // If the pixmap is two small to hold the view contents we enlarge, otherwise just use the old (large) pixmap. + if (pixmap.width() < m_size.width() || pixmap.height() < m_size.height()) { +#if QT_DEBUG_RECACHE + qDebug() << "CacheGrow" << this << m_size; +#endif + pixmap = QPixmap(m_size.toSize()); + pixmap.fill(Qt::transparent); + newRegion = QRegion(0, 0, m_size.width(), m_size.height()); + } + +#if 1 + // Blit the contents of oldPixmap back into the cached pixmap as we are just adding new pixels. + if (!oldPixmap.isNull()) { + const QRegion cleanRegion = (QRegion(0, 0, m_size.width(), m_size.height()) + & QRegion(0, 0, m_backingStore.size.width(), m_backingStore.size.height())) - regionToUpdate; + if (!cleanRegion.isEmpty()) { +#if QT_DEBUG_RECACHE + qDebug() << "CacheBlit" << this << cleanRegion; +#endif + const QRect cleanBounds(cleanRegion.boundingRect()); + QPainter painter(&pixmap); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.drawPixmap(cleanBounds.topLeft(), oldPixmap, cleanBounds); + newRegion -= cleanRegion; + fill = false; // We cannot just fill the pixmap. + } + oldPixmap = QPixmap(); + } +#endif + region += newRegion; + if (fill && !region.isEmpty()) { // Clear the entire pixmap with the background. +#if QT_DEBUG_RECACHE + qDebug() << "CacheErase" << this << m_size << background; +#endif + erased = true; + pixmap.fill(Qt::transparent); + } + } + region &= QRegion(0, 0, m_size.width(), m_size.height()); + + // If we have something to draw its time to erase it and render the contents. + if (!region.isEmpty()) { +#if QT_DEBUG_CACHEDUMP + static int recacheCount = 0; + ++recacheCount; + qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; + pixmap.save(QString().sprintf("/tmp/%05d_A.png", recacheCount), "PNG"); +#endif + + QPainter painter(&pixmap); + GraphicsContext gc(&painter); - QPainter painter(&pixmap); - GraphicsContext gc(&painter); + painter.setClipRegion(region); - // Clear the area in cache that we're drawing into - painter.setCompositionMode(QPainter::CompositionMode_Clear); - painter.fillRect(region.boundingRect(), Qt::transparent); + if (!erased) { // Erase the area in cache that we're drawing into. + painter.setCompositionMode(QPainter::CompositionMode_Clear); + painter.fillRect(region.boundingRect(), Qt::transparent); - // Render the actual contents into the cache - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); - painter.end(); +#if QT_DEBUG_CACHEDUMP + qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; + pixmap.save(QString().sprintf("/tmp/%05d_B.png", recacheCount), "PNG"); +#endif + } - m_backingStoreKey = QPixmapCache::insert(pixmap); + // Render the actual contents into the cache. + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); + painter.end(); + +#if QT_DEBUG_CACHEDUMP + qDebug() << "**** CACHEDUMP" << recacheCount << this << m_layer << region << m_size; + pixmap.save(QString().sprintf("/tmp/%05d_C.png", recacheCount), "PNG"); +#endif + } + m_backingStore.size = m_size; // Store the used size of the pixmap. + } + + // Finally insert into the cache and allow a reference there. + m_backingStore.key = QPixmapCache::insert(pixmap); return pixmap; } @@ -487,8 +566,9 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte if (m_state.drawsContent) { QPixmap backingStore; // We might need to recache, in case we try to paint and the cache was purged (e.g. if it was full). - if (!QPixmapCache::find(m_backingStoreKey, &backingStore) || backingStore.size() != m_size.toSize()) + if (!QPixmapCache::find(m_backingStore.key, &backingStore) || backingStore.size() != m_size.toSize()) backingStore = recache(QRegion(m_state.contentsRect)); + const QRectF bounds(0, 0, m_backingStore.size.width(), m_backingStore.size.height()); painter->drawPixmap(0, 0, backingStore); } break; @@ -674,11 +754,13 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform else #endif if (m_changeMask & DisplayChange) { +#ifndef QT_GRAPHICS_LAYER_NO_RECACHE_ON_DISPLAY_CHANGE // Recache now: all the content is ready and we don't want to wait until the paint event. // We only need to do this for HTML content, there's no point in caching directly composited // content like images or solid rectangles. if (m_pendingContent.contentType == HTMLContentType) recache(m_pendingContent.regionToUpdate); +#endif update(m_pendingContent.regionToUpdate.boundingRect()); m_pendingContent.regionToUpdate = QRegion(); } @@ -1441,10 +1523,7 @@ bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSiz if (anim->fillsBackwards()) newAnim->setCurrentTime(0); - if (anim->delay()) - QTimer::singleShot(anim->delay() * 1000, newAnim, SLOT(start())); - else - newAnim->start(); + newAnim->start(); // We synchronize the animation's clock to WebCore's timeOffset. newAnim->setCurrentTime(timeOffset * 1000); diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index af94f55..dd97873 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -64,6 +64,8 @@ static QPixmap loadResourcePixmap(const char *name) pixmap = QWebSettings::webGraphic(QWebSettings::TextAreaSizeGripCornerGraphic); else if (qstrcmp(name, "deleteButton") == 0) pixmap = QWebSettings::webGraphic(QWebSettings::DeleteButtonGraphic); + else if (!qstrcmp(name, "inputSpeech")) + pixmap = QWebSettings::webGraphic(QWebSettings::InputSpeechButtonGraphic); return pixmap; } @@ -164,6 +166,9 @@ void BitmapImage::invalidatePlatformData() void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { + FloatRect normalizedDst = dst.normalized(); + FloatRect normalizedSrc = src.normalized(); + startAnimation(); QPixmap* image = nativeImageForCurrentFrame(); @@ -171,7 +176,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, return; if (mayFillWithSolidColor()) { - fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op); + fillWithSolidColor(ctxt, normalizedDst, solidColor(), styleColorSpace, op); return; } @@ -191,22 +196,22 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, float shadowBlur; Color shadowColor; if (ctxt->getShadow(shadowSize, shadowBlur, shadowColor)) { - FloatRect shadowImageRect(dst); + FloatRect shadowImageRect(normalizedDst); shadowImageRect.move(shadowSize.width(), shadowSize.height()); - QImage shadowImage(QSize(static_cast<int>(src.width()), static_cast<int>(src.height())), QImage::Format_ARGB32_Premultiplied); + QImage shadowImage(QSize(static_cast<int>(normalizedSrc.width()), static_cast<int>(normalizedSrc.height())), QImage::Format_ARGB32_Premultiplied); QPainter p(&shadowImage); p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(shadowImage.rect(), shadowColor); p.setCompositionMode(QPainter::CompositionMode_DestinationIn); - p.drawPixmap(dst, *image, src); + p.drawPixmap(normalizedDst, *image, normalizedSrc); p.end(); - painter->drawImage(shadowImageRect, shadowImage, src); + painter->drawImage(shadowImageRect, shadowImage, normalizedSrc); } // Test using example site at // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html - painter->drawPixmap(dst, *image, src); + painter->drawPixmap(normalizedDst, *image, normalizedSrc); painter->setCompositionMode(lastCompositionMode); diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index 8f1f912..a367212 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -69,8 +69,19 @@ Path& Path::operator=(const Path& other) return *this; } +static inline bool areCollinear(const QPointF& a, const QPointF& b, const QPointF& c) +{ + // Solved from comparing the slopes of a to b and b to c: (ay-by)/(ax-bx) == (cy-by)/(cx-bx) + return qFuzzyCompare((c.y() - b.y()) * (a.x() - b.x()), (a.y() - b.y()) * (c.x() - b.x())); +} + +static inline bool withinRange(qreal p, qreal a, qreal b) +{ + return (p >= a && p <= b) || (p >= b && p <= a); +} + // Check whether a point is on the border -bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) +static bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) { // null border doesn't contain points if (border.isEmpty()) @@ -81,15 +92,12 @@ bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) for (int i = 1; i < border.size(); ++i) { p2 = border.at(i); - // (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) && (y2-y1)(x-x1) == (y-y1)(x2-x1) - // In which, (y2-y1)(x-x1) == (y-y1)(x2-x1) is from (y2-y1)/(x2-x1) == (y-y1)/(x-x1) - // it want to check the slope between p1 and p2 is same with slope between p and p1, - // if so then the three points lie on the same line. - // In which, (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) want to make sure p is - // between p1 and p2, not outside. - if (((p.x() <= p1.x() && p.x() >= p2.x()) || (p.x() >= p1.x() && p.x() <= p2.x())) - && ((p.y() <= p1.y() && p.y() >= p2.y()) || (p.y() >= p1.y() && p.y() <= p2.y())) - && (p2.y() - p1.y()) * (p.x() - p1.x()) == (p.y() - p1.y()) * (p2.x() - p1.x())) { + if (areCollinear(p, p1, p2) + // Once we know that the points are collinear we + // only need to check one of the coordinates + && (qAbs(p2.x() - p1.x()) > qAbs(p2.y() - p1.y()) ? + withinRange(p.x(), p1.x(), p2.x()) : + withinRange(p.y(), p1.y(), p2.y()))) { return true; } p1 = p2; @@ -212,19 +220,14 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) float p1p2_length = sqrtf(p1p2.x() * p1p2.x() + p1p2.y() * p1p2.y()); double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length); - // all points on a line logic - if (cos_phi == -1) { + + // The points p0, p1, and p2 are on the same straight line (HTML5, 4.8.11.1.8) + // We could have used areCollinear() here, but since we're reusing + // the variables computed above later on we keep this logic. + if (qFuzzyCompare(qAbs(cos_phi), 1.0)) { m_path.lineTo(p1); return; } - if (cos_phi == 1) { - // add infinite far away point - unsigned int max_length = 65535; - double factor_max = max_length / p1p0_length; - FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y())); - m_path.lineTo(ep); - return; - } float tangent = radius / tan(acos(cos_phi) / 2); float factor_p1p0 = tangent / p1p0_length; diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index 62e2f17..ee0a874 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -63,7 +63,7 @@ bool GraphicsContext3D::getImageData(Image* image, if (!premultiplyAlpha) // FIXME: must fetch the image data before the premultiplication step neededAlphaOp = kAlphaDoUnmultiply; - return packPixels(pixels, kSourceFormatBGRA8, skiaImage->width(), height, + return packPixels(pixels, kSourceFormatBGRA8, skiaImage->width(), height, 0, format, type, neededAlphaOp, outputVector.data()); } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 74d0c6e..793fe72 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -478,6 +478,17 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, } } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT!! +} + // This method is only used to draw the little circles used in lists. void GraphicsContext::drawEllipse(const IntRect& elipseRect) { diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp index 7387a14..94df6ae 100644 --- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp @@ -84,6 +84,12 @@ GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha) } } +static void setRGBABitmapAlpha(unsigned char* bytes, size_t length, unsigned char level) +{ + for (size_t i = 0; i < length; i += 4) + bytes[i + 3] = level; +} + void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { if (!mayCreateBitmap || !hdc || !inTransparencyLayer()) { @@ -100,9 +106,16 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo GetObject(bitmap, sizeof(info), &info); ASSERT(info.bmBitsPixel == 32); + // If this context does not support alpha blending, then it may have + // been drawn with GDI functions which always set the alpha channel + // to zero. We need to manually set the bitmap to be fully opaque. + unsigned char* bytes = reinterpret_cast<unsigned char*>(info.bmBits); + if (!supportAlphaBlend) + setRGBABitmapAlpha(bytes, info.bmHeight * info.bmWidthBytes, 255); + // Need to make a cairo_surface_t out of the bitmap's pixel buffer and then draw // it into our context. - cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, + cairo_surface_t* image = cairo_image_surface_create_for_data(bytes, CAIRO_FORMAT_ARGB32, info.bmWidth, info.bmHeight, @@ -111,9 +124,10 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo // Scale the target surface to the new image size, and flip it // so that when we set the srcImage as the surface it will draw // right-side-up. - cairo_translate(m_data->cr, 0, dstRect.height()); - cairo_scale(m_data->cr, dstRect.width(), -dstRect.height()); - cairo_set_source_surface (m_data->cr, image, dstRect.x(), dstRect.y()); + cairo_save(m_data->cr); + cairo_translate(m_data->cr, dstRect.x(), dstRect.height() + dstRect.y()); + cairo_scale(m_data->cr, 1.0, -1.0); + cairo_set_source_surface(m_data->cr, image, 0, 0); if (m_data->layers.size()) cairo_paint_with_alpha(m_data->cr, m_data->layers.last()); @@ -124,6 +138,7 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo cairo_surface_destroy(image); ::DeleteDC(hdc); ::DeleteObject(bitmap); + cairo_restore(m_data->cr); } void GraphicsContextPlatformPrivate::syncContext(PlatformGraphicsContext* cr) diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp index 2ca1a96..e664f2a 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp @@ -28,9 +28,12 @@ #include "IntRect.h" #include "WebCoreInstanceHandle.h" -#include <CoreGraphics/CGColor.h> #include <windows.h> +#if PLATFORM(CG) +#include <CoreGraphics/CGColor.h> +#endif + namespace WebCore { MediaPlayerPrivateFullscreenWindow::MediaPlayerPrivateFullscreenWindow(MediaPlayerPrivateFullscreenClient* client) diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp index afea10a..bceec2d 100644 --- a/WebCore/platform/graphics/win/UniscribeController.cpp +++ b/WebCore/platform/graphics/win/UniscribeController.cpp @@ -287,9 +287,16 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S roundingHackCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos; int boundary = k + m_currentCharacter + item.iCharPos; - if (boundary < m_run.length() && - Font::isRoundingHackCharacter(*(str + k + 1))) - roundingHackWordBoundaries[clusters[k]] = boundary; + if (boundary < m_run.length()) { + // When at the last character in the str, don't look one past the end for a rounding hack character. + // Instead look ahead to the first character of next item, if there is a next one. + if (k + 1 == len) { + if (i + 2 < m_items.size() // Check for at least 2 items remaining. The last item is a terminating item containing no characters. + && Font::isRoundingHackCharacter(*(cp + m_items[i + 1].iCharPos))) + roundingHackWordBoundaries[clusters[k]] = boundary; + } else if (Font::isRoundingHackCharacter(*(str + k + 1))) + roundingHackWordBoundaries[clusters[k]] = boundary; + } } // Populate our glyph buffer with this information. diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index c2c29c7..7bc6a27 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -948,6 +948,17 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points } } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT!! +} + void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { if (paintingDisabled() || !m_data->m_opacity) diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 0b6c81b..5968ef3 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -256,6 +256,17 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points delete [] polygon; } +void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points) +{ + if (paintingDisabled()) + return; + + if (numPoints <= 1) + return; + + // FIXME: IMPLEMENT!! +} + void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) |