summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/FloatRect.h1
-rw-r--r--WebCore/platform/graphics/GlyphMetricsMap.h3
-rw-r--r--WebCore/platform/graphics/Gradient.h2
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h1
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.cpp324
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h34
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h4
-rw-r--r--WebCore/platform/graphics/IntRect.h5
-rw-r--r--WebCore/platform/graphics/TextRun.h19
-rw-r--r--WebCore/platform/graphics/WidthIterator.cpp7
-rw-r--r--WebCore/platform/graphics/cairo/DrawErrorUnderline.h99
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp31
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp2
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp28
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm447
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/FontRenderStyle.h18
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp30
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.h1
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp8
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp33
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp37
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp11
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformDataMac.mm2
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.mm14
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h1
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm6
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm10
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm2
-rw-r--r--WebCore/platform/graphics/qt/FloatRectQt.cpp15
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GradientQt.cpp4
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp18
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.cpp135
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp17
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp43
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp2
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp11
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp23
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp5
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.cpp13
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWince.cpp11
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp11
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())