summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-12-17 09:55:06 -0800
committerAndroid Git Automerger <android-git-automerger@android.com>2009-12-17 09:55:06 -0800
commitb880d713c04257ca40abfef97c300afdead423b8 (patch)
tree6982576c228bcd1a7efe98afed544d840751094c /WebCore/platform/graphics
parente2e7a5c57b53f01e63a0245b4420d54b454cb373 (diff)
parent643ca7872b450ea4efacab6188849e5aac2ba161 (diff)
downloadexternal_webkit-b880d713c04257ca40abfef97c300afdead423b8.zip
external_webkit-b880d713c04257ca40abfef97c300afdead423b8.tar.gz
external_webkit-b880d713c04257ca40abfef97c300afdead423b8.tar.bz2
am 643ca787: Merge webkit.org at r51976 : Initial merge by git.
Merge commit '643ca7872b450ea4efacab6188849e5aac2ba161' into eclair-mr2-plus-aosp * commit '643ca7872b450ea4efacab6188849e5aac2ba161': Merge webkit.org at r51976 : Initial merge by git.
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/BitmapImage.h10
-rw-r--r--WebCore/platform/graphics/Color.h3
-rw-r--r--WebCore/platform/graphics/ColorSpace.h35
-rw-r--r--WebCore/platform/graphics/FloatRect.cpp10
-rw-r--r--WebCore/platform/graphics/FloatRect.h3
-rw-r--r--WebCore/platform/graphics/FontCache.h2
-rw-r--r--WebCore/platform/graphics/GeneratedImage.cpp6
-rw-r--r--WebCore/platform/graphics/GeneratedImage.h4
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp90
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h63
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h490
-rw-r--r--WebCore/platform/graphics/GraphicsContextPrivate.h30
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.cpp15
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h12
-rw-r--r--WebCore/platform/graphics/GraphicsLayerClient.h3
-rw-r--r--WebCore/platform/graphics/Icon.h1
-rw-r--r--WebCore/platform/graphics/Image.cpp18
-rw-r--r--WebCore/platform/graphics/Image.h14
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp15
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h14
-rw-r--r--WebCore/platform/graphics/MediaPlayerPrivate.h5
-rw-r--r--WebCore/platform/graphics/Path.h3
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp32
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp281
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp4
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp39
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp14
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp229
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h19
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp49
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp31
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.h4
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.cpp17
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.h2
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp17
-rw-r--r--WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp135
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumLinux.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumMac.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/IconChromiumWin.cpp19
-rw-r--r--WebCore/platform/graphics/chromium/TransparencyWin.cpp2
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp2
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp2
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp24
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.cpp10
-rw-r--r--WebCore/platform/graphics/filters/Filter.h15
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h8
-rw-r--r--WebCore/platform/graphics/filters/ImageBufferFilter.cpp43
-rw-r--r--WebCore/platform/graphics/filters/ImageBufferFilter.h57
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp4
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.cpp4
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp2
-rw-r--r--WebCore/platform/graphics/gtk/IconGtk.cpp26
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp330
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h6
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp2
-rw-r--r--WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp84
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp10
-rw-r--r--WebCore/platform/graphics/haiku/IconHaiku.cpp6
-rw-r--r--WebCore/platform/graphics/haiku/ImageHaiku.cpp6
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.cpp (renamed from WebCore/platform/graphics/mac/CoreTextController.cpp)273
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.h162
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp341
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp144
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.h116
-rw-r--r--WebCore/platform/graphics/mac/FontComplexTextMac.cpp (renamed from WebCore/platform/graphics/mac/FontMacCoreText.cpp)38
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp9
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm7
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm635
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp733
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h1
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm57
-rw-r--r--WebCore/platform/graphics/mac/IconMac.mm35
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h3
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm32
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp68
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeSanitizer.h57
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp2
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp245
-rw-r--r--WebCore/platform/graphics/qt/FontCustomPlatformData.cpp2
-rw-r--r--WebCore/platform/graphics/qt/FontFallbackListQt.cpp138
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformData.h120
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformDataQt.cpp116
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp3
-rw-r--r--WebCore/platform/graphics/qt/FontQt43.cpp354
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp69
-rw-r--r--WebCore/platform/graphics/qt/IconQt.cpp16
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp10
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp49
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp8
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.h2
-rw-r--r--WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h2
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp24
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp16
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp4
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp16
-rw-r--r--WebCore/platform/graphics/transforms/TransformOperations.h2
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.h3
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp6
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp4
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp4
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.cpp721
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.h144
-rw-r--r--WebCore/platform/graphics/win/IconWin.cpp22
-rw-r--r--WebCore/platform/graphics/win/ImageCGWin.cpp10
-rw-r--r--WebCore/platform/graphics/win/ImageCairoWin.cpp10
-rw-r--r--WebCore/platform/graphics/win/IntPointWin.cpp1
-rw-r--r--WebCore/platform/graphics/win/IntRectWin.cpp2
-rw-r--r--WebCore/platform/graphics/win/IntSizeWin.cpp1
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp14
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h9
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.cpp35
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.h3
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.cpp88
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.h60
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.cpp359
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.h248
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp449
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.h106
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWince.cpp20
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformDataWx.cpp2
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp82
-rw-r--r--WebCore/platform/graphics/wx/IconWx.cpp6
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp8
126 files changed, 5425 insertions, 3307 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
index 13641d2..a07daf2 100644
--- a/WebCore/platform/graphics/BitmapImage.h
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -140,8 +140,10 @@ public:
virtual CGImageRef getCGImageRef();
#endif
-#if PLATFORM(WIN)
+#if PLATFORM(WIN) || (PLATFORM(QT) && PLATFORM(WIN_OS))
static PassRefPtr<BitmapImage> create(HBITMAP);
+#endif
+#if PLATFORM(WIN)
virtual bool getHBITMAP(HBITMAP);
virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE);
#endif
@@ -167,13 +169,13 @@ protected:
BitmapImage(ImageObserver* = 0);
#if PLATFORM(WIN)
- virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator);
+ virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator);
#endif
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
#if PLATFORM(WX) || (PLATFORM(WINCE) && !PLATFORM(QT))
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
#endif
#if PLATFORM(HAIKU)
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
index 8e51b95..c348166 100644
--- a/WebCore/platform/graphics/Color.h
+++ b/WebCore/platform/graphics/Color.h
@@ -26,6 +26,7 @@
#ifndef Color_h
#define Color_h
+#include <wtf/FastAllocBase.h>
#include <wtf/Platform.h>
#if PLATFORM(CG)
@@ -68,7 +69,7 @@ RGBA32 makeRGBAFromCMYKA(float c, float m, float y, float k, float a);
int differenceSquared(const Color&, const Color&);
-class Color {
+class Color : public FastAllocBase {
public:
Color() : m_color(0), m_valid(false) { }
Color(RGBA32 col) : m_color(col), m_valid(true) { }
diff --git a/WebCore/platform/graphics/ColorSpace.h b/WebCore/platform/graphics/ColorSpace.h
new file mode 100644
index 0000000..1bad58c
--- /dev/null
+++ b/WebCore/platform/graphics/ColorSpace.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ColorSpace_h
+#define ColorSpace_h
+
+namespace WebCore {
+
+ enum ColorSpace { DeviceColorSpace, sRGBColorSpace };
+
+} // namespace WebCore
+
+#endif // ColorSpace_h
diff --git a/WebCore/platform/graphics/FloatRect.cpp b/WebCore/platform/graphics/FloatRect.cpp
index 532f719..7a54f21 100644
--- a/WebCore/platform/graphics/FloatRect.cpp
+++ b/WebCore/platform/graphics/FloatRect.cpp
@@ -102,12 +102,12 @@ void FloatRect::unite(const FloatRect& other)
m_size.setHeight(b - t);
}
-void FloatRect::scale(float s)
+void FloatRect::scale(float sx, float sy)
{
- m_location.setX(x() * s);
- m_location.setY(y() * s);
- m_size.setWidth(width() * s);
- m_size.setHeight(height() * s);
+ m_location.setX(x() * sx);
+ m_location.setY(y() * sy);
+ m_size.setWidth(width() * sx);
+ m_size.setHeight(height() * sy);
}
IntRect enclosingIntRect(const FloatRect& rect)
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
index 50cb095..4b4694f 100644
--- a/WebCore/platform/graphics/FloatRect.h
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -120,7 +120,8 @@ public:
m_size.setHeight(m_size.height() + dy + dy);
}
void inflate(float d) { inflateX(d); inflateY(d); }
- void scale(float s);
+ void scale(float s) { scale(s, s); }
+ void scale(float sx, float sy);
#if PLATFORM(CG)
FloatRect(const CGRect&);
diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h
index b88305f..4a6222b 100644
--- a/WebCore/platform/graphics/FontCache.h
+++ b/WebCore/platform/graphics/FontCache.h
@@ -50,7 +50,7 @@ class FontDescription;
class FontSelector;
class SimpleFontData;
-class FontCache {
+class FontCache : public Noncopyable {
public:
friend FontCache* fontCache();
diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp
index bac9da0..eec7ffb 100644
--- a/WebCore/platform/graphics/GeneratedImage.cpp
+++ b/WebCore/platform/graphics/GeneratedImage.cpp
@@ -34,7 +34,7 @@ using namespace std;
namespace WebCore {
-void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp)
{
context->save();
context->setCompositeOperation(compositeOp);
@@ -48,7 +48,7 @@ void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, co
}
void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator compositeOp, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect)
{
// Create a BitmapImage and call drawPattern on it.
OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(m_size);
@@ -62,7 +62,7 @@ void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcR
Image* bitmap = imageBuffer->image();
// Now just call drawTiled on that image.
- bitmap->drawPattern(context, srcRect, patternTransform, phase, compositeOp, destRect);
+ bitmap->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect);
}
}
diff --git a/WebCore/platform/graphics/GeneratedImage.h b/WebCore/platform/graphics/GeneratedImage.h
index dea0c54..a4583e3 100644
--- a/WebCore/platform/graphics/GeneratedImage.h
+++ b/WebCore/platform/graphics/GeneratedImage.h
@@ -57,9 +57,9 @@ public:
virtual unsigned decodedSize() const { return 0; }
protected:
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
GeneratedImage(PassRefPtr<Generator> generator, const IntSize& size)
: m_generator(generator)
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index ccdce08..fee05ee 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -120,24 +120,21 @@ void GraphicsContext::setStrokeStyle(const StrokeStyle& style)
setPlatformStrokeStyle(style);
}
-void GraphicsContext::setStrokeColor(const Color& color)
+void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace)
{
- m_common->state.strokeColorSpace = SolidColorSpace;
m_common->state.strokeColor = color;
- setPlatformStrokeColor(color);
+ m_common->state.strokeColorSpace = colorSpace;
+ m_common->state.strokeGradient.clear();
+ m_common->state.strokePattern.clear();
+ setPlatformStrokeColor(color, colorSpace);
}
-ColorSpace GraphicsContext::strokeColorSpace() const
-{
- return m_common->state.strokeColorSpace;
-}
-
-void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color)
+void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
{
m_common->state.shadowSize = size;
m_common->state.shadowBlur = blur;
m_common->state.shadowColor = color;
- setPlatformShadow(size, blur, color);
+ setPlatformShadow(size, blur, color, colorSpace);
}
void GraphicsContext::clearShadow()
@@ -172,6 +169,11 @@ Color GraphicsContext::strokeColor() const
return m_common->state.strokeColor;
}
+ColorSpace GraphicsContext::strokeColorSpace() const
+{
+ return m_common->state.strokeColorSpace;
+}
+
WindRule GraphicsContext::fillRule() const
{
return m_common->state.fillRule;
@@ -182,11 +184,13 @@ void GraphicsContext::setFillRule(WindRule fillRule)
m_common->state.fillRule = fillRule;
}
-void GraphicsContext::setFillColor(const Color& color)
+void GraphicsContext::setFillColor(const Color& color, ColorSpace colorSpace)
{
- m_common->state.fillColorSpace = SolidColorSpace;
m_common->state.fillColor = color;
- setPlatformFillColor(color);
+ m_common->state.fillColorSpace = colorSpace;
+ m_common->state.fillGradient.clear();
+ m_common->state.fillPattern.clear();
+ setPlatformFillColor(color, colorSpace);
}
Color GraphicsContext::fillColor() const
@@ -194,6 +198,11 @@ Color GraphicsContext::fillColor() const
return m_common->state.fillColor;
}
+ColorSpace GraphicsContext::fillColorSpace() const
+{
+ return m_common->state.fillColorSpace;
+}
+
void GraphicsContext::setShouldAntialias(bool b)
{
m_common->state.shouldAntialias = b;
@@ -209,10 +218,10 @@ void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
if (!pattern) {
- setStrokeColor(Color::black);
+ setStrokeColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.strokeColorSpace = PatternColorSpace;
+ m_common->state.strokeGradient.clear();
m_common->state.strokePattern = pattern;
setPlatformStrokePattern(m_common->state.strokePattern.get());
}
@@ -221,10 +230,10 @@ void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
{
ASSERT(pattern);
if (!pattern) {
- setFillColor(Color::black);
+ setFillColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.fillColorSpace = PatternColorSpace;
+ m_common->state.fillGradient.clear();
m_common->state.fillPattern = pattern;
setPlatformFillPattern(m_common->state.fillPattern.get());
}
@@ -233,11 +242,11 @@ void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
{
ASSERT(gradient);
if (!gradient) {
- setStrokeColor(Color::black);
+ setStrokeColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.strokeColorSpace = GradientColorSpace;
m_common->state.strokeGradient = gradient;
+ m_common->state.strokePattern.clear();
setPlatformStrokeGradient(m_common->state.strokeGradient.get());
}
@@ -245,11 +254,11 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
{
ASSERT(gradient);
if (!gradient) {
- setFillColor(Color::black);
+ setFillColor(Color::black, DeviceColorSpace);
return;
}
- m_common->state.fillColorSpace = GradientColorSpace;
m_common->state.fillGradient = gradient;
+ m_common->state.fillPattern.clear();
setPlatformFillGradient(m_common->state.fillGradient.get());
}
@@ -258,11 +267,6 @@ Gradient* GraphicsContext::fillGradient() const
return m_common->state.fillGradient.get();
}
-ColorSpace GraphicsContext::fillColorSpace() const
-{
- return m_common->state.fillColorSpace;
-}
-
Gradient* GraphicsContext::strokeGradient() const
{
return m_common->state.strokeGradient.get();
@@ -304,24 +308,24 @@ bool GraphicsContext::paintingDisabled() const
return m_common->state.paintingDisabled;
}
-void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
{
- drawImage(image, p, IntRect(0, 0, -1, -1), op);
+ drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
}
-void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
{
- drawImage(image, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
+ drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
}
-void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
{
- drawImage(image, IntRect(dest, srcRect.size()), srcRect, op);
+ drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
}
-void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
{
- drawImage(image, FloatRect(dest), srcRect, op, useLowQualityScale);
+ drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
}
#if !PLATFORM(WINCE) || PLATFORM(QT)
@@ -370,12 +374,12 @@ void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const F
bidiResolver.deleteRuns();
}
-void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const IntPoint& point, int h, const Color& backgroundColor, int from, int to)
+void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const IntPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to)
{
if (paintingDisabled())
return;
- fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor);
+ fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
}
void GraphicsContext::initFocusRing(int width, int offset)
@@ -427,7 +431,7 @@ const Vector<IntRect>& GraphicsContext::focusRingRects() const
return m_common->m_focusRingRects;
}
-void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
{
if (paintingDisabled() || !image)
return;
@@ -451,29 +455,29 @@ void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
save();
setImageInterpolationQuality(InterpolationNone);
}
- image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op);
+ image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), styleColorSpace, op);
if (useLowQualityScale)
restore();
}
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op)
+void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op)
{
if (paintingDisabled() || !image)
return;
- image->drawTiled(this, rect, srcPoint, tileSize, op);
+ image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op);
}
-void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
+void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
{
if (paintingDisabled() || !image)
return;
if (hRule == Image::StretchTile && vRule == Image::StretchTile)
// Just do a scale.
- return drawImage(image, dest, srcRect, op);
+ return drawImage(image, styleColorSpace, dest, srcRect, op);
- image->drawTiled(this, dest, srcRect, hRule, vRule, op);
+ image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op);
}
void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 3ffc211..96a6221 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008-2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,7 @@
#ifndef GraphicsContext_h
#define GraphicsContext_h
+#include "ColorSpace.h"
#include "DashArray.h"
#include "FloatRect.h"
#include "Image.h"
@@ -111,17 +112,17 @@ namespace WebCore {
const int cMisspellingLinePatternWidth = 4;
const int cMisspellingLinePatternGapWidth = 1;
- class TransformationMatrix;
class Font;
class Generator;
class Gradient;
- class GraphicsContextPrivate;
class GraphicsContextPlatformPrivate;
+ class GraphicsContextPrivate;
class ImageBuffer;
class KURL;
class Path;
class Pattern;
class TextRun;
+ class TransformationMatrix;
// These bits can be ORed together for a total of 8 possible text drawing modes.
const int cTextInvisible = 0;
@@ -136,18 +137,6 @@ namespace WebCore {
DashedStroke
};
- // FIXME: This is a place-holder until we decide to add
- // real color space support to WebCore. At that time, ColorSpace will be a
- // class and instances will be held off of Colors. There will be
- // special singleton Gradient and Pattern color spaces to mark when
- // a fill or stroke is using a gradient or pattern instead of a solid color.
- // https://bugs.webkit.org/show_bug.cgi?id=20558
- enum ColorSpace {
- SolidColorSpace,
- PatternColorSpace,
- GradientColorSpace
- };
-
enum InterpolationQuality {
InterpolationDefault,
InterpolationNone,
@@ -170,9 +159,8 @@ namespace WebCore {
StrokeStyle strokeStyle() const;
void setStrokeStyle(const StrokeStyle& style);
Color strokeColor() const;
- void setStrokeColor(const Color&);
-
ColorSpace strokeColorSpace() const;
+ void setStrokeColor(const Color&, ColorSpace);
void setStrokePattern(PassRefPtr<Pattern>);
Pattern* strokePattern() const;
@@ -183,7 +171,8 @@ namespace WebCore {
WindRule fillRule() const;
void setFillRule(WindRule);
Color fillColor() const;
- void setFillColor(const Color&);
+ ColorSpace fillColorSpace() const;
+ void setFillColor(const Color&, ColorSpace);
void setFillPattern(PassRefPtr<Pattern>);
Pattern* fillPattern() const;
@@ -191,8 +180,6 @@ namespace WebCore {
void setFillGradient(PassRefPtr<Gradient>);
Gradient* fillGradient() const;
- ColorSpace fillColorSpace() const;
-
void setShadowsIgnoreTransforms(bool);
void setShouldAntialias(bool);
@@ -250,24 +237,24 @@ namespace WebCore {
void strokeArc(const IntRect&, int startAngle, int angleSpan);
void fillRect(const FloatRect&);
- void fillRect(const FloatRect&, const Color&);
+ void fillRect(const FloatRect&, const Color&, ColorSpace);
void fillRect(const FloatRect&, Generator&);
- void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&);
+ void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&, ColorSpace);
void clearRect(const FloatRect&);
void strokeRect(const FloatRect&);
void strokeRect(const FloatRect&, float lineWidth);
- void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver);
- void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawImage(Image*, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
- void drawImage(Image*, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
+ void drawImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
- void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
+ void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
CompositeOperator = CompositeSourceOver);
- void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
+ void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect,
Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
CompositeOperator = CompositeSourceOver);
@@ -288,7 +275,7 @@ namespace WebCore {
void drawText(const Font&, const TextRun&, const IntPoint&, int from = 0, int to = -1);
void drawBidiText(const Font&, const TextRun&, const FloatPoint&);
- void drawHighlightForText(const Font&, const TextRun&, const IntPoint&, int h, const Color& backgroundColor, int from = 0, int to = -1);
+ void drawHighlightForText(const Font&, const TextRun&, const IntPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1);
FloatRect roundToDevicePixels(const FloatRect&);
@@ -304,7 +291,7 @@ namespace WebCore {
void beginTransparencyLayer(float opacity);
void endTransparencyLayer();
- void setShadow(const IntSize&, int blur, const Color&);
+ void setShadow(const IntSize&, int blur, const Color&, ColorSpace);
bool getShadow(IntSize&, int&, Color&) const;
void clearShadow();
@@ -322,6 +309,8 @@ namespace WebCore {
void setAlpha(float);
#if PLATFORM(CAIRO)
float getAlpha();
+ void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize);
+ static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur);
#endif
void setCompositeOperation(CompositeOperator);
@@ -405,12 +394,16 @@ namespace WebCore {
void drawWindowsBitmap(WindowsBitmap*, const IntPoint&);
#endif
-#if PLATFORM(QT) && defined(Q_WS_WIN)
+#if (PLATFORM(QT) && defined(Q_WS_WIN)) || (PLATFORM(WX) && PLATFORM(WIN_OS))
HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);
void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true);
bool shouldIncludeChildWindows() const { return false; }
#endif
+#if PLATFORM(WX)
+ bool inTransparencyLayer() const { return false; }
+#endif
+
#if PLATFORM(QT)
bool inTransparencyLayer() const;
PlatformPath* currentPath();
@@ -434,19 +427,19 @@ namespace WebCore {
void setPlatformTextDrawingMode(int);
void setPlatformFont(const Font& font);
- void setPlatformStrokeColor(const Color&);
+ void setPlatformStrokeColor(const Color&, ColorSpace);
void setPlatformStrokeStyle(const StrokeStyle&);
void setPlatformStrokeThickness(float);
void setPlatformStrokeGradient(Gradient*);
void setPlatformStrokePattern(Pattern*);
- void setPlatformFillColor(const Color&);
+ void setPlatformFillColor(const Color&, ColorSpace);
void setPlatformFillGradient(Gradient*);
void setPlatformFillPattern(Pattern*);
void setPlatformShouldAntialias(bool b);
- void setPlatformShadow(const IntSize&, int blur, const Color&);
+ void setPlatformShadow(const IntSize&, int blur, const Color&, ColorSpace);
void clearPlatformShadow();
static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&);
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index 07ec04d..aad8dd4 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -28,9 +28,15 @@
#include "PlatformString.h"
+#include <wtf/ListHashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
+// FIXME: Find a better way to avoid the name confliction for NO_ERROR.
+#if PLATFORM(CHROMIUM) && PLATFORM(WIN_OS)
+#undef NO_ERROR
+#endif
+
#if PLATFORM(MAC)
#include <OpenGL/OpenGL.h>
@@ -46,20 +52,19 @@ const Platform3DObject NullPlatform3DObject = 0;
#endif
namespace WebCore {
- class CanvasActiveInfo;
- class CanvasArray;
- class CanvasBuffer;
- class CanvasUnsignedByteArray;
- class CanvasFloatArray;
- class CanvasFramebuffer;
- class CanvasIntArray;
- class CanvasProgram;
- class CanvasRenderbuffer;
- class CanvasRenderingContext3D;
- class CanvasShader;
- class CanvasTexture;
- class HTMLCanvasElement;
- class HTMLImageElement;
+ class WebGLActiveInfo;
+ class WebGLArray;
+ class WebGLBuffer;
+ class WebGLUnsignedByteArray;
+ class WebGLFloatArray;
+ class WebGLFramebuffer;
+ class WebGLIntArray;
+ class WebGLProgram;
+ class WebGLRenderbuffer;
+ class WebGLRenderingContext;
+ class WebGLShader;
+ class WebGLTexture;
+ class Image;
class HTMLVideoElement;
class ImageData;
class WebKitCSSMatrix;
@@ -77,8 +82,309 @@ namespace WebCore {
class GraphicsContext3D : public Noncopyable {
public:
- enum ShaderType { FRAGMENT_SHADER, VERTEX_SHADER };
-
+ enum WebGLEnumType {
+ DEPTH_BUFFER_BIT = 0x00000100,
+ STENCIL_BUFFER_BIT = 0x00000400,
+ COLOR_BUFFER_BIT = 0x00004000,
+ POINTS = 0x0000,
+ LINES = 0x0001,
+ LINE_LOOP = 0x0002,
+ LINE_STRIP = 0x0003,
+ TRIANGLES = 0x0004,
+ TRIANGLE_STRIP = 0x0005,
+ TRIANGLE_FAN = 0x0006,
+ ZERO = 0,
+ ONE = 1,
+ SRC_COLOR = 0x0300,
+ ONE_MINUS_SRC_COLOR = 0x0301,
+ SRC_ALPHA = 0x0302,
+ ONE_MINUS_SRC_ALPHA = 0x0303,
+ DST_ALPHA = 0x0304,
+ ONE_MINUS_DST_ALPHA = 0x0305,
+ DST_COLOR = 0x0306,
+ ONE_MINUS_DST_COLOR = 0x0307,
+ SRC_ALPHA_SATURATE = 0x0308,
+ FUNC_ADD = 0x8006,
+ BLEND_EQUATION = 0x8009,
+ BLEND_EQUATION_RGB = 0x8009,
+ BLEND_EQUATION_ALPHA = 0x883D,
+ FUNC_SUBTRACT = 0x800A,
+ FUNC_REVERSE_SUBTRACT = 0x800B,
+ BLEND_DST_RGB = 0x80C8,
+ BLEND_SRC_RGB = 0x80C9,
+ BLEND_DST_ALPHA = 0x80CA,
+ BLEND_SRC_ALPHA = 0x80CB,
+ CONSTANT_COLOR = 0x8001,
+ ONE_MINUS_CONSTANT_COLOR = 0x8002,
+ CONSTANT_ALPHA = 0x8003,
+ ONE_MINUS_CONSTANT_ALPHA = 0x8004,
+ BLEND_COLOR = 0x8005,
+ ARRAY_BUFFER = 0x8892,
+ ELEMENT_ARRAY_BUFFER = 0x8893,
+ ARRAY_BUFFER_BINDING = 0x8894,
+ ELEMENT_ARRAY_BUFFER_BINDING = 0x8895,
+ STREAM_DRAW = 0x88E0,
+ STATIC_DRAW = 0x88E4,
+ DYNAMIC_DRAW = 0x88E8,
+ BUFFER_SIZE = 0x8764,
+ BUFFER_USAGE = 0x8765,
+ CURRENT_VERTEX_ATTRIB = 0x8626,
+ FRONT = 0x0404,
+ BACK = 0x0405,
+ FRONT_AND_BACK = 0x0408,
+ TEXTURE_2D = 0x0DE1,
+ CULL_FACE = 0x0B44,
+ BLEND = 0x0BE2,
+ DITHER = 0x0BD0,
+ STENCIL_TEST = 0x0B90,
+ DEPTH_TEST = 0x0B71,
+ SCISSOR_TEST = 0x0C11,
+ POLYGON_OFFSET_FILL = 0x8037,
+ SAMPLE_ALPHA_TO_COVERAGE = 0x809E,
+ SAMPLE_COVERAGE = 0x80A0,
+ NO_ERROR = 0,
+ INVALID_ENUM = 0x0500,
+ INVALID_VALUE = 0x0501,
+ INVALID_OPERATION = 0x0502,
+ OUT_OF_MEMORY = 0x0505,
+ CW = 0x0900,
+ CCW = 0x0901,
+ LINE_WIDTH = 0x0B21,
+ ALIASED_POINT_SIZE_RANGE = 0x846D,
+ ALIASED_LINE_WIDTH_RANGE = 0x846E,
+ CULL_FACE_MODE = 0x0B45,
+ FRONT_FACE = 0x0B46,
+ DEPTH_RANGE = 0x0B70,
+ DEPTH_WRITEMASK = 0x0B72,
+ DEPTH_CLEAR_VALUE = 0x0B73,
+ DEPTH_FUNC = 0x0B74,
+ STENCIL_CLEAR_VALUE = 0x0B91,
+ STENCIL_FUNC = 0x0B92,
+ STENCIL_FAIL = 0x0B94,
+ STENCIL_PASS_DEPTH_FAIL = 0x0B95,
+ STENCIL_PASS_DEPTH_PASS = 0x0B96,
+ STENCIL_REF = 0x0B97,
+ STENCIL_VALUE_MASK = 0x0B93,
+ STENCIL_WRITEMASK = 0x0B98,
+ STENCIL_BACK_FUNC = 0x8800,
+ STENCIL_BACK_FAIL = 0x8801,
+ STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802,
+ STENCIL_BACK_PASS_DEPTH_PASS = 0x8803,
+ STENCIL_BACK_REF = 0x8CA3,
+ STENCIL_BACK_VALUE_MASK = 0x8CA4,
+ STENCIL_BACK_WRITEMASK = 0x8CA5,
+ VIEWPORT = 0x0BA2,
+ SCISSOR_BOX = 0x0C10,
+ COLOR_CLEAR_VALUE = 0x0C22,
+ COLOR_WRITEMASK = 0x0C23,
+ UNPACK_ALIGNMENT = 0x0CF5,
+ PACK_ALIGNMENT = 0x0D05,
+ MAX_TEXTURE_SIZE = 0x0D33,
+ MAX_VIEWPORT_DIMS = 0x0D3A,
+ SUBPIXEL_BITS = 0x0D50,
+ RED_BITS = 0x0D52,
+ GREEN_BITS = 0x0D53,
+ BLUE_BITS = 0x0D54,
+ ALPHA_BITS = 0x0D55,
+ DEPTH_BITS = 0x0D56,
+ STENCIL_BITS = 0x0D57,
+ POLYGON_OFFSET_UNITS = 0x2A00,
+ POLYGON_OFFSET_FACTOR = 0x8038,
+ TEXTURE_BINDING_2D = 0x8069,
+ SAMPLE_BUFFERS = 0x80A8,
+ SAMPLES = 0x80A9,
+ SAMPLE_COVERAGE_VALUE = 0x80AA,
+ SAMPLE_COVERAGE_INVERT = 0x80AB,
+ NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2,
+ COMPRESSED_TEXTURE_FORMATS = 0x86A3,
+ DONT_CARE = 0x1100,
+ FASTEST = 0x1101,
+ NICEST = 0x1102,
+ GENERATE_MIPMAP_HINT = 0x8192,
+ BYTE = 0x1400,
+ UNSIGNED_BYTE = 0x1401,
+ SHORT = 0x1402,
+ UNSIGNED_SHORT = 0x1403,
+ INT = 0x1404,
+ UNSIGNED_INT = 0x1405,
+ FLOAT = 0x1406,
+ FIXED = 0x140C,
+ DEPTH_COMPONENT = 0x1902,
+ ALPHA = 0x1906,
+ RGB = 0x1907,
+ RGBA = 0x1908,
+ LUMINANCE = 0x1909,
+ LUMINANCE_ALPHA = 0x190A,
+ UNSIGNED_SHORT_4_4_4_4 = 0x8033,
+ UNSIGNED_SHORT_5_5_5_1 = 0x8034,
+ UNSIGNED_SHORT_5_6_5 = 0x8363,
+ FRAGMENT_SHADER = 0x8B30,
+ VERTEX_SHADER = 0x8B31,
+ MAX_VERTEX_ATTRIBS = 0x8869,
+ MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB,
+ MAX_VARYING_VECTORS = 0x8DFC,
+ MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D,
+ MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C,
+ MAX_TEXTURE_IMAGE_UNITS = 0x8872,
+ MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD,
+ SHADER_TYPE = 0x8B4F,
+ DELETE_STATUS = 0x8B80,
+ LINK_STATUS = 0x8B82,
+ VALIDATE_STATUS = 0x8B83,
+ ATTACHED_SHADERS = 0x8B85,
+ ACTIVE_UNIFORMS = 0x8B86,
+ ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
+ ACTIVE_ATTRIBUTES = 0x8B89,
+ ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
+ SHADING_LANGUAGE_VERSION = 0x8B8C,
+ CURRENT_PROGRAM = 0x8B8D,
+ NEVER = 0x0200,
+ LESS = 0x0201,
+ EQUAL = 0x0202,
+ LEQUAL = 0x0203,
+ GREATER = 0x0204,
+ NOTEQUAL = 0x0205,
+ GEQUAL = 0x0206,
+ ALWAYS = 0x0207,
+ KEEP = 0x1E00,
+ REPLACE = 0x1E01,
+ INCR = 0x1E02,
+ DECR = 0x1E03,
+ INVERT = 0x150A,
+ INCR_WRAP = 0x8507,
+ DECR_WRAP = 0x8508,
+ VENDOR = 0x1F00,
+ RENDERER = 0x1F01,
+ VERSION = 0x1F02,
+ EXTENSIONS = 0x1F03,
+ NEAREST = 0x2600,
+ LINEAR = 0x2601,
+ NEAREST_MIPMAP_NEAREST = 0x2700,
+ LINEAR_MIPMAP_NEAREST = 0x2701,
+ NEAREST_MIPMAP_LINEAR = 0x2702,
+ LINEAR_MIPMAP_LINEAR = 0x2703,
+ TEXTURE_MAG_FILTER = 0x2800,
+ TEXTURE_MIN_FILTER = 0x2801,
+ TEXTURE_WRAP_S = 0x2802,
+ TEXTURE_WRAP_T = 0x2803,
+ TEXTURE = 0x1702,
+ TEXTURE_CUBE_MAP = 0x8513,
+ TEXTURE_BINDING_CUBE_MAP = 0x8514,
+ TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515,
+ TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516,
+ TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517,
+ TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518,
+ TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519,
+ TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A,
+ MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C,
+ TEXTURE0 = 0x84C0,
+ TEXTURE1 = 0x84C1,
+ TEXTURE2 = 0x84C2,
+ TEXTURE3 = 0x84C3,
+ TEXTURE4 = 0x84C4,
+ TEXTURE5 = 0x84C5,
+ TEXTURE6 = 0x84C6,
+ TEXTURE7 = 0x84C7,
+ TEXTURE8 = 0x84C8,
+ TEXTURE9 = 0x84C9,
+ TEXTURE10 = 0x84CA,
+ TEXTURE11 = 0x84CB,
+ TEXTURE12 = 0x84CC,
+ TEXTURE13 = 0x84CD,
+ TEXTURE14 = 0x84CE,
+ TEXTURE15 = 0x84CF,
+ TEXTURE16 = 0x84D0,
+ TEXTURE17 = 0x84D1,
+ TEXTURE18 = 0x84D2,
+ TEXTURE19 = 0x84D3,
+ TEXTURE20 = 0x84D4,
+ TEXTURE21 = 0x84D5,
+ TEXTURE22 = 0x84D6,
+ TEXTURE23 = 0x84D7,
+ TEXTURE24 = 0x84D8,
+ TEXTURE25 = 0x84D9,
+ TEXTURE26 = 0x84DA,
+ TEXTURE27 = 0x84DB,
+ TEXTURE28 = 0x84DC,
+ TEXTURE29 = 0x84DD,
+ TEXTURE30 = 0x84DE,
+ TEXTURE31 = 0x84DF,
+ ACTIVE_TEXTURE = 0x84E0,
+ REPEAT = 0x2901,
+ CLAMP_TO_EDGE = 0x812F,
+ MIRRORED_REPEAT = 0x8370,
+ FLOAT_VEC2 = 0x8B50,
+ FLOAT_VEC3 = 0x8B51,
+ FLOAT_VEC4 = 0x8B52,
+ INT_VEC2 = 0x8B53,
+ INT_VEC3 = 0x8B54,
+ INT_VEC4 = 0x8B55,
+ BOOL = 0x8B56,
+ BOOL_VEC2 = 0x8B57,
+ BOOL_VEC3 = 0x8B58,
+ BOOL_VEC4 = 0x8B59,
+ FLOAT_MAT2 = 0x8B5A,
+ FLOAT_MAT3 = 0x8B5B,
+ FLOAT_MAT4 = 0x8B5C,
+ SAMPLER_2D = 0x8B5E,
+ SAMPLER_CUBE = 0x8B60,
+ VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622,
+ VERTEX_ATTRIB_ARRAY_SIZE = 0x8623,
+ VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624,
+ VERTEX_ATTRIB_ARRAY_TYPE = 0x8625,
+ VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A,
+ VERTEX_ATTRIB_ARRAY_POINTER = 0x8645,
+ VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F,
+ IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A,
+ IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B,
+ COMPILE_STATUS = 0x8B81,
+ INFO_LOG_LENGTH = 0x8B84,
+ SHADER_SOURCE_LENGTH = 0x8B88,
+ SHADER_COMPILER = 0x8DFA,
+ SHADER_BINARY_FORMATS = 0x8DF8,
+ NUM_SHADER_BINARY_FORMATS = 0x8DF9,
+ LOW_FLOAT = 0x8DF0,
+ MEDIUM_FLOAT = 0x8DF1,
+ HIGH_FLOAT = 0x8DF2,
+ LOW_INT = 0x8DF3,
+ MEDIUM_INT = 0x8DF4,
+ HIGH_INT = 0x8DF5,
+ FRAMEBUFFER = 0x8D40,
+ RENDERBUFFER = 0x8D41,
+ RGBA4 = 0x8056,
+ RGB5_A1 = 0x8057,
+ RGB565 = 0x8D62,
+ DEPTH_COMPONENT16 = 0x81A5,
+ STENCIL_INDEX = 0x1901,
+ STENCIL_INDEX8 = 0x8D48,
+ RENDERBUFFER_WIDTH = 0x8D42,
+ RENDERBUFFER_HEIGHT = 0x8D43,
+ RENDERBUFFER_INTERNAL_FORMAT = 0x8D44,
+ RENDERBUFFER_RED_SIZE = 0x8D50,
+ RENDERBUFFER_GREEN_SIZE = 0x8D51,
+ RENDERBUFFER_BLUE_SIZE = 0x8D52,
+ RENDERBUFFER_ALPHA_SIZE = 0x8D53,
+ RENDERBUFFER_DEPTH_SIZE = 0x8D54,
+ RENDERBUFFER_STENCIL_SIZE = 0x8D55,
+ FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0,
+ FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1,
+ FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2,
+ FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3,
+ COLOR_ATTACHMENT0 = 0x8CE0,
+ DEPTH_ATTACHMENT = 0x8D00,
+ STENCIL_ATTACHMENT = 0x8D20,
+ NONE = 0,
+ FRAMEBUFFER_COMPLETE = 0x8CD5,
+ FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6,
+ FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7,
+ FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9,
+ FRAMEBUFFER_UNSUPPORTED = 0x8CDD,
+ FRAMEBUFFER_BINDING = 0x8CA6,
+ RENDERBUFFER_BINDING = 0x8CA7,
+ MAX_RENDERBUFFER_SIZE = 0x84E8,
+ INVALID_FRAMEBUFFER_OPERATION = 0x0506
+ };
+
static PassOwnPtr<GraphicsContext3D> create();
virtual ~GraphicsContext3D();
@@ -92,7 +398,6 @@ namespace WebCore {
PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; }
Platform3DObject platformTexture() const { return NullPlatform3DObject; }
#endif
- void checkError() const;
void makeContextCurrent();
// Helper to return the size in bytes of OpenGL data types
@@ -100,12 +405,12 @@ namespace WebCore {
int sizeInBytes(int type);
void activeTexture(unsigned long texture);
- void attachShader(CanvasProgram* program, CanvasShader* shader);
- void bindAttribLocation(CanvasProgram*, unsigned long index, const String& name);
- void bindBuffer(unsigned long target, CanvasBuffer*);
- void bindFramebuffer(unsigned long target, CanvasFramebuffer*);
- void bindRenderbuffer(unsigned long target, CanvasRenderbuffer*);
- void bindTexture(unsigned long target, CanvasTexture* texture);
+ void attachShader(WebGLProgram* program, WebGLShader* shader);
+ void bindAttribLocation(WebGLProgram*, unsigned long index, const String& name);
+ void bindBuffer(unsigned long target, WebGLBuffer*);
+ void bindFramebuffer(unsigned long target, WebGLFramebuffer*);
+ void bindRenderbuffer(unsigned long target, WebGLRenderbuffer*);
+ void bindTexture(unsigned long target, WebGLTexture* texture);
void blendColor(double red, double green, double blue, double alpha);
void blendEquation(unsigned long mode);
void blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha);
@@ -113,8 +418,8 @@ namespace WebCore {
void blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha);
void bufferData(unsigned long target, int size, unsigned long usage);
- void bufferData(unsigned long target, CanvasArray* data, unsigned long usage);
- void bufferSubData(unsigned long target, long offset, CanvasArray* data);
+ void bufferData(unsigned long target, WebGLArray* data, unsigned long usage);
+ void bufferSubData(unsigned long target, long offset, WebGLArray* data);
unsigned long checkFramebufferStatus(unsigned long target);
void clear(unsigned long mask);
@@ -122,7 +427,7 @@ namespace WebCore {
void clearDepth(double depth);
void clearStencil(long s);
void colorMask(bool red, bool green, bool blue, bool alpha);
- void compileShader(CanvasShader*);
+ void compileShader(WebGLShader*);
//void compressedTexImage2D(unsigned long target, long level, unsigned long internalformat, unsigned long width, unsigned long height, long border, unsigned long imageSize, const void* data);
//void compressedTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, unsigned long width, unsigned long height, unsigned long format, unsigned long imageSize, const void* data);
@@ -133,7 +438,7 @@ namespace WebCore {
void depthFunc(unsigned long func);
void depthMask(bool flag);
void depthRange(double zNear, double zFar);
- void detachShader(CanvasProgram*, CanvasShader*);
+ void detachShader(WebGLProgram*, WebGLShader*);
void disable(unsigned long cap);
void disableVertexAttribArray(unsigned long index);
void drawArrays(unsigned long mode, long first, long count);
@@ -143,84 +448,77 @@ namespace WebCore {
void enableVertexAttribArray(unsigned long index);
void finish();
void flush();
- void framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, CanvasRenderbuffer*);
- void framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, CanvasTexture*, long level);
+ void framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer*);
+ void framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture*, long level);
void frontFace(unsigned long mode);
void generateMipmap(unsigned long target);
- bool getActiveAttrib(CanvasProgram* program, unsigned long index, ActiveInfo&);
- bool getActiveUniform(CanvasProgram* program, unsigned long index, ActiveInfo&);
+ bool getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo&);
+ bool getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo&);
- int getAttribLocation(CanvasProgram*, const String& name);
+ int getAttribLocation(WebGLProgram*, const String& name);
- bool getBoolean(unsigned long pname);
- PassRefPtr<CanvasUnsignedByteArray> getBooleanv(unsigned long pname);
- int getBufferParameteri(unsigned long target, unsigned long pname);
- PassRefPtr<CanvasIntArray> getBufferParameteriv(unsigned long target, unsigned long pname);
+ void getBooleanv(unsigned long pname, unsigned char* value);
+
+ void getBufferParameteriv(unsigned long target, unsigned long pname, int* value);
unsigned long getError();
- float getFloat(unsigned long pname);
- PassRefPtr<CanvasFloatArray> getFloatv(unsigned long pname);
- int getFramebufferAttachmentParameteri(unsigned long target, unsigned long attachment, unsigned long pname);
- PassRefPtr<CanvasIntArray> getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname);
- int getInteger(unsigned long pname);
- PassRefPtr<CanvasIntArray> getIntegerv(unsigned long pname);
- int getProgrami(CanvasProgram*, unsigned long pname);
- PassRefPtr<CanvasIntArray> getProgramiv(CanvasProgram*, unsigned long pname);
- String getProgramInfoLog(CanvasProgram*);
- int getRenderbufferParameteri(unsigned long target, unsigned long pname);
- PassRefPtr<CanvasIntArray> getRenderbufferParameteriv(unsigned long target, unsigned long pname);
- int getShaderi(CanvasShader*, unsigned long pname);
- PassRefPtr<CanvasIntArray> getShaderiv(CanvasShader*, unsigned long pname);
-
- String getShaderInfoLog(CanvasShader*);
+ void getFloatv(unsigned long pname, float* value);
+
+ void getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value);
+
+ void getIntegerv(unsigned long pname, int* value);
+
+ void getProgramiv(WebGLProgram* program, unsigned long pname, int* value);
+
+ String getProgramInfoLog(WebGLProgram*);
+
+ void getRenderbufferParameteriv(unsigned long target, unsigned long pname, int* value);
+
+ void getShaderiv(WebGLShader*, unsigned long pname, int* value);
+
+ String getShaderInfoLog(WebGLShader*);
// TBD
// void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
- String getShaderSource(CanvasShader*);
+ String getShaderSource(WebGLShader*);
String getString(unsigned long name);
-
- float getTexParameterf(unsigned long target, unsigned long pname);
- PassRefPtr<CanvasFloatArray> getTexParameterfv(unsigned long target, unsigned long pname);
- int getTexParameteri(unsigned long target, unsigned long pname);
- PassRefPtr<CanvasIntArray> getTexParameteriv(unsigned long target, unsigned long pname);
-
- float getUniformf(CanvasProgram* program, long location);
- PassRefPtr<CanvasFloatArray> getUniformfv(CanvasProgram* program, long location);
- int getUniformi(CanvasProgram* program, long location);
- PassRefPtr<CanvasIntArray> getUniformiv(CanvasProgram* program, long location);
-
- long getUniformLocation(CanvasProgram*, const String& name);
-
- float getVertexAttribf(unsigned long index, unsigned long pname);
- PassRefPtr<CanvasFloatArray> getVertexAttribfv(unsigned long index, unsigned long pname);
- int getVertexAttribi(unsigned long index, unsigned long pname);
- PassRefPtr<CanvasIntArray> getVertexAttribiv(unsigned long index, unsigned long pname);
-
+
+ void getTexParameterfv(unsigned long target, unsigned long pname, float* value);
+ void getTexParameteriv(unsigned long target, unsigned long pname, int* value);
+
+ void getUniformfv(WebGLProgram* program, long location, float* value);
+ void getUniformiv(WebGLProgram* program, long location, int* value);
+
+ long getUniformLocation(WebGLProgram*, const String& name);
+
+ void getVertexAttribfv(unsigned long index, unsigned long pname, float* value);
+ void getVertexAttribiv(unsigned long index, unsigned long pname, int* value);
+
long getVertexAttribOffset(unsigned long index, unsigned long pname);
void hint(unsigned long target, unsigned long mode);
- bool isBuffer(CanvasBuffer*);
+ bool isBuffer(WebGLBuffer*);
bool isEnabled(unsigned long cap);
- bool isFramebuffer(CanvasFramebuffer*);
- bool isProgram(CanvasProgram*);
- bool isRenderbuffer(CanvasRenderbuffer*);
- bool isShader(CanvasShader*);
- bool isTexture(CanvasTexture*);
+ bool isFramebuffer(WebGLFramebuffer*);
+ bool isProgram(WebGLProgram*);
+ bool isRenderbuffer(WebGLRenderbuffer*);
+ bool isShader(WebGLShader*);
+ bool isTexture(WebGLTexture*);
void lineWidth(double);
- void linkProgram(CanvasProgram*);
+ void linkProgram(WebGLProgram*);
void pixelStorei(unsigned long pname, long param);
void polygonOffset(double factor, double units);
- PassRefPtr<CanvasArray> readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type);
+ PassRefPtr<WebGLArray> readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type);
void releaseShaderCompiler();
void renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height);
void sampleCoverage(double value, bool invert);
void scissor(long x, long y, unsigned long width, unsigned long height);
- void shaderSource(CanvasShader*, const String& string);
+ void shaderSource(WebGLShader*, const String& string);
void stencilFunc(unsigned long func, long ref, unsigned long mask);
void stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask);
void stencilMask(unsigned long mask);
@@ -232,13 +530,11 @@ namespace WebCore {
// Currently they return -1 on any error.
int texImage2D(unsigned target, unsigned level, unsigned internalformat,
unsigned width, unsigned height, unsigned border,
- unsigned format, unsigned type, CanvasArray* pixels);
+ unsigned format, unsigned type, WebGLArray* pixels);
int texImage2D(unsigned target, unsigned level, unsigned internalformat,
unsigned width, unsigned height, unsigned border,
unsigned format, unsigned type, ImageData* pixels);
- int texImage2D(unsigned target, unsigned level, HTMLImageElement* image,
- bool flipY, bool premultiplyAlpha);
- int texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas,
+ int texImage2D(unsigned target, unsigned level, Image* image,
bool flipY, bool premultiplyAlpha);
int texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
bool flipY, bool premultiplyAlpha);
@@ -248,15 +544,12 @@ namespace WebCore {
int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
unsigned width, unsigned height,
- unsigned format, unsigned type, CanvasArray* pixels);
+ unsigned format, unsigned type, WebGLArray* pixels);
int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
unsigned width, unsigned height,
unsigned format, unsigned type, ImageData* pixels);
int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
- unsigned width, unsigned height, HTMLImageElement* image,
- bool flipY, bool premultiplyAlpha);
- int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
- unsigned width, unsigned height, HTMLCanvasElement* canvas,
+ unsigned width, unsigned height, Image* image,
bool flipY, bool premultiplyAlpha);
int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
unsigned width, unsigned height, HTMLVideoElement* video,
@@ -282,8 +575,8 @@ namespace WebCore {
void uniformMatrix3fv(long location, bool transpose, float* value, int size);
void uniformMatrix4fv(long location, bool transpose, float* value, int size);
- void useProgram(CanvasProgram*);
- void validateProgram(CanvasProgram*);
+ void useProgram(WebGLProgram*);
+ void validateProgram(WebGLProgram*);
void vertexAttrib1f(unsigned long indx, float x);
void vertexAttrib1fv(unsigned long indx, float* values);
@@ -301,7 +594,7 @@ namespace WebCore {
void reshape(int width, int height);
// Helpers for notification about paint events
- void beginPaint(CanvasRenderingContext3D* context);
+ void beginPaint(WebGLRenderingContext* context);
void endPaint();
// Support for buffer creation and deletion
@@ -309,7 +602,7 @@ namespace WebCore {
unsigned createFramebuffer();
unsigned createProgram();
unsigned createRenderbuffer();
- unsigned createShader(ShaderType);
+ unsigned createShader(unsigned long);
unsigned createTexture();
void deleteBuffer(unsigned);
@@ -319,6 +612,16 @@ namespace WebCore {
void deleteShader(unsigned);
void deleteTexture(unsigned);
+ // Synthesizes an OpenGL error which will be returned from a
+ // later call to getError. This is used to emulate OpenGL ES
+ // 2.0 behavior on the desktop and to enforce additional error
+ // checking mandated by WebGL.
+ //
+ // Per the behavior of glGetError, this stores at most one
+ // instance of any given error, and returns them from calls to
+ // getError in the order they were added.
+ void synthesizeGLError(unsigned long error);
+
private:
GraphicsContext3D();
@@ -331,6 +634,8 @@ namespace WebCore {
GLuint m_texture;
GLuint m_fbo;
GLuint m_depthBuffer;
+ // Errors raised by synthesizeGLError().
+ ListHashSet<unsigned long> m_syntheticErrors;
#endif
// FIXME: ideally this would be used on all platforms.
@@ -343,4 +648,3 @@ namespace WebCore {
} // namespace WebCore
#endif // GraphicsContext3D_h
-
diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h
index 98baab1..c532162 100644
--- a/WebCore/platform/graphics/GraphicsContextPrivate.h
+++ b/WebCore/platform/graphics/GraphicsContextPrivate.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,10 +26,10 @@
#ifndef GraphicsContextPrivate_h
#define GraphicsContextPrivate_h
-#include "TransformationMatrix.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "Pattern.h"
+#include "TransformationMatrix.h"
namespace WebCore {
@@ -38,18 +38,18 @@ namespace WebCore {
: textDrawingMode(cTextFill)
, strokeStyle(SolidStroke)
, strokeThickness(0)
-#if PLATFORM(CAIRO)
- , globalAlpha(1.0f)
-#endif
- , strokeColorSpace(SolidColorSpace)
, strokeColor(Color::black)
+ , strokeColorSpace(DeviceColorSpace)
, fillRule(RULE_NONZERO)
- , fillColorSpace(SolidColorSpace)
, fillColor(Color::black)
+ , fillColorSpace(DeviceColorSpace)
, shouldAntialias(true)
, paintingDisabled(false)
, shadowBlur(0)
, shadowsIgnoreTransforms(false)
+#if PLATFORM(CAIRO)
+ , globalAlpha(1.0f)
+#endif
{
}
@@ -57,19 +57,14 @@ namespace WebCore {
StrokeStyle strokeStyle;
float strokeThickness;
-#if PLATFORM(CAIRO)
- float globalAlpha;
-#elif PLATFORM(QT)
- TransformationMatrix pathTransform;
-#endif
- ColorSpace strokeColorSpace;
Color strokeColor;
+ ColorSpace strokeColorSpace;
RefPtr<Gradient> strokeGradient;
RefPtr<Pattern> strokePattern;
WindRule fillRule;
- ColorSpace fillColorSpace;
Color fillColor;
+ ColorSpace fillColorSpace;
RefPtr<Gradient> fillGradient;
RefPtr<Pattern> fillPattern;
@@ -82,9 +77,14 @@ namespace WebCore {
Color shadowColor;
bool shadowsIgnoreTransforms;
+#if PLATFORM(CAIRO)
+ float globalAlpha;
+#elif PLATFORM(QT)
+ TransformationMatrix pathTransform;
+#endif
};
- class GraphicsContextPrivate {
+ class GraphicsContextPrivate : public Noncopyable {
public:
GraphicsContextPrivate()
: m_focusRingWidth(0)
diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp
index c8582bb..e215097 100644
--- a/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -92,6 +92,21 @@ bool GraphicsLayer::hasAncestor(GraphicsLayer* ancestor) const
return false;
}
+bool GraphicsLayer::setChildren(const Vector<GraphicsLayer*>& newChildren)
+{
+ // If the contents of the arrays are the same, nothing to do.
+ if (newChildren == m_children)
+ return false;
+
+ removeAllChildren();
+
+ size_t listSize = newChildren.size();
+ for (size_t i = 0; i < listSize; ++i)
+ addChild(newChildren[i]);
+
+ return true;
+}
+
void GraphicsLayer::addChild(GraphicsLayer* childLayer)
{
ASSERT(childLayer != this);
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 85eace0..0456bad 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -53,6 +53,12 @@ typedef CALayer* NativeLayer;
typedef void* PlatformLayer;
typedef void* NativeLayer;
#endif
+#elif PLATFORM(WIN)
+namespace WebCore {
+class WKCACFLayer;
+typedef WKCACFLayer PlatformLayer;
+typedef void* NativeLayer;
+}
#else
typedef void* PlatformLayer;
typedef void* NativeLayer;
@@ -176,6 +182,8 @@ public:
bool hasAncestor(GraphicsLayer*) const;
const Vector<GraphicsLayer*>& children() const { return m_children; }
+ // Returns true if the child list changed.
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
// Add child layers. If the child is already parented, it will be removed from its old parent.
virtual void addChild(GraphicsLayer*);
@@ -292,8 +300,8 @@ public:
virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation) { m_contentsOrientation = orientation; }
CompositingCoordinatesOrientation contentsOrientation() const { return m_contentsOrientation; }
- static bool showDebugBorders();
- static bool showRepaintCounter();
+ bool showDebugBorders() { return m_client ? m_client->showDebugBorders() : false; }
+ bool showRepaintCounter() { return m_client ? m_client->showRepaintCounter() : false; }
void updateDebugIndicators();
diff --git a/WebCore/platform/graphics/GraphicsLayerClient.h b/WebCore/platform/graphics/GraphicsLayerClient.h
index 5facc94..afb297d 100644
--- a/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -62,6 +62,9 @@ public:
virtual void notifySyncRequired(const GraphicsLayer*) = 0;
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) = 0;
+
+ virtual bool showDebugBorders() const = 0;
+ virtual bool showRepaintCounter() const = 0;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h
index 444c67c..d7d694a 100644
--- a/WebCore/platform/graphics/Icon.h
+++ b/WebCore/platform/graphics/Icon.h
@@ -51,7 +51,6 @@ class String;
class Icon : public RefCounted<Icon> {
public:
- static PassRefPtr<Icon> createIconForFile(const String& filename);
static PassRefPtr<Icon> createIconForFiles(const Vector<String>& filenames);
~Icon();
diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp
index 80b5457..611216a 100644
--- a/WebCore/platform/graphics/Image.cpp
+++ b/WebCore/platform/graphics/Image.cpp
@@ -75,14 +75,14 @@ bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
return dataChanged(allDataReceived);
}
-void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
+void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, ColorSpace styleColorSpace, CompositeOperator op)
{
if (color.alpha() <= 0)
return;
ctxt->save();
ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
- ctxt->fillRect(dstRect, color);
+ ctxt->fillRect(dstRect, color, styleColorSpace);
ctxt->restore();
}
@@ -104,10 +104,10 @@ static inline FloatSize calculatePatternScale(const FloatRect& dstRect, const Fl
}
-void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op)
+void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, ColorSpace styleColorSpace, CompositeOperator op)
{
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, destRect, solidColor(), op);
+ fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, op);
return;
}
@@ -132,22 +132,22 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
visibleSrcRect.setWidth(destRect.width() / scale.width());
visibleSrcRect.setHeight(destRect.height() / scale.height());
- draw(ctxt, destRect, visibleSrcRect, op);
+ draw(ctxt, destRect, visibleSrcRect, styleColorSpace, op);
return;
}
TransformationMatrix patternTransform = TransformationMatrix().scaleNonUniform(scale.width(), scale.height());
FloatRect tileRect(FloatPoint(), intrinsicTileSize);
- drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect);
+ drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect);
startAnimation();
}
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
-void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator op)
+void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator op)
{
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dstRect, solidColor(), op);
+ fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, op);
return;
}
@@ -170,7 +170,7 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const Flo
vPhase -= fmodf(dstRect.height(), scale.height() * srcRect.height()) / 2.0f;
FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
- drawPattern(ctxt, srcRect, patternTransform, patternPhase, op, dstRect);
+ drawPattern(ctxt, srcRect, patternTransform, patternPhase, styleColorSpace, op, dstRect);
startAnimation();
}
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
index 294ddf6..aef6577 100644
--- a/WebCore/platform/graphics/Image.h
+++ b/WebCore/platform/graphics/Image.h
@@ -28,6 +28,7 @@
#define Image_h
#include "Color.h"
+#include "ColorSpace.h"
#include "GraphicsTypes.h"
#include "ImageSource.h"
#include "IntRect.h"
@@ -158,21 +159,22 @@ public:
protected:
Image(ImageObserver* = 0);
- static void fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op);
+ static void fillWithSolidColor(GraphicsContext*, const FloatRect& dstRect, const Color&, ColorSpace styleColorSpace, CompositeOperator);
+ // The ColorSpace parameter will only be used for untagged images.
#if PLATFORM(WIN)
- virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator) { }
+ virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator) { }
#endif
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator) = 0;
- void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, CompositeOperator);
- void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator) = 0;
+ void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, ColorSpace styleColorSpace, CompositeOperator);
+ void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, ColorSpace styleColorSpace, CompositeOperator);
// Supporting tiled drawing
virtual bool mayFillWithSolidColor() { return false; }
virtual Color solidColor() const { return Color(); }
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
private:
RefPtr<SharedBuffer> m_data; // The encoded raw data for the image.
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index b64f82b..4c66c50 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -91,6 +91,9 @@ public:
virtual void setVolume(float) { }
+ virtual bool hasClosedCaptions() const { return false; }
+ virtual void setClosedCaptionsVisible(bool) { };
+
virtual MediaPlayer::NetworkState networkState() const { return MediaPlayer::Empty; }
virtual MediaPlayer::ReadyState readyState() const { return MediaPlayer::HaveNothing; }
@@ -126,7 +129,7 @@ static MediaPlayerPrivateInterface* createNullMediaPlayer(MediaPlayer* player)
// engine support
-struct MediaPlayerFactory {
+struct MediaPlayerFactory : Noncopyable {
MediaPlayerFactory(CreateMediaEnginePlayer constructor, MediaEngineSupportedTypes getSupportedTypes, MediaEngineSupportsType supportsTypeAndCodecs)
: constructor(constructor)
, getSupportedTypes(getSupportedTypes)
@@ -377,6 +380,16 @@ void MediaPlayer::setVolume(float volume)
m_private->setVolume(volume);
}
+bool MediaPlayer::hasClosedCaptions() const
+{
+ return m_private->hasClosedCaptions();
+}
+
+void MediaPlayer::setClosedCaptionsVisible(bool closedCaptionsVisible)
+{
+ m_private->setClosedCaptionsVisible(closedCaptionsVisible);
+}
+
float MediaPlayer::rate() const
{
return m_rate;
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index 4cc6476..ec8ac33 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -37,6 +37,7 @@
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
#ifdef __OBJC__
@class QTMovie;
@@ -115,7 +116,11 @@ public:
class MediaPlayer : public Noncopyable {
public:
- MediaPlayer(MediaPlayerClient*);
+
+ static PassOwnPtr<MediaPlayer> create(MediaPlayerClient* client)
+ {
+ return new MediaPlayer(client);
+ }
virtual ~MediaPlayer();
// media engine support
@@ -175,7 +180,10 @@ public:
float volume() const;
void setVolume(float);
-
+
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool closedCaptionsVisible);
+
int dataRate() const;
bool autobuffer() const;
@@ -223,6 +231,8 @@ public:
bool hasSingleSecurityOrigin() const;
private:
+ MediaPlayer(MediaPlayerClient*);
+
static void initializeMediaEngines();
MediaPlayerClient* m_mediaPlayerClient;
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index f5687b3..03906bd 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -36,7 +36,7 @@ class IntRect;
class IntSize;
class String;
-class MediaPlayerPrivateInterface {
+class MediaPlayerPrivateInterface : public Noncopyable {
public:
virtual ~MediaPlayerPrivateInterface() { }
@@ -76,6 +76,9 @@ public:
virtual void setVolume(float) = 0;
+ virtual bool hasClosedCaptions() const { return false; }
+ virtual void setClosedCaptionsVisible(bool) { }
+
virtual MediaPlayer::NetworkState networkState() const = 0;
virtual MediaPlayer::ReadyState readyState() const = 0;
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index 6b617a0..fef5ad2 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -29,6 +29,7 @@
#define Path_h
#include <algorithm>
+#include <wtf/FastAllocBase.h>
#if PLATFORM(CG)
typedef struct CGPath PlatformPath;
@@ -93,7 +94,7 @@ namespace WebCore {
typedef void (*PathApplierFunction)(void* info, const PathElement*);
- class Path {
+ class Path : public FastAllocBase {
public:
Path();
~Path();
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index 1a951c2..3bfa8f3 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -32,6 +32,7 @@
#include "GlyphBuffer.h"
#include "Gradient.h"
#include "GraphicsContext.h"
+#include "ImageBuffer.h"
#include "Pattern.h"
#include "SimpleFontData.h"
#include "TransformationMatrix.h"
@@ -85,6 +86,34 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
shadowFillColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
+#if ENABLE(FILTERS)
+ cairo_text_extents_t extents;
+ cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
+
+ FloatRect rect(FloatPoint(), FloatSize(extents.width, extents.height));
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize = 0.f;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+
+ // Draw shadow into a new ImageBuffer
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ GraphicsContext* shadowContext = shadowBuffer->context();
+ cairo_t* shadowCr = shadowContext->platformContext();
+
+ cairo_translate(shadowCr, kernelSize, extents.height + kernelSize);
+
+ cairo_set_scaled_font(shadowCr, font->platformData().scaledFont());
+ cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
+ if (font->syntheticBoldOffset()) {
+ cairo_save(shadowCr);
+ cairo_translate(shadowCr, font->syntheticBoldOffset(), 0);
+ cairo_show_glyphs(shadowCr, glyphs, numGlyphs);
+ cairo_restore(shadowCr);
+ }
+ cairo_translate(cr, 0.0, -extents.height);
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+#else
cairo_translate(cr, shadowSize.width(), shadowSize.height());
cairo_show_glyphs(cr, glyphs, numGlyphs);
if (font->syntheticBoldOffset()) {
@@ -93,6 +122,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_show_glyphs(cr, glyphs, numGlyphs);
cairo_restore(cr);
}
+#endif
cairo_restore(cr);
}
@@ -156,7 +186,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
// Re-enable the platform shadow we disabled earlier
if (hasShadow)
- context->setShadow(shadowSize, shadowBlur, shadowColor);
+ context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace);
cairo_restore(cr);
}
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 8741c5e..14034fd 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -1,8 +1,9 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
- * Copyright (C) 2008 Dirk Schulze <vbs85@gmx.de>
+ * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2008 Nuanti Ltd.
+ * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,14 +33,17 @@
#if PLATFORM(CAIRO)
#include "CairoPath.h"
+#include "FEGaussianBlur.h"
#include "FloatRect.h"
#include "Font.h"
#include "ImageBuffer.h"
+#include "ImageBufferFilter.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
#include "SimpleFontData.h"
+#include "SourceGraphic.h"
#include "TransformationMatrix.h"
#include <cairo.h>
@@ -69,6 +73,42 @@ static inline void setColor(cairo_t* cr, const Color& col)
cairo_set_source_rgba(cr, red, green, blue, alpha);
}
+static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp)
+{
+ cairo_save(cr);
+ if (gcp->state.fillPattern) {
+ TransformationMatrix affine;
+ cairo_set_source(cr, gcp->state.fillPattern->createPlatformPattern(affine));
+ } else if (gcp->state.fillGradient)
+ cairo_set_source(cr, gcp->state.fillGradient->platformGradient());
+ else
+ setColor(cr, context->fillColor());
+ cairo_clip_preserve(cr);
+ cairo_paint_with_alpha(cr, gcp->state.globalAlpha);
+ cairo_restore(cr);
+}
+
+static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp)
+{
+ cairo_save(cr);
+ if (gcp->state.strokePattern) {
+ TransformationMatrix affine;
+ cairo_set_source(cr, gcp->state.strokePattern->createPlatformPattern(affine));
+ } else if (gcp->state.strokeGradient)
+ cairo_set_source(cr, gcp->state.strokeGradient->platformGradient());
+ else {
+ Color strokeColor = colorWithOverrideAlpha(context->strokeColor().rgb(), context->strokeColor().alpha() / 255.f * gcp->state.globalAlpha);
+ setColor(cr, strokeColor);
+ }
+ if (gcp->state.globalAlpha < 1.0f && (gcp->state.strokePattern || gcp->state.strokeGradient)) {
+ cairo_push_group(cr);
+ cairo_paint_with_alpha(cr, gcp->state.globalAlpha);
+ cairo_pop_group_to_source(cr);
+ }
+ cairo_stroke_preserve(cr);
+ cairo_restore(cr);
+}
+
// A fillRect helper
static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col)
{
@@ -78,6 +118,81 @@ static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const
cairo_fill(cr);
}
+static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
+{
+ cairo_set_antialias(dstCr, cairo_get_antialias(srcCr));
+
+ size_t dashCount = cairo_get_dash_count(srcCr);
+ Vector<double> dashes(dashCount);
+
+ double offset;
+ cairo_get_dash(srcCr, dashes.data(), &offset);
+ cairo_set_dash(dstCr, dashes.data(), dashCount, offset);
+ cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr));
+ cairo_set_line_join(dstCr, cairo_get_line_join(srcCr));
+ cairo_set_line_width(dstCr, cairo_get_line_width(srcCr));
+ cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr));
+ cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr));
+}
+
+void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur)
+{
+#if ENABLE(FILTERS)
+ // calculate the kernel size according to the HTML5 canvas shadow specification
+ kernelSize = (shadowBlur < 8 ? shadowBlur / 2.f : sqrt(shadowBlur * 2.f));
+ int blurRadius = ceil(kernelSize);
+
+ shadowBufferSize = IntSize(sourceRect.width() + blurRadius * 2, sourceRect.height() + blurRadius * 2);
+
+ // determine dimensions of shadow rect
+ shadowRect = FloatRect(sourceRect.location(), shadowBufferSize);
+ shadowRect.move(shadowSize.width() - kernelSize, shadowSize.height() - kernelSize);
+#endif
+}
+
+static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow)
+{
+#if ENABLE(FILTERS)
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (!context->getShadow(shadowSize, shadowBlur, shadowColor))
+ return;
+
+ // Calculate filter values to create appropriate shadow.
+ cairo_t* cr = context->platformContext();
+ cairo_path_t* path = cairo_copy_path(cr);
+ double x0, x1, y0, y1;
+ if (strokeShadow)
+ cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
+ else
+ cairo_fill_extents(cr, &x0, &y0, &x1, &y1);
+ FloatRect rect(x0, y0, x1 - x0, y1 - y0);
+
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize = 0;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+
+ // Create suitably-sized ImageBuffer to hold the shadow.
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+
+ // Draw shadow into a new ImageBuffer.
+ cairo_t* shadowContext = shadowBuffer->context()->platformContext();
+ copyContextProperties(cr, shadowContext);
+ cairo_translate(shadowContext, -rect.x() + kernelSize, -rect.y() + kernelSize);
+ cairo_new_path(shadowContext);
+ cairo_append_path(shadowContext, path);
+
+ if (fillShadow)
+ setPlatformFill(context, shadowContext, gcp);
+ if (strokeShadow)
+ setPlatformStroke(context, shadowContext, gcp);
+
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+#endif
+}
+
GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate)
@@ -387,30 +502,12 @@ void GraphicsContext::fillPath()
return;
cairo_t* cr = m_data->cr;
- cairo_save(cr);
cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- setColor(cr, fillColor());
- cairo_clip(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- cairo_set_source(cr, m_common->state.fillPattern->createPlatformPattern(affine));
- cairo_clip(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- break;
- }
- case GradientColorSpace:
- cairo_pattern_t* pattern = m_common->state.fillGradient->platformGradient();
- cairo_set_source(cr, pattern);
- cairo_clip(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- break;
- }
- cairo_restore(cr);
+ drawPathShadow(this, m_common, true, false);
+
+ setPlatformFill(this, cr, m_common);
+ cairo_new_path(cr);
}
void GraphicsContext::strokePath()
@@ -419,45 +516,26 @@ void GraphicsContext::strokePath()
return;
cairo_t* cr = m_data->cr;
- cairo_save(cr);
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- float red, green, blue, alpha;
- strokeColor().getRGBA(red, green, blue, alpha);
- if (m_common->state.globalAlpha < 1.0f)
- alpha *= m_common->state.globalAlpha;
- cairo_set_source_rgba(cr, red, green, blue, alpha);
- cairo_stroke(cr);
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- cairo_set_source(cr, m_common->state.strokePattern->createPlatformPattern(affine));
- if (m_common->state.globalAlpha < 1.0f) {
- cairo_push_group(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- cairo_pop_group_to_source(cr);
- }
- cairo_stroke(cr);
- break;
- }
- case GradientColorSpace:
- cairo_pattern_t* pattern = m_common->state.strokeGradient->platformGradient();
- cairo_set_source(cr, pattern);
- if (m_common->state.globalAlpha < 1.0f) {
- cairo_push_group(cr);
- cairo_paint_with_alpha(cr, m_common->state.globalAlpha);
- cairo_pop_group_to_source(cr);
- }
- cairo_stroke(cr);
- break;
- }
- cairo_restore(cr);
+ drawPathShadow(this, m_common, false, true);
+
+ setPlatformStroke(this, cr, m_common);
+ cairo_new_path(cr);
+
}
void GraphicsContext::drawPath()
{
- fillPath();
- strokePath();
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+
+ cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
+ drawPathShadow(this, m_common, true, true);
+
+ setPlatformFill(this, cr, m_common);
+ setPlatformStroke(this, cr, m_common);
+ cairo_new_path(cr);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -470,11 +548,36 @@ void GraphicsContext::fillRect(const FloatRect& rect)
fillPath();
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor)
+{
+#if ENABLE(FILTERS)
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+
+ if (!context->getShadow(shadowSize, shadowBlur, shadowColor))
+ return;
+
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize = 0;
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, rect, shadowSize, shadowBlur);
+
+ // Draw shadow into a new ImageBuffer
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ GraphicsContext* shadowContext = shadowBuffer->context();
+ shadowContext->fillRect(FloatRect(FloatPoint(kernelSize, kernelSize), rect.size()), rectColor, DeviceColorSpace);
+
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+#endif
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
+ drawBorderlessRectShadow(this, rect, color);
if (color.alpha())
fillRectSourceOver(m_data->cr, rect, color);
}
@@ -634,13 +737,13 @@ IntPoint GraphicsContext::origin()
return IntPoint(static_cast<int>(matrix.x0), static_cast<int>(matrix.y0));
}
-void GraphicsContext::setPlatformFillColor(const Color& col)
+void GraphicsContext::setPlatformFillColor(const Color& col, ColorSpace colorSpace)
{
// Cairo contexts can't hold separate fill and stroke colors
// so we set them just before we actually fill or stroke
}
-void GraphicsContext::setPlatformStrokeColor(const Color& col)
+void GraphicsContext::setPlatformStrokeColor(const Color& col, ColorSpace colorSpace)
{
// Cairo contexts can't hold separate fill and stroke colors
// so we set them just before we actually fill or stroke
@@ -726,9 +829,48 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer
notImplemented();
}
-void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&)
+void GraphicsContext::setPlatformShadow(IntSize const& size, int, Color const&, ColorSpace)
{
- notImplemented();
+ // Cairo doesn't support shadows natively, they are drawn manually in the draw*
+ // functions
+
+ if (m_common->state.shadowsIgnoreTransforms) {
+ // Meaning that this graphics context is associated with a CanvasRenderingContext
+ // We flip the height since CG and HTML5 Canvas have opposite Y axis
+ m_common->state.shadowSize = IntSize(size.width(), -size.height());
+ }
+}
+
+void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize)
+{
+#if ENABLE(FILTERS)
+ cairo_t* cr = m_data->cr;
+
+ // draw the shadow without blurring, if kernelSize is zero
+ if (!kernelSize) {
+ setColor(cr, shadowColor);
+ cairo_mask_surface(cr, buffer->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y());
+ return;
+ }
+
+ // limit kernel size to 1000, this is what CG is doing.
+ kernelSize = std::min(1000.f, kernelSize);
+
+ // create filter
+ RefPtr<Filter> filter = ImageBufferFilter::create();
+ filter->setSourceImage(buffer.release());
+ RefPtr<FilterEffect> source = SourceGraphic::create();
+ source->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
+ source->setIsAlphaImage(true);
+ RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), kernelSize, kernelSize);
+ blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size()));
+ blur->apply(filter.get());
+
+ // Mask the filter with the shadow color and draw it to the context.
+ // Masking makes it possible to just blur the alpha channel.
+ setColor(cr, shadowColor);
+ cairo_mask_surface(cr, blur->resultImage()->image()->nativeImageForCurrentFrame(), shadowRect.x(), shadowRect.y());
+#endif
}
void GraphicsContext::clearPlatformShadow()
@@ -941,7 +1083,6 @@ void GraphicsContext::clipOut(const Path& path)
if (paintingDisabled())
return;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0)
cairo_t* cr = m_data->cr;
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
@@ -952,9 +1093,6 @@ void GraphicsContext::clipOut(const Path& path)
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip(cr);
cairo_set_fill_rule(cr, savedFillRule);
-#else
- notImplemented();
-#endif
}
void GraphicsContext::rotate(float radians)
@@ -980,19 +1118,15 @@ void GraphicsContext::clipOut(const IntRect& r)
if (paintingDisabled())
return;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,4,0)
cairo_t* cr = m_data->cr;
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
- cairo_rectangle(cr, x1, x2, x2 - x1, y2 - y1);
+ cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_clip(cr);
cairo_set_fill_rule(cr, savedFillRule);
-#else
- notImplemented();
-#endif
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
@@ -1005,7 +1139,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
clipOut(p);
}
-void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1015,6 +1149,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft,
beginPath();
addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
setColor(cr, color);
+ drawPathShadow(this, m_common, true, false);
cairo_fill(cr);
cairo_restore(cr);
}
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 0213944..d991c80 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -136,6 +136,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
*pixel = premultipliedARGBFromColor(pixelColor);
}
}
+ cairo_surface_mark_dirty_rectangle (m_data.m_surface, 0, 0, m_size.width(), m_size.height());
}
template <Multiply multiplied>
@@ -260,6 +261,9 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
}
srcRows += srcBytesPerRow;
}
+ cairo_surface_mark_dirty_rectangle (data.m_surface,
+ destx, desty,
+ numColumns, numRows);
}
void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
index c8c992e..92e36fc 100644
--- a/WebCore/platform/graphics/cairo/ImageCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -89,7 +89,7 @@ BitmapImage::BitmapImage(cairo_surface_t* surface, ImageObserver* observer)
checkForSolidColor();
}
-void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
FloatRect srcRect(src);
FloatRect dstRect(dst);
@@ -105,7 +105,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(context, dstRect, solidColor(), op);
+ fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op);
return;
}
@@ -125,17 +125,37 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
// Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
- // To avoid the unwanted gradient effect (#14017) we use
- // CAIRO_FILTER_NEAREST now, but the real fix will be to have
- // CAIRO_EXTEND_PAD implemented for surfaces in Cairo allowing us to still
- // use bilinear filtering
- cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
float scaleX = srcRect.width() / dstRect.width();
float scaleY = srcRect.height() / dstRect.height();
cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
cairo_pattern_set_matrix(pattern, &matrix);
+ // Draw the shadow
+#if ENABLE(FILTERS)
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ IntSize shadowBufferSize;
+ FloatRect shadowRect;
+ float kernelSize (0.0);
+ GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, kernelSize, dstRect, shadowSize, shadowBlur);
+ shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f);
+
+ //draw shadow into a new ImageBuffer
+ OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize);
+ cairo_t* shadowContext = shadowBuffer->context()->platformContext();
+ cairo_set_source(shadowContext, pattern);
+ cairo_translate(shadowContext, -dstRect.x(), -dstRect.y());
+ cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height());
+ cairo_fill(shadowContext);
+
+ context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, kernelSize);
+ }
+#endif
+
// Draw the image.
cairo_translate(cr, dstRect.x(), dstRect.y());
cairo_set_source(cr, pattern);
@@ -151,7 +171,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo
}
void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
{
cairo_surface_t* image = nativeImageForCurrentFrame();
if (!image) // If it's too early we won't have an image yet.
@@ -180,9 +200,6 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, con
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
- // Workaround to avoid the unwanted gradient effect (#14017)
- cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
-
cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()};
cairo_matrix_t combined;
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index 75681bd..8bde57e 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -78,15 +78,7 @@ void Path::clear()
bool Path::isEmpty() const
{
- cairo_t* cr = platformPath()->m_cr;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,10)
- return !cairo_has_current_point(cr);
-#else
- cairo_path_t* p = cairo_copy_path(cr);
- bool hasData = p->num_data;
- cairo_path_destroy(p);
- return !hasData;
-#endif
+ return !cairo_has_current_point(platformPath()->m_cr);
}
bool Path::hasCurrentPoint() const
@@ -256,11 +248,7 @@ FloatRect Path::boundingRect() const
{
cairo_t* cr = platformPath()->m_cr;
double x0, x1, y0, y1;
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 6, 0)
cairo_path_extents(cr, &x0, &y0, &x1, &y1);
-#else
- cairo_stroke_extents(cr, &x0, &y0, &x1, &y1);
-#endif
return FloatRect(x0, y0, x1 - x0, y1 - y0);
}
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 1350bd3..39f06a6 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -43,26 +43,78 @@
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+// Building on 10.6 or later: kCGInterpolationMedium is defined in the CGInterpolationQuality enum.
#define HAVE_CG_INTERPOLATION_MEDIUM 1
#endif
+#if !defined(TARGETING_TIGER) && !defined(TARGETING_LEOPARD)
+// Targeting 10.6 or later: use kCGInterpolationMedium.
+#define WTF_USE_CG_INTERPOLATION_MEDIUM 1
+#endif
+
+#endif
+
using namespace std;
namespace WebCore {
-static void setCGFillColor(CGContextRef context, const Color& color)
+static CGColorRef createCGColorWithColorSpace(const Color& color, ColorSpace colorSpace)
{
- CGFloat red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- CGContextSetRGBFillColor(context, red, green, blue, alpha);
+ CGFloat components[4];
+ color.getRGBA(components[0], components[1], components[2], components[3]);
+
+ CGColorRef cgColor = 0;
+ if (colorSpace == sRGBColorSpace)
+ cgColor = CGColorCreate(sRGBColorSpaceRef(), components);
+ else
+ cgColor = CGColorCreate(deviceRGBColorSpaceRef(), components);
+
+ return cgColor;
}
-static void setCGStrokeColor(CGContextRef context, const Color& color)
+static void setCGFillColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
{
- CGFloat red, green, blue, alpha;
- color.getRGBA(red, green, blue, alpha);
- CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
+ CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
+ CGContextSetFillColorWithColor(context, cgColor);
+ CFRelease(cgColor);
+}
+
+static void setCGStrokeColor(CGContextRef context, const Color& color, ColorSpace colorSpace)
+{
+ CGColorRef cgColor = createCGColorWithColorSpace(color, colorSpace);
+ CGContextSetStrokeColorWithColor(context, cgColor);
+ CFRelease(cgColor);
+}
+
+static void setCGFillColorSpace(CGContextRef context, ColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ break;
+ case sRGBColorSpace:
+ CGContextSetFillColorSpace(context, sRGBColorSpaceRef());
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+static void setCGStrokeColorSpace(CGContextRef context, ColorSpace colorSpace)
+{
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ break;
+ case sRGBColorSpace:
+ CGContextSetStrokeColorSpace(context, sRGBColorSpaceRef());
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
}
GraphicsContext::GraphicsContext(CGContextRef cgContext)
@@ -72,8 +124,8 @@ GraphicsContext::GraphicsContext(CGContextRef cgContext)
setPaintingDisabled(!cgContext);
if (cgContext) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), fillColorSpace());
+ setPlatformStrokeColor(strokeColor(), strokeColorSpace());
}
}
@@ -123,7 +175,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
// We do a fill of four rects to simulate the stroke of a border.
Color oldFillColor = fillColor();
if (oldFillColor != strokeColor())
- setCGFillColor(context, strokeColor());
+ setCGFillColor(context, strokeColor(), strokeColorSpace());
CGRect rects[4] = {
FloatRect(rect.x(), rect.y(), rect.width(), 1),
FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),
@@ -132,7 +184,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
};
CGContextFillRects(context, rects, 4);
if (oldFillColor != strokeColor())
- setCGFillColor(context, oldFillColor);
+ setCGFillColor(context, oldFillColor, fillColorSpace());
}
}
@@ -200,7 +252,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
// Do a rect fill of our endpoints. This ensures we always have the
// appearance of being a border. We then draw the actual dotted/dashed line.
- setCGFillColor(context, strokeColor()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
+ setCGFillColor(context, strokeColor(), strokeColorSpace()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
if (isVerticalLine) {
CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width));
CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width));
@@ -392,7 +444,7 @@ void GraphicsContext::applyStrokePattern()
{
CGContextRef cgContext = platformContext();
- RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern.get()->createPlatformPattern(getCTM()));
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
@@ -407,7 +459,7 @@ void GraphicsContext::applyFillPattern()
{
CGContextRef cgContext = platformContext();
- RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern.get()->createPlatformPattern(getCTM()));
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
@@ -420,8 +472,8 @@ void GraphicsContext::applyFillPattern()
static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPathDrawingMode& mode)
{
- bool shouldFill = state.fillColorSpace == PatternColorSpace || state.fillColor.alpha();
- bool shouldStroke = state.strokeColorSpace == PatternColorSpace || (state.strokeStyle != NoStroke && state.strokeColor.alpha());
+ bool shouldFill = state.fillPattern || state.fillColor.alpha();
+ bool shouldStroke = state.strokePattern || (state.strokeStyle != NoStroke && state.strokeColor.alpha());
bool useEOFill = state.fillRule == RULE_EVENODD;
if (shouldFill) {
@@ -453,16 +505,16 @@ void GraphicsContext::drawPath()
CGContextRef context = platformContext();
const GraphicsContextState& state = m_common->state;
- if (state.fillColorSpace == GradientColorSpace || state.strokeColorSpace == GradientColorSpace) {
+ if (state.fillGradient || state.strokeGradient) {
// We don't have any optimized way to fill & stroke a path using gradients
fillPath();
strokePath();
return;
}
- if (state.fillColorSpace == PatternColorSpace)
+ if (state.fillPattern)
applyFillPattern();
- if (state.strokeColorSpace == PatternColorSpace)
+ if (state.strokePattern)
applyStrokePattern();
CGPathDrawingMode drawingMode;
@@ -484,15 +536,11 @@ void GraphicsContext::fillPath()
return;
CGContextRef context = platformContext();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- fillPathWithFillRule(context, fillRule());
- break;
- case PatternColorSpace:
- applyFillPattern();
- fillPathWithFillRule(context, fillRule());
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
+ setCGFillColorSpace(context, m_common->state.fillColorSpace);
+
+ if (m_common->state.fillGradient) {
CGContextSaveGState(context);
if (fillRule() == RULE_EVENODD)
CGContextEOClip(context);
@@ -501,8 +549,12 @@ void GraphicsContext::fillPath()
CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.fillGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.fillPattern)
+ applyFillPattern();
+ fillPathWithFillRule(context, fillRule());
}
void GraphicsContext::strokePath()
@@ -511,76 +563,83 @@ void GraphicsContext::strokePath()
return;
CGContextRef context = platformContext();
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- CGContextStrokePath(context);
- break;
- case PatternColorSpace:
- applyStrokePattern();
- CGContextStrokePath(context);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
+ setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
+
+ if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
CGContextConcatCTM(context, m_common->state.strokeGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.strokePattern)
+ applyStrokePattern();
+ CGContextStrokePath(context);
}
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
+
CGContextRef context = platformContext();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- CGContextFillRect(context, rect);
- break;
- case PatternColorSpace:
- applyFillPattern();
- CGContextFillRect(context, rect);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the fillPattern and fillGradient cases?
+ setCGFillColorSpace(context, m_common->state.fillColorSpace);
+
+ if (m_common->state.fillGradient) {
CGContextSaveGState(context);
CGContextClipToRect(context, rect);
CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
CGContextDrawShading(context, m_common->state.fillGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.fillPattern)
+ applyFillPattern();
+ CGContextFillRect(context, rect);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
+ ColorSpace oldColorSpace = fillColorSpace();
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, color, colorSpace);
+
CGContextFillRect(context, rect);
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
Color oldFillColor = fillColor();
- if (oldFillColor != color)
- setCGFillColor(context, color);
+ ColorSpace oldColorSpace = fillColorSpace();
+
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, color, colorSpace);
addPath(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
fillPath();
- if (oldFillColor != color)
- setCGFillColor(context, oldFillColor);
+ if (oldFillColor != color || oldColorSpace != colorSpace)
+ setCGFillColor(context, oldFillColor, oldColorSpace);
}
void GraphicsContext::clip(const FloatRect& rect)
@@ -680,7 +739,7 @@ void GraphicsContext::endTransparencyLayer()
m_data->m_userToDeviceTransformKnownToBeIdentity = false;
}
-void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -727,7 +786,7 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
if (!color.isValid())
CGContextSetShadow(context, CGSizeMake(width, height), blurRadius);
else {
- RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColor(color));
+ RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColorWithColorSpace(color, colorSpace));
CGContextSetShadowWithColor(context,
CGSizeMake(width, height),
blurRadius,
@@ -769,15 +828,11 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
return;
CGContextRef context = platformContext();
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- CGContextStrokeRectWithWidth(context, r, lineWidth);
- break;
- case PatternColorSpace:
- applyStrokePattern();
- CGContextStrokeRectWithWidth(context, r, lineWidth);
- break;
- case GradientColorSpace:
+
+ // FIXME: Is this helpful and correct in the strokePattern and strokeGradient cases?
+ setCGStrokeColorSpace(context, m_common->state.strokeColorSpace);
+
+ if (m_common->state.strokeGradient) {
CGContextSaveGState(context);
setStrokeThickness(lineWidth);
CGContextAddRect(context, r);
@@ -785,8 +840,12 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextClip(context);
CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient());
CGContextRestoreGState(context);
- break;
+ return;
}
+
+ if (m_common->state.strokePattern)
+ applyStrokePattern();
+ CGContextStrokeRectWithWidth(context, r, lineWidth);
}
void GraphicsContext::setLineCap(LineCap cap)
@@ -986,10 +1045,10 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
}
if (fillColor() != strokeColor())
- setCGFillColor(platformContext(), strokeColor());
+ setCGFillColor(platformContext(), strokeColor(), strokeColorSpace());
CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
if (fillColor() != strokeColor())
- setCGFillColor(platformContext(), fillColor());
+ setCGFillColor(platformContext(), fillColor(), fillColorSpace());
if (restoreAntialiasMode)
CGContextSetShouldAntialias(platformContext(), true);
@@ -1034,9 +1093,9 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
quality = kCGInterpolationLow;
break;
- // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
+ // Fall through to InterpolationHigh if kCGInterpolationMedium is not usable.
case InterpolationMedium:
-#if HAVE(CG_INTERPOLATION_MEDIUM)
+#if USE(CG_INTERPOLATION_MEDIUM)
quality = kCGInterpolationMedium;
break;
#endif
@@ -1061,9 +1120,15 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
case kCGInterpolationLow:
return InterpolationLow;
#if HAVE(CG_INTERPOLATION_MEDIUM)
+ // kCGInterpolationMedium is known to be present in the CGInterpolationQuality enum.
case kCGInterpolationMedium:
+#if USE(CG_INTERPOLATION_MEDIUM)
+ // Only map to InterpolationMedium if targeting a system that understands it.
return InterpolationMedium;
-#endif
+#else
+ return InterpolationDefault;
+#endif // USE(CG_INTERPOLATION_MEDIUM)
+#endif // HAVE(CG_INTERPOLATION_MEDIUM)
case kCGInterpolationHigh:
return InterpolationHigh;
}
@@ -1107,11 +1172,11 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
}
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- setCGStrokeColor(platformContext(), color);
+ setCGStrokeColor(platformContext(), color, colorSpace);
}
void GraphicsContext::setPlatformStrokeThickness(float thickness)
@@ -1121,11 +1186,11 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
CGContextSetLineWidth(platformContext(), thickness);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
- setCGFillColor(platformContext(), color);
+ setCGFillColor(platformContext(), color, colorSpace);
}
void GraphicsContext::setPlatformShouldAntialias(bool enable)
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index 38c5506..ff1816f 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -27,6 +27,25 @@
namespace WebCore {
+// FIXME: This would be in GraphicsContextCG.h if that existed.
+inline CGColorSpaceRef deviceRGBColorSpaceRef()
+{
+ static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB();
+ return deviceSpace;
+}
+
+// FIXME: This would be in GraphicsContextCG.h if that existed.
+inline CGColorSpaceRef sRGBColorSpaceRef()
+{
+ // FIXME: Windows should be able to use kCGColorSpaceSRGB, this is tracked by http://webkit.org/b/31363.
+#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER)
+ return deviceRGBColorSpaceRef();
+#else
+ static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ return sRGBSpace;
+#endif
+}
+
class GraphicsContextPlatformPrivate {
public:
GraphicsContextPlatformPrivate(CGContextRef cgContext)
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
index 4da7018..2e372e2 100644
--- a/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -32,6 +32,7 @@
#include "FloatConversion.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
+#include "GraphicsContextPlatformPrivateCG.h"
#include "ImageObserver.h"
#include "PDFDocumentImage.h"
#include "PlatformString.h"
@@ -127,25 +128,46 @@ void BitmapImage::checkForSolidColor()
}
}
+static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
+{
+ CGColorSpaceRef originalColorSpace = CGImageGetColorSpace(originalImage);
+
+ // If the image already has a (non-device) color space, we don't want to
+ // override it, so return.
+ if (!originalColorSpace || !CFEqual(originalColorSpace, deviceRGBColorSpaceRef()))
+ return originalImage;
+
+ switch (colorSpace) {
+ case DeviceColorSpace:
+ return originalImage;
+ case sRGBColorSpace:
+ return RetainPtr<CGImageRef>(AdoptCF, CGImageCreateCopyWithColorSpace(originalImage,
+ sRGBColorSpaceRef()));
+ }
+
+ ASSERT_NOT_REACHED();
+ return originalImage;
+}
+
CGImageRef BitmapImage::getCGImageRef()
{
return frameAtIndex(0);
}
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
startAnimation();
- CGImageRef image = frameAtIndex(m_currentFrame);
+ RetainPtr<CGImageRef> image = frameAtIndex(m_currentFrame);
if (!image) // If it's too early we won't have an image yet.
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, destRect, solidColor(), compositeOp);
+ fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
return;
}
- float currHeight = CGImageGetHeight(image);
+ float currHeight = CGImageGetHeight(image.get());
if (currHeight <= srcRect.y())
return;
@@ -181,10 +203,10 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
adjustedDestRect.setHeight(subimageRect.height() / yScale);
- image = CGImageCreateWithImageInRect(image, subimageRect);
+ image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
if (currHeight < srcRect.bottom()) {
- ASSERT(CGImageGetHeight(image) == currHeight - CGRectIntegral(srcRect).origin.y);
- adjustedDestRect.setHeight(CGImageGetHeight(image) / yScale);
+ ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
+ adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
}
} else {
adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
@@ -204,11 +226,11 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
CGContextScaleCTM(context, 1, -1);
adjustedDestRect.setY(-adjustedDestRect.bottom());
- // Draw the image.
- CGContextDrawImage(context, adjustedDestRect, image);
+ // Adjust the color space.
+ image = imageWithColorSpace(image.get(), styleColorSpace);
- if (shouldUseSubimage)
- CGImageRelease(image);
+ // Draw the image.
+ CGContextDrawImage(context, adjustedDestRect, image.get());
ctxt->restore();
@@ -223,7 +245,7 @@ static void drawPatternCallback(void* info, CGContextRef context)
}
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
if (!nativeImageForCurrentFrame())
return;
@@ -260,6 +282,9 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
ASSERT(h == height());
subImage.adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect));
}
+
+ // Adjust the color space.
+ subImage = imageWithColorSpace(subImage.get(), styleColorSpace);
#ifndef BUILDING_ON_TIGER
// Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index 66246fe..2b2c6b0 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -35,12 +35,27 @@
#include <ApplicationServices/ApplicationServices.h>
#include <wtf/UnusedParam.h>
+using namespace std;
+
namespace WebCore {
static const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
#if !PLATFORM(MAC)
-static void sharedBufferDerefCallback(void*, void* info)
+size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
+{
+ SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
+ size_t sourceSize = sharedBuffer->size();
+ if (position >= sourceSize)
+ return 0;
+
+ const char* source = sharedBuffer->data() + position;
+ size_t amount = min<size_t>(count, sourceSize - position);
+ memcpy(buffer, source, amount);
+ return amount;
+}
+
+void sharedBufferRelease(void* info)
{
SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
sharedBuffer->deref();
@@ -110,15 +125,17 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
// to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData());
+ CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
#else
- // If no NSData is available, then we know SharedBuffer will always just be a vector. That means no secret changes can occur to it behind the
- // scenes. We use CFDataCreateWithBytesNoCopy in that case. Ensure that the SharedBuffer lives as long as the CFDataRef.
+ // Create a CGDataProvider to wrap the SharedBuffer.
data->ref();
- CFAllocatorContext context = {0, data, 0, 0, 0, 0, 0, &sharedBufferDerefCallback, 0};
- RetainPtr<CFAllocatorRef> derefAllocator(AdoptCF, CFAllocatorCreate(kCFAllocatorDefault, &context));
- RetainPtr<CFDataRef> cfData(AdoptCF, CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data->data()), data->size(), derefAllocator.get()));
+ // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
+ // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
+ // is a requirement for using the GetBytePointer callback.
+ CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirect(data, data->size(), &providerCallbacks));
+ CGImageSourceUpdateDataProvider(m_decoder, dataProvider.get(), allDataReceived);
#endif
- CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
}
String ImageSource::filenameExtension() const
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.h b/WebCore/platform/graphics/cg/ImageSourceCG.h
index d5b4b5a..76b4160 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.h
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.h
@@ -36,6 +36,10 @@ String preferredExtensionForImageSourceType(const String& type);
String MIMETypeForImageSourceType(const String& type);
+#if !PLATFORM(MAC)
+size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count);
+#endif
+
}
#endif // ImageSourceCG_h
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
index 2f5c15e..67333ae 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -33,6 +33,10 @@
#include "ImageObserver.h"
#include <wtf/MathExtras.h>
+#if !PLATFORM(MAC)
+#include "ImageSourceCG.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -69,12 +73,15 @@ bool PDFDocumentImage::dataChanged(bool allDataReceived)
// On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
// to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
RetainPtr<CFDataRef> data(AdoptCF, this->data()->createCFData());
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get()));
#else
- // If no NSData is available, then we know SharedBuffer will always just be a vector. That means no secret changes can occur to it behind the
- // scenes. We use CFDataCreateWithBytesNoCopy in that case.
- RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(this->data()->data()), this->data()->size(), kCFAllocatorNull));
+ // Create a CGDataProvider to wrap the SharedBuffer.
+ // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
+ // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
+ // is a requirement for using the GetBytePointer callback.
+ CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, 0 };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirect(this->data(), this->data()->size(), &providerCallbacks));
#endif
- RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get()));
m_document = CGPDFDocumentCreateWithProvider(dataProvider.get());
setCurrentPage(0);
}
@@ -139,7 +146,7 @@ int PDFDocumentImage::pageCount() const
return m_document ? CGPDFDocumentGetNumberOfPages(m_document) : 0;
}
-void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op)
+void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator op)
{
if (!m_document || m_currentPage == -1)
return;
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h
index 130c12c..12ab46c 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.h
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -58,7 +58,7 @@ namespace WebCore {
virtual IntSize size() const;
PDFDocumentImage();
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
void setCurrentPage(int);
int pageCount() const;
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 229188e..9f8f354 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -112,12 +112,16 @@ void TransparencyAwareFontPainter::init()
void TransparencyAwareFontPainter::initializeForGDI()
{
+ m_graphicsContext->save();
SkColor color = m_platformContext->effectiveFillColor();
+ // Used only when m_createdTransparencyLayer is true.
+ float layerAlpha = 0.0f;
if (SkColorGetA(color) != 0xFF) {
// When the font has some transparency, apply it by creating a new
- // transparency layer with that opacity applied.
+ // transparency layer with that opacity applied. We'll actually create
+ // a new transparency layer after we calculate the bounding box.
m_createdTransparencyLayer = true;
- m_graphicsContext->beginTransparencyLayer(SkColorGetA(color) / 255.0f);
+ layerAlpha = SkColorGetA(color) / 255.0f;
// The color should be opaque now.
color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
}
@@ -131,16 +135,22 @@ void TransparencyAwareFontPainter::initializeForGDI()
// and we could do ClearType in that case.
layerMode = TransparencyWin::TextComposite;
layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
// The transparency helper requires that we draw text in black in
// this mode and it will apply the color.
m_transparency.setTextCompositeColor(color);
color = SkColorSetRGB(0, 0, 0);
- } else if (canvasHasMultipleLayers(m_platformContext->canvas())) {
+ } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
// When we're drawing a web page, we know the background is opaque,
// but if we're drawing to a layer, we still need extra work.
layerMode = TransparencyWin::OpaqueCompositeLayer;
layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
} else {
// Common case of drawing onto the bottom layer of a web page: we
// know everything is opaque so don't need to do anything special.
@@ -167,6 +177,7 @@ TransparencyAwareFontPainter::~TransparencyAwareFontPainter()
m_transparency.composite();
if (m_createdTransparencyLayer)
m_graphicsContext->endTransparencyLayer();
+ m_graphicsContext->restore();
m_platformContext->canvas()->endPlatformPaint();
}
diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
index 88035d5..6bd7d7c 100644
--- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp
@@ -42,12 +42,11 @@
#include "FontPlatformData.h"
#include "NotImplemented.h"
+#include "OpenTypeSanitizer.h"
#include "SharedBuffer.h"
#if PLATFORM(WIN_OS)
#include <objbase.h>
-#include <t2embapi.h>
-#pragma comment(lib, "t2embed")
#elif PLATFORM(LINUX)
#include <cstring>
#endif
@@ -57,13 +56,8 @@ namespace WebCore {
FontCustomPlatformData::~FontCustomPlatformData()
{
#if PLATFORM(WIN_OS)
- if (m_fontReference) {
- if (m_name.isNull()) {
- ULONG status;
- TTDeleteEmbeddedFont(m_fontReference, 0, &status);
- } else
- RemoveFontMemResourceEx(m_fontReference);
- }
+ if (m_fontReference)
+ RemoveFontMemResourceEx(m_fontReference);
#elif PLATFORM(LINUX)
if (m_fontReference)
m_fontReference->unref();
@@ -76,19 +70,15 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
ASSERT(m_fontReference);
LOGFONT logFont;
- if (m_name.isNull())
- TTGetNewFontName(&m_fontReference, logFont.lfFaceName, LF_FACESIZE, 0, 0);
- else {
- // m_name comes from createUniqueFontName, which, in turn, gets
- // it from base64-encoded uuid (128-bit). So, m_name
- // can never be longer than LF_FACESIZE (32).
- if (m_name.length() + 1 >= LF_FACESIZE) {
- ASSERT_NOT_REACHED();
- return FontPlatformData();
- }
- memcpy(logFont.lfFaceName, m_name.charactersWithNullTermination(),
- sizeof(logFont.lfFaceName[0]) * (1 + m_name.length()));
+ // m_name comes from createUniqueFontName, which, in turn, gets
+ // it from base64-encoded uuid (128-bit). So, m_name
+ // can never be longer than LF_FACESIZE (32).
+ if (m_name.length() + 1 >= LF_FACESIZE) {
+ ASSERT_NOT_REACHED();
+ return FontPlatformData();
}
+ memcpy(logFont.lfFaceName, m_name.charactersWithNullTermination(),
+ sizeof(logFont.lfFaceName[0]) * (1 + m_name.length()));
// FIXME: almost identical to FillLogFont in FontCacheWin.cpp.
// Need to refactor.
@@ -119,69 +109,6 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
}
#if PLATFORM(WIN_OS)
-// FIXME: EOTStream class and static functions in this #if block are
-// duplicated from platform/graphics/win/FontCustomPlatformData.cpp
-// and need to be shared.
-
-// Streams the concatenation of a header and font data.
-class EOTStream {
-public:
- EOTStream(const EOTHeader& eotHeader, const SharedBuffer* fontData, size_t overlayDst, size_t overlaySrc, size_t overlayLength)
- : m_eotHeader(eotHeader)
- , m_fontData(fontData)
- , m_overlayDst(overlayDst)
- , m_overlaySrc(overlaySrc)
- , m_overlayLength(overlayLength)
- , m_offset(0)
- , m_inHeader(true)
- {
- }
-
- size_t read(void* buffer, size_t count);
-
-private:
- const EOTHeader& m_eotHeader;
- const SharedBuffer* m_fontData;
- size_t m_overlayDst;
- size_t m_overlaySrc;
- size_t m_overlayLength;
- size_t m_offset;
- bool m_inHeader;
-};
-
-size_t EOTStream::read(void* buffer, size_t count)
-{
- size_t bytesToRead = count;
- if (m_inHeader) {
- size_t bytesFromHeader = std::min(m_eotHeader.size() - m_offset, count);
- memcpy(buffer, m_eotHeader.data() + m_offset, bytesFromHeader);
- m_offset += bytesFromHeader;
- bytesToRead -= bytesFromHeader;
- if (m_offset == m_eotHeader.size()) {
- m_inHeader = false;
- m_offset = 0;
- }
- }
- if (bytesToRead && !m_inHeader) {
- size_t bytesFromData = std::min(m_fontData->size() - m_offset, bytesToRead);
- memcpy(buffer, m_fontData->data() + m_offset, bytesFromData);
- if (m_offset < m_overlayDst + m_overlayLength && m_offset + bytesFromData >= m_overlayDst) {
- size_t dstOffset = std::max<int>(m_overlayDst - m_offset, 0);
- size_t srcOffset = std::max<int>(0, m_offset - m_overlayDst);
- size_t bytesToCopy = std::min(bytesFromData - dstOffset, m_overlayLength - srcOffset);
- memcpy(reinterpret_cast<char*>(buffer) + dstOffset, m_fontData->data() + m_overlaySrc + srcOffset, bytesToCopy);
- }
- m_offset += bytesFromData;
- bytesToRead -= bytesFromData;
- }
- return count - bytesToRead;
-}
-
-static unsigned long WINAPIV readEmbedProc(void* stream, void* buffer, unsigned long length)
-{
- return static_cast<EOTStream*>(stream)->read(buffer, length);
-}
-
// Creates a unique and unpredictable font name, in order to avoid collisions and to
// not allow access from CSS.
static String createUniqueFontName()
@@ -245,38 +172,22 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
+#if ENABLE(OPENTYPE_SANITIZER)
+ OpenTypeSanitizer sanitizer(buffer);
+ RefPtr<SharedBuffer> transcodeBuffer = sanitizer.sanitize();
+ if (!transcodeBuffer)
+ return 0; // validation failed.
+ buffer = transcodeBuffer.get();
+#endif
+
#if PLATFORM(WIN_OS)
- // Introduce the font to GDI. AddFontMemResourceEx cannot be used, because it will pollute the process's
+ // Introduce the font to GDI. AddFontMemResourceEx should be used with care, because it will pollute the process's
// font namespace (Windows has no API for creating an HFONT from data without exposing the font to the
- // entire process first). TTLoadEmbeddedFont lets us override the font family name, so using a unique name
- // we avoid namespace collisions.
-
+ // entire process first).
String fontName = createUniqueFontName();
-
- // TTLoadEmbeddedFont works only with Embedded OpenType (.eot) data,
- // so we need to create an EOT header and prepend it to the font data.
- EOTHeader eotHeader;
- size_t overlayDst;
- size_t overlaySrc;
- size_t overlayLength;
-
- if (!getEOTHeader(buffer, eotHeader, overlayDst, overlaySrc, overlayLength))
+ HANDLE fontReference = renameAndActivateFont(buffer, fontName);
+ if (!fontReference)
return 0;
-
- HANDLE fontReference;
- ULONG privStatus;
- ULONG status;
- EOTStream eotStream(eotHeader, buffer, overlayDst, overlaySrc, overlayLength);
-
- LONG loadEmbeddedFontResult = TTLoadEmbeddedFont(&fontReference, TTLOAD_PRIVATE, &privStatus, LICENSE_PREVIEWPRINT, &status, readEmbedProc, &eotStream, const_cast<LPWSTR>(fontName.charactersWithNullTermination()), 0, 0);
- if (loadEmbeddedFontResult == E_NONE)
- fontName = String();
- else {
- fontReference = renameAndActivateFont(buffer, fontName);
- if (!fontReference)
- return 0;
- }
-
return new FontCustomPlatformData(fontReference, fontName);
#elif PLATFORM(LINUX)
RemoteFontStream stream(buffer);
diff --git a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
index a5a6e1f..1386163 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
@@ -46,12 +46,6 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String&)
-{
- notImplemented();
- return 0;
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
{
notImplemented();
diff --git a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
index 93e36ba..23ca698 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
@@ -39,11 +39,6 @@
namespace WebCore {
-PassRefPtr<Icon> Icon::createIconForFile(const String&)
-{
- return 0;
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
{
return 0;
diff --git a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
index b419e6f..b0145f8 100644
--- a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
@@ -52,26 +52,11 @@ Icon::~Icon()
DestroyIcon(m_icon);
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
-{
- SHFILEINFO sfi;
- memset(&sfi, 0, sizeof(sfi));
-
- String tmpFilename = filename;
- if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON))
- return 0;
-
- return adoptRef(new Icon(sfi.hIcon));
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- // FIXME: support multiple files.
+ // FIXME: We can't access icons directly from renderer processes.
// http://code.google.com/p/chromium/issues/detail?id=4092
- if (!filenames.size())
- return 0;
-
- return createIconForFile(filenames[0]);
+ return 0;
}
void Icon::paint(GraphicsContext* context, const IntRect& rect)
diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
index 7957d5a..6dcd595 100644
--- a/WebCore/platform/graphics/chromium/TransparencyWin.cpp
+++ b/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -275,7 +275,7 @@ void TransparencyWin::setupLayerForWhiteLayer()
if (!m_validLayer)
return;
- m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white);
+ m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white, DeviceColorSpace);
// Layer rect represents the part of the original layer.
}
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 2364cc4..f362148 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -111,10 +111,10 @@ void FEBlend::apply(Filter* filter)
if (!getEffectContext())
return;
- IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
- IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
IntRect imageRect(IntPoint(), resultImage()->size());
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index a2ed9bd..f422157 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -164,7 +164,7 @@ void FEColorMatrix::apply(Filter* filter)
if (!filterContext)
return;
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
IntRect imageRect(IntPoint(), resultImage()->size());
PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 0d76d8d..1d9cfff 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -165,7 +165,7 @@ void FEComponentTransfer::apply(Filter* filter)
for (unsigned channel = 0; channel < 4; channel++)
(*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
- IntRect drawingRect = calculateDrawingIntRect(m_in->subRegion());
+ IntRect drawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect));
CanvasPixelArray* srcPixelArray(imageData->data());
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 1b41165..c540cb7 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -133,32 +133,32 @@ void FEComposite::apply(Filter* filter)
FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f);
switch (m_type) {
case FECOMPOSITE_OPERATOR_OVER:
- filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()));
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
break;
case FECOMPOSITE_OPERATOR_IN:
filterContext->save();
- filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->subRegion()), m_in2->resultImage());
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
+ filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage());
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
filterContext->restore();
break;
case FECOMPOSITE_OPERATOR_OUT:
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
- filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()), srcRect, CompositeDestinationOut);
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
break;
case FECOMPOSITE_OPERATOR_ATOP:
- filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()));
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()), srcRect, CompositeSourceAtop);
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
break;
case FECOMPOSITE_OPERATOR_XOR:
- filterContext->drawImage(m_in2->resultImage()->image(), calculateDrawingRect(m_in2->subRegion()));
- filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()), srcRect, CompositeXOR);
+ filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+ filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
break;
case FECOMPOSITE_OPERATOR_ARITHMETIC: {
- IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
- IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->scaledSubRegion());
RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
CanvasPixelArray* srcPixelArrayB(imageData->data());
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index f480f10..0b97e39 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -32,6 +32,8 @@
#include <math.h>
#include <wtf/MathExtras.h>
+using std::max;
+
namespace WebCore {
FEGaussianBlur::FEGaussianBlur(FilterEffect* in, const float& x, const float& y)
@@ -111,10 +113,12 @@ void FEGaussianBlur::apply(Filter* filter)
if (m_x == 0 || m_y == 0)
return;
- unsigned sdx = static_cast<unsigned>(floor(m_x * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
- unsigned sdy = static_cast<unsigned>(floor(m_y * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
+ unsigned sdx = static_cast<unsigned>(floor(m_x * filter->filterResolution().width() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
+ unsigned sdy = static_cast<unsigned>(floor(m_y * filter->filterResolution().height() * 3 * sqrt(2 * piDouble) / 4.f + 0.5f));
+ sdx = max(sdx, static_cast<unsigned>(1));
+ sdy = max(sdy, static_cast<unsigned>(1));
- IntRect effectDrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ IntRect effectDrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
RefPtr<ImageData> srcImageData(m_in->resultImage()->getPremultipliedImageData(effectDrawingRect));
CanvasPixelArray* srcPixelArray(srcImageData->data());
diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h
index ee97afc..8924b94 100644
--- a/WebCore/platform/graphics/filters/Filter.h
+++ b/WebCore/platform/graphics/filters/Filter.h
@@ -22,6 +22,7 @@
#if ENABLE(FILTERS)
#include "FloatRect.h"
+#include "FloatSize.h"
#include "ImageBuffer.h"
#include "StringHash.h"
@@ -40,15 +41,21 @@ namespace WebCore {
void setSourceImage(PassOwnPtr<ImageBuffer> sourceImage) { m_sourceImage = sourceImage; }
ImageBuffer* sourceImage() { return m_sourceImage.get(); }
- virtual FloatRect sourceImageRect() = 0;
- virtual FloatRect filterRegion() = 0;
+ FloatSize filterResolution() const { return m_filterResolution; }
+ void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; }
+
+ virtual FloatRect sourceImageRect() const = 0;
+ virtual FloatRect filterRegion() const = 0;
// SVG specific
- virtual void calculateEffectSubRegion(FilterEffect*) = 0;
- virtual bool effectBoundingBoxMode() = 0;
+ virtual void calculateEffectSubRegion(FilterEffect*) { }
+
+ virtual FloatSize maxImageSize() const = 0;
+ virtual bool effectBoundingBoxMode() const = 0;
private:
OwnPtr<ImageBuffer> m_sourceImage;
+ FloatSize m_filterResolution;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index 68900b5..5583813 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -58,21 +58,21 @@ FloatRect FilterEffect::calculateEffectRect(Filter* filter)
IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect)
{
- IntPoint location = roundedIntPoint(FloatPoint(subRegion().x() - effectRect.x(),
- subRegion().y() - effectRect.y()));
+ IntPoint location = roundedIntPoint(FloatPoint(scaledSubRegion().x() - effectRect.x(),
+ scaledSubRegion().y() - effectRect.y()));
return IntRect(location, resultImage()->size());
}
FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect)
{
- FloatPoint startPoint = FloatPoint(srcRect.x() - subRegion().x(), srcRect.y() - subRegion().y());
+ FloatPoint startPoint = FloatPoint(srcRect.x() - scaledSubRegion().x(), srcRect.y() - scaledSubRegion().y());
FloatRect drawingRect = FloatRect(startPoint, srcRect.size());
return drawingRect;
}
GraphicsContext* FilterEffect::getEffectContext()
{
- IntRect bufferRect = enclosingIntRect(subRegion());
+ IntRect bufferRect = enclosingIntRect(scaledSubRegion());
m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB);
return m_effectBuffer->context();
}
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index b30e513..a46d795 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -44,6 +44,12 @@ namespace WebCore {
FloatRect subRegion() const { return m_subRegion; }
void setSubRegion(const FloatRect& subRegion) { m_subRegion = subRegion; }
+ FloatRect scaledSubRegion() const { return m_scaledSubRegion; }
+ void setScaledSubRegion(const FloatRect& scaledSubRegion) { m_scaledSubRegion = scaledSubRegion; }
+
+ FloatRect effectBoundaries() const { return m_effectBoundaries; }
+ void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
+
bool hasX() { return m_hasX; }
void setHasX(bool value) { m_hasX = value; }
@@ -96,7 +102,9 @@ namespace WebCore {
bool m_alphaImage;
+ FloatRect m_effectBoundaries;
FloatRect m_subRegion;
+ FloatRect m_scaledSubRegion;
FloatRect m_unionOfChildEffectSubregions;
mutable OwnPtr<ImageBuffer> m_effectBuffer;
diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.cpp b/WebCore/platform/graphics/filters/ImageBufferFilter.cpp
new file mode 100644
index 0000000..33953d6
--- /dev/null
+++ b/WebCore/platform/graphics/filters/ImageBufferFilter.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * 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
+ * aint 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(FILTERS)
+#include "ImageBufferFilter.h"
+
+#include "FloatSize.h"
+
+namespace WebCore {
+
+ImageBufferFilter::ImageBufferFilter()
+ : Filter()
+{
+ setFilterResolution(FloatSize(1.f, 1.f));
+}
+
+PassRefPtr<ImageBufferFilter> ImageBufferFilter::create()
+{
+ return adoptRef(new ImageBufferFilter());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
diff --git a/WebCore/platform/graphics/filters/ImageBufferFilter.h b/WebCore/platform/graphics/filters/ImageBufferFilter.h
new file mode 100644
index 0000000..a2775ea
--- /dev/null
+++ b/WebCore/platform/graphics/filters/ImageBufferFilter.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
+ *
+ * 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
+ * aint 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.
+ */
+
+#ifndef ImageBufferFilter_h
+#define ImageBufferFilter_h
+
+#if ENABLE(FILTERS)
+#include "Filter.h"
+#include "FilterEffect.h"
+#include "FloatRect.h"
+#include "FloatSize.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class ImageBufferFilter : public Filter {
+public:
+ static PassRefPtr<ImageBufferFilter> create();
+
+ virtual FloatRect filterRegion() const { return FloatRect(); }
+ virtual FloatRect sourceImageRect() const { return FloatRect(); }
+
+ // SVG specific
+ virtual bool effectBoundingBoxMode() const { return false; }
+
+ virtual FloatSize maxImageSize() const { return FloatSize(); }
+ virtual void calculateEffectSubRegion(FilterEffect*) { }
+
+private:
+ ImageBufferFilter();
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(FILTERS)
+
+#endif // ImageBufferFilter_h
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index 1b6309b..539bb44 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -50,6 +50,8 @@ FloatRect SourceAlpha::calculateEffectRect(Filter* filter)
if (filter->sourceImageRect().y() < filter->filterRegion().y())
clippedSourceRect.setY(filter->filterRegion().y());
setSubRegion(clippedSourceRect);
+ clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ setScaledSubRegion(clippedSourceRect);
return filter->filterRegion();
}
@@ -64,7 +66,7 @@ void SourceAlpha::apply(Filter* filter)
FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size());
filterContext->save();
filterContext->clipToImageBuffer(imageRect, filter->sourceImage());
- filterContext->fillRect(imageRect, Color::black);
+ filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
filterContext->restore();
}
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
index 023eeac..cc55618 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -49,6 +49,8 @@ FloatRect SourceGraphic::calculateEffectRect(Filter* filter)
if (filter->sourceImageRect().y() < filter->filterRegion().y())
clippedSourceRect.setY(filter->filterRegion().y());
setSubRegion(clippedSourceRect);
+ clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+ setScaledSubRegion(clippedSourceRect);
return filter->filterRegion();
}
@@ -58,7 +60,7 @@ void SourceGraphic::apply(Filter* filter)
if (!filterContext)
return;
- filterContext->drawImage(filter->sourceImage()->image(), IntPoint());
+ filterContext->drawImage(filter->sourceImage()->image(), DeviceColorSpace, IntPoint());
}
void SourceGraphic::dump()
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index ee86f96..5c320e0 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -259,7 +259,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
// Re-enable the platform shadow we disabled earlier
if (hasShadow)
- context->setShadow(shadowSize, shadowBlur, shadowColor);
+ context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace);
// Pango sometimes leaves behind paths we don't want
cairo_new_path(cr);
diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp
index e08c1ab..3563a59 100644
--- a/WebCore/platform/graphics/gtk/IconGtk.cpp
+++ b/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -87,23 +87,25 @@ static String lookupIconName(String MIMEType)
return GTK_STOCK_FILE;
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- if (!g_path_skip_root(filename.utf8().data()))
+ if (filenames.isEmpty())
return 0;
- String MIMEType = MIMETypeRegistry::getMIMETypeForPath(filename);
- String iconName = lookupIconName(MIMEType);
+ if (filenames.size() == 1) {
+ if (!g_path_skip_root(filenames[0].utf8().data()))
+ return 0;
- RefPtr<Icon> icon = adoptRef(new Icon);
- icon->m_icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), iconName.utf8().data(), 16, GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
- if (!icon->m_icon)
- return 0;
- return icon.release();
-}
+ String MIMEType = MIMETypeRegistry::getMIMETypeForPath(filenames[0]);
+ String iconName = lookupIconName(MIMEType);
+
+ RefPtr<Icon> icon = adoptRef(new Icon);
+ icon->m_icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), iconName.utf8().data(), 16, GTK_ICON_LOOKUP_USE_BUILTIN, 0);
+ if (!icon->m_icon)
+ return 0;
+ return icon.release();
+ }
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
-{
//FIXME: Implement this
return 0;
}
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
index 8d1d261..a023dae 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
@@ -46,7 +46,7 @@
#include <gst/video/video.h>
#include <limits>
#include <math.h>
-#include <wtf/GOwnPtr.h>
+#include <wtf/gtk/GOwnPtr.h>
using namespace std;
@@ -66,11 +66,15 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
error = MediaPlayer::Empty;
- if (err->domain == GST_CORE_ERROR || err->domain == GST_LIBRARY_ERROR)
- error = MediaPlayer::DecodeError;
- else if (err->domain == GST_RESOURCE_ERROR)
+ if (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND
+ || err->code == GST_STREAM_ERROR_WRONG_TYPE
+ || err->code == GST_STREAM_ERROR_FAILED
+ || err->code == GST_CORE_ERROR_MISSING_PLUGIN
+ || err->code == GST_RESOURCE_ERROR_NOT_FOUND)
error = MediaPlayer::FormatError;
else if (err->domain == GST_STREAM_ERROR)
+ error = MediaPlayer::DecodeError;
+ else if (err->domain == GST_RESOURCE_ERROR)
error = MediaPlayer::NetworkError;
if (mp)
@@ -95,6 +99,33 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
return true;
}
+static float playbackPosition(GstElement* playbin)
+{
+
+ float ret = 0.0;
+
+ GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
+ if (!gst_element_query(playbin, query)) {
+ LOG_VERBOSE(Media, "Position query failed...");
+ gst_query_unref(query);
+ return ret;
+ }
+
+ gint64 position;
+ gst_query_parse_position(query, 0, &position);
+
+ // Position is available only if the pipeline is not in NULL or
+ // READY state.
+ if (position != static_cast<gint64>(GST_CLOCK_TIME_NONE))
+ ret = static_cast<float>(position) / static_cast<float>(GST_SECOND);
+
+ LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
+
+ gst_query_unref(query);
+
+ return ret;
+}
+
void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate)
{
g_return_if_fail(GST_IS_BUFFER(buffer));
@@ -115,16 +146,34 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
static bool gstInitialized = false;
-static void do_gst_init()
+static bool do_gst_init()
{
// FIXME: We should pass the arguments from the command line
if (!gstInitialized) {
- gst_init(0, 0);
- gstInitialized = true;
- gst_element_register(0, "webkitmediasrc", GST_RANK_PRIMARY,
- WEBKIT_TYPE_DATA_SRC);
+ GOwnPtr<GError> error;
+ gstInitialized = gst_init_check(0, 0, &error.outPtr());
+ if (!gstInitialized)
+ LOG_VERBOSE(Media, "Could not initialize GStreamer: %s",
+ error ? error->message : "unknown error occurred");
+ else
+ gst_element_register(0, "webkitmediasrc", GST_RANK_PRIMARY,
+ WEBKIT_TYPE_DATA_SRC);
}
+ return gstInitialized;
+}
+
+bool MediaPlayerPrivate::isAvailable()
+{
+ if (!do_gst_init())
+ return false;
+
+ GstElementFactory* factory = gst_element_factory_find("playbin2");
+ if (factory) {
+ gst_object_unref(GST_OBJECT(factory));
+ return true;
+ }
+ return false;
}
MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
@@ -132,6 +181,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_playBin(0)
, m_videoSink(0)
, m_source(0)
+ , m_seekTime(0)
+ , m_changingRate(false)
, m_endTime(numeric_limits<float>::infinity())
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
@@ -181,14 +232,26 @@ void MediaPlayerPrivate::load(const String& url)
void MediaPlayerPrivate::play()
{
- LOG_VERBOSE(Media, "Play");
- gst_element_set_state(m_playBin, GST_STATE_PLAYING);
+ GstState state;
+ GstState pending;
+
+ gst_element_get_state(m_playBin, &state, &pending, 0);
+ if (state != GST_STATE_PLAYING && pending != GST_STATE_PLAYING) {
+ LOG_VERBOSE(Media, "Play");
+ gst_element_set_state(m_playBin, GST_STATE_PLAYING);
+ }
}
void MediaPlayerPrivate::pause()
{
- LOG_VERBOSE(Media, "Pause");
- gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ GstState state;
+ GstState pending;
+
+ gst_element_get_state(m_playBin, &state, &pending, 0);
+ if (state != GST_STATE_PAUSED && pending != GST_STATE_PAUSED) {
+ LOG_VERBOSE(Media, "Pause");
+ gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ }
}
float MediaPlayerPrivate::duration() const
@@ -202,7 +265,7 @@ float MediaPlayerPrivate::duration() const
GstFormat timeFormat = GST_FORMAT_TIME;
gint64 timeLength = 0;
- if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeFormat != GST_FORMAT_TIME || timeLength == GST_CLOCK_TIME_NONE) {
+ if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeFormat != GST_FORMAT_TIME || static_cast<guint64>(timeLength) == GST_CLOCK_TIME_NONE) {
LOG_VERBOSE(Media, "Time duration query failed.");
return numeric_limits<float>::infinity();
}
@@ -221,23 +284,11 @@ float MediaPlayerPrivate::currentTime() const
if (m_errorOccured)
return 0;
- float ret = 0.0;
+ if (m_seeking)
+ return m_seekTime;
- GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
- if (!gst_element_query(m_playBin, query)) {
- LOG_VERBOSE(Media, "Position query failed...");
- gst_query_unref(query);
- return ret;
- }
+ return playbackPosition(m_playBin);
- gint64 position;
- gst_query_parse_position(query, 0, &position);
- ret = (float) (position / 1000000000.0);
- LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
-
- gst_query_unref(query);
-
- return ret;
}
void MediaPlayerPrivate::seek(float time)
@@ -260,8 +311,10 @@ void MediaPlayerPrivate::seek(float time)
GST_SEEK_TYPE_SET, sec,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
LOG_VERBOSE(Media, "Seek to %f failed", time);
- else
+ else {
m_seeking = true;
+ m_seekTime = sec;
+ }
}
void MediaPlayerPrivate::setEndTime(float time)
@@ -310,10 +363,10 @@ IntSize MediaPlayerPrivate::naturalSize() const
gfloat pixelAspectRatio;
gint pixelAspectRatioNumerator, pixelAspectRatioDenominator;
- if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps) ||
- !gst_video_format_parse_caps(caps, NULL, &width, &height) ||
- !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
- &pixelAspectRatioDenominator)) {
+ if (!GST_IS_CAPS(caps) || !gst_caps_is_fixed(caps)
+ || !gst_video_format_parse_caps(caps, 0, &width, &height)
+ || !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
+ &pixelAspectRatioDenominator)) {
gst_object_unref(GST_OBJECT(pad));
return IntSize();
}
@@ -353,16 +406,50 @@ void MediaPlayerPrivate::setVolume(float volume)
void MediaPlayerPrivate::setRate(float rate)
{
- if (rate == 0.0) {
- gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ GstState state;
+ GstState pending;
+
+ gst_element_get_state(m_playBin, &state, &pending, 0);
+ if ((state != GST_STATE_PLAYING && state != GST_STATE_PAUSED)
+ || (pending == GST_STATE_PAUSED))
return;
- }
if (m_isStreaming)
return;
+ m_changingRate = true;
+ float currentPosition = playbackPosition(m_playBin) * GST_SECOND;
+ GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH);
+ gint64 start, end;
+ bool mute = false;
+
LOG_VERBOSE(Media, "Set Rate to %f", rate);
- seek(currentTime());
+ if (rate >= 0) {
+ // Mute the sound if the playback rate is too extreme.
+ // TODO: in other cases we should perform pitch adjustments.
+ mute = (bool) (rate < 0.8 || rate > 2);
+ start = currentPosition;
+ end = GST_CLOCK_TIME_NONE;
+ } else {
+ start = 0;
+ mute = true;
+
+ // If we are at beginning of media, start from the end to
+ // avoid immediate EOS.
+ if (currentPosition <= 0)
+ end = duration() * GST_SECOND;
+ else
+ end = currentPosition;
+ }
+
+ LOG_VERBOSE(Media, "Need to mute audio: %d", (int) mute);
+
+ if (!gst_element_seek(m_playBin, rate, GST_FORMAT_TIME, flags,
+ GST_SEEK_TYPE_SET, start,
+ GST_SEEK_TYPE_SET, end))
+ LOG_VERBOSE(Media, "Set rate to %f failed", rate);
+ else
+ g_object_set(m_playBin, "mute", mute, NULL);
}
int MediaPlayerPrivate::dataRate() const
@@ -497,6 +584,11 @@ void MediaPlayerPrivate::updateStates()
} else
m_paused = true;
+ if (m_changingRate) {
+ m_player->rateChanged();
+ m_changingRate = false;
+ }
+
if (m_seeking) {
shouldUpdateAfterSeek = true;
m_seeking = false;
@@ -560,11 +652,6 @@ void MediaPlayerPrivate::loadStateChanged()
updateStates();
}
-void MediaPlayerPrivate::rateChanged()
-{
- updateStates();
-}
-
void MediaPlayerPrivate::sizeChanged()
{
notImplemented();
@@ -624,54 +711,36 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
return;
int width = 0, height = 0;
- int pixelAspectRatioNumerator = 0;
- int pixelAspectRatioDenominator = 0;
- double doublePixelAspectRatioNumerator = 0;
- double doublePixelAspectRatioDenominator = 0;
- double displayWidth;
- double displayHeight;
- double scale, gapHeight, gapWidth;
-
GstCaps *caps = gst_buffer_get_caps(m_buffer);
+ GstVideoFormat format;
- if (!gst_video_format_parse_caps(caps, NULL, &width, &height) ||
- !gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator, &pixelAspectRatioDenominator)) {
+ if (!gst_video_format_parse_caps(caps, &format, &width, &height)) {
gst_caps_unref(caps);
return;
}
- displayWidth = width;
- displayHeight = height;
- doublePixelAspectRatioNumerator = pixelAspectRatioNumerator;
- doublePixelAspectRatioDenominator = pixelAspectRatioDenominator;
+ cairo_format_t cairoFormat;
+ if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA)
+ cairoFormat = CAIRO_FORMAT_ARGB32;
+ else
+ cairoFormat = CAIRO_FORMAT_RGB24;
cairo_t* cr = context->platformContext();
cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(m_buffer),
- CAIRO_FORMAT_RGB24,
+ cairoFormat,
width, height,
4 * width);
cairo_save(cr);
- cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-
- displayWidth *= doublePixelAspectRatioNumerator / doublePixelAspectRatioDenominator;
- displayHeight *= doublePixelAspectRatioDenominator / doublePixelAspectRatioNumerator;
- scale = MIN (rect.width () / displayWidth, rect.height () / displayHeight);
- displayWidth *= scale;
- displayHeight *= scale;
+ // translate and scale the context to correct size
+ cairo_translate(cr, rect.x(), rect.y());
+ cairo_scale(cr, static_cast<double>(rect.width()) / width, static_cast<double>(rect.height()) / height);
- // Calculate gap between border an picture
- gapWidth = (rect.width() - displayWidth) / 2.0;
- gapHeight = (rect.height() - displayHeight) / 2.0;
-
- // paint the rectangle on the context and draw the surface inside.
- cairo_translate(cr, rect.x() + gapWidth, rect.y() + gapHeight);
- cairo_rectangle(cr, 0, 0, rect.width(), rect.height());
- cairo_scale(cr, doublePixelAspectRatioNumerator / doublePixelAspectRatioDenominator,
- doublePixelAspectRatioDenominator / doublePixelAspectRatioNumerator);
- cairo_scale(cr, scale, scale);
+ // And paint it.
cairo_set_source_surface(cr, src, 0, 0);
+ cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_PAD);
+ cairo_rectangle(cr, 0, 0, width, height);
cairo_fill(cr);
cairo_restore(cr);
@@ -688,76 +757,91 @@ static HashSet<String> mimeTypeCache()
static bool typeListInitialized = false;
if (!typeListInitialized) {
- // These subtypes are already beeing supported by WebKit itself
- HashSet<String> ignoredApplicationSubtypes;
- ignoredApplicationSubtypes.add(String("javascript"));
- ignoredApplicationSubtypes.add(String("ecmascript"));
- ignoredApplicationSubtypes.add(String("x-javascript"));
- ignoredApplicationSubtypes.add(String("xml"));
- ignoredApplicationSubtypes.add(String("xhtml+xml"));
- ignoredApplicationSubtypes.add(String("rss+xml"));
- ignoredApplicationSubtypes.add(String("atom+xml"));
- ignoredApplicationSubtypes.add(String("x-ftp-directory"));
- ignoredApplicationSubtypes.add(String("x-java-applet"));
- ignoredApplicationSubtypes.add(String("x-java-bean"));
- ignoredApplicationSubtypes.add(String("x-java-vm"));
- ignoredApplicationSubtypes.add(String("x-shockwave-flash"));
+ // Build a whitelist of mime-types known to be supported by
+ // GStreamer.
+ HashSet<String> handledApplicationSubtypes;
+ handledApplicationSubtypes.add(String("ogg"));
+ handledApplicationSubtypes.add(String("x-3gp"));
+ handledApplicationSubtypes.add(String("vnd.rn-realmedia"));
+ handledApplicationSubtypes.add(String("x-pn-realaudio"));
GList* factories = gst_type_find_factory_get_list();
for (GList* iterator = factories; iterator; iterator = iterator->next) {
GstTypeFindFactory* factory = GST_TYPE_FIND_FACTORY(iterator->data);
GstCaps* caps = gst_type_find_factory_get_caps(factory);
- // Splitting the capability by comma and taking the first part
- // as capability can be something like "audio/x-wavpack, framed=(boolean)false"
- GOwnPtr<gchar> capabilityString(gst_caps_to_string(caps));
- gchar** capability = g_strsplit(capabilityString.get(), ",", 2);
- gchar** mimetype = g_strsplit(capability[0], "/", 2);
-
- // GStreamer plugins can be capable of supporting types which WebKit supports
- // by default. In that case, we should not consider these types supportable by GStreamer.
- // Examples of what GStreamer can support but should not be added:
- // text/plain, text/html, image/jpeg, application/xml
- if (g_str_equal(mimetype[0], "audio") ||
- g_str_equal(mimetype[0], "video") ||
- (g_str_equal(mimetype[0], "application") &&
- !ignoredApplicationSubtypes.contains(String(mimetype[1])))) {
- cache.add(String(capability[0]));
-
- // These formats are supported by GStreamer, but not correctly advertised
- if (g_str_equal(capability[0], "video/x-h264") ||
- g_str_equal(capability[0], "audio/x-m4a")) {
+ if (!caps)
+ continue;
+
+ for (guint structureIndex = 0; structureIndex < gst_caps_get_size(caps); structureIndex++) {
+ GstStructure* structure = gst_caps_get_structure(caps, structureIndex);
+ const gchar* name = gst_structure_get_name(structure);
+ bool cached = false;
+
+ // These formats are supported by GStreamer, but not
+ // correctly advertised.
+ if (g_str_equal(name, "video/x-h264")
+ || g_str_equal(name, "audio/x-m4a")) {
cache.add(String("video/mp4"));
cache.add(String("audio/aac"));
+ cached = true;
}
- if (g_str_equal(capability[0], "video/x-theora"))
+ if (g_str_equal(name, "video/x-theora")) {
cache.add(String("video/ogg"));
+ cached = true;
+ }
- if (g_str_equal(capability[0], "audio/x-wav"))
- cache.add(String("audio/wav"));
+ if (g_str_equal(name, "audio/x-vorbis")) {
+ cache.add(String("audio/ogg"));
+ cached = true;
+ }
- if (g_str_equal(capability[0], "audio/mpeg")) {
- // This is what we are handling: mpegversion=(int)1, layer=(int)[ 1, 3 ]
- gchar** versionAndLayer = g_strsplit(capability[1], ",", 2);
+ if (g_str_equal(name, "audio/x-wav")) {
+ cache.add(String("audio/wav"));
+ cached = true;
+ }
- if (g_str_has_suffix (versionAndLayer[0], "(int)1")) {
- for (int i = 0; versionAndLayer[1][i] != '\0'; i++) {
- if (versionAndLayer[1][i] == '1')
+ if (g_str_equal(name, "audio/mpeg")) {
+ cache.add(String(name));
+ cached = true;
+
+ // This is what we are handling:
+ // mpegversion=(int)1, layer=(int)[ 1, 3 ]
+ gint mpegVersion = 0;
+ if (gst_structure_get_int(structure, "mpegversion", &mpegVersion) && (mpegVersion == 1)) {
+ const GValue* layer = gst_structure_get_value(structure, "layer");
+ if (G_VALUE_TYPE(layer) == GST_TYPE_INT_RANGE) {
+ gint minLayer = gst_value_get_int_range_min(layer);
+ gint maxLayer = gst_value_get_int_range_max(layer);
+ if (minLayer <= 1 <= maxLayer)
cache.add(String("audio/mp1"));
- else if (versionAndLayer[1][i] == '2')
+ if (minLayer <= 2 <= maxLayer)
cache.add(String("audio/mp2"));
- else if (versionAndLayer[1][i] == '3')
+ if (minLayer <= 3 <= maxLayer)
cache.add(String("audio/mp3"));
}
}
+ }
- g_strfreev(versionAndLayer);
+ if (!cached) {
+ // GStreamer plugins can be capable of supporting
+ // types which WebKit supports by default. In that
+ // case, we should not consider these types
+ // supportable by GStreamer. Examples of what
+ // GStreamer can support but should not be added:
+ // text/plain, text/html, image/jpeg,
+ // application/xml
+ gchar** mimetype = g_strsplit(name, "/", 2);
+ if (g_str_equal(mimetype[0], "audio")
+ || g_str_equal(mimetype[0], "video")
+ || (g_str_equal(mimetype[0], "application")
+ && handledApplicationSubtypes.contains(String(mimetype[1]))))
+ cache.add(String(name));
+
+ g_strfreev(mimetype);
}
}
-
- g_strfreev(capability);
- g_strfreev(mimetype);
}
gst_plugin_feature_list_free(factories);
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
index 54da420..6ab8edb 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
@@ -29,6 +29,7 @@
#include <cairo.h>
#include <glib.h>
+#include <gst/gst.h>
typedef struct _WebKitVideoSink WebKitVideoSink;
typedef struct _GstBuffer GstBuffer;
@@ -89,7 +90,6 @@ namespace WebCore {
void setSize(const IntSize&);
void loadStateChanged();
- void rateChanged();
void sizeChanged();
void timeChanged();
void volumeChanged();
@@ -109,7 +109,7 @@ namespace WebCore {
static void getSupportedTypes(HashSet<String>&);
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
- static bool isAvailable() { return true; }
+ static bool isAvailable();
void updateStates();
void cancelSeek();
@@ -124,6 +124,8 @@ namespace WebCore {
GstElement* m_playBin;
GstElement* m_videoSink;
GstElement* m_source;
+ GstClockTime m_seekTime;
+ bool m_changingRate;
float m_endTime;
bool m_isEndReached;
MediaPlayer::NetworkState m_networkState;
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
index 9a616f4..df25393 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
@@ -39,8 +39,6 @@
#include "FontDescription.h"
#include "GlyphBuffer.h"
#include <cairo.h>
-#include <unicode/uchar.h>
-#include <unicode/unorm.h>
#include <wtf/MathExtras.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
index b5e1a8b..5e0f8e2 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
@@ -37,21 +37,15 @@ static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink",
GST_PAD_SINK, GST_PAD_ALWAYS,
// CAIRO_FORMAT_RGB24 used to render the video buffers is little/big endian dependant.
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- GST_STATIC_CAPS(GST_VIDEO_CAPS_BGRx)
+ GST_STATIC_CAPS(GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_BGRA)
#else
- GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB)
+ GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_ARGB)
#endif
);
GST_DEBUG_CATEGORY_STATIC(webkit_video_sink_debug);
#define GST_CAT_DEFAULT webkit_video_sink_debug
-static GstElementDetails webkit_video_sink_details =
- GST_ELEMENT_DETAILS((gchar*) "WebKit video sink",
- (gchar*) "Sink/Video",
- (gchar*) "Sends video data from a GStreamer pipeline to a Cairo surface",
- (gchar*) "Alp Toker <alp@atoker.com>");
-
enum {
REPAINT_REQUESTED,
LAST_SIGNAL
@@ -98,7 +92,9 @@ webkit_video_sink_base_init(gpointer g_class)
GstElementClass* element_class = GST_ELEMENT_CLASS(g_class);
gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinktemplate));
- gst_element_class_set_details(element_class, &webkit_video_sink_details);
+ gst_element_class_set_details_simple(element_class, "WebKit video sink",
+ "Sink/Video", "Sends video data from a GStreamer pipeline to a Cairo surface",
+ "Alp Toker <alp@atoker.com>");
}
static void
@@ -129,11 +125,6 @@ webkit_video_sink_timeout_func(gpointer data)
return FALSE;
}
- if (G_UNLIKELY(!GST_BUFFER_CAPS(buffer))) {
- buffer = gst_buffer_make_metadata_writable(buffer);
- gst_buffer_set_caps(buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(sink)));
- }
-
g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0, buffer);
gst_buffer_unref(buffer);
g_cond_signal(priv->data_cond);
@@ -157,6 +148,71 @@ webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer)
priv->buffer = gst_buffer_ref(buffer);
+ // For the unlikely case where the buffer has no caps, the caps
+ // are implicitely the caps of the pad. This shouldn't happen.
+ if (G_UNLIKELY(!GST_BUFFER_CAPS(buffer))) {
+ buffer = priv->buffer = gst_buffer_make_metadata_writable(priv->buffer);
+ gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(bsink)));
+ }
+
+ GstCaps *caps = GST_BUFFER_CAPS(buffer);
+ GstVideoFormat format;
+ int width, height;
+ if (G_UNLIKELY(!gst_video_format_parse_caps(caps, &format, &width, &height))) {
+ gst_buffer_unref(buffer);
+ g_mutex_unlock(priv->buffer_mutex);
+ return GST_FLOW_ERROR;
+ }
+
+ // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't.
+ // Here we convert to Cairo's ARGB.
+ if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) {
+ // Because GstBaseSink::render() only owns the buffer reference in the
+ // method scope we can't use gst_buffer_make_writable() here. Also
+ // The buffer content should not be changed here because the same buffer
+ // could be passed multiple times to this method (in theory)
+ GstBuffer *newBuffer = gst_buffer_try_new_and_alloc(GST_BUFFER_SIZE(buffer));
+
+ // Check if allocation failed
+ if (G_UNLIKELY(!newBuffer)) {
+ gst_buffer_unref(buffer);
+ g_mutex_unlock(priv->buffer_mutex);
+ return GST_FLOW_ERROR;
+ }
+
+ gst_buffer_copy_metadata(newBuffer, buffer, (GstBufferCopyFlags) GST_BUFFER_COPY_ALL);
+
+ // We don't use Color::premultipliedARGBFromColor() here because
+ // one function call per video pixel is just too expensive:
+ // For 720p/PAL for example this means 1280*720*25=23040000
+ // function calls per second!
+ unsigned short alpha;
+ const guint8 *source = GST_BUFFER_DATA(buffer);
+ guint8 *destination = GST_BUFFER_DATA(newBuffer);
+
+ for (int x = 0; x < height; x++) {
+ for (int y = 0; y < width; y++) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ alpha = source[3];
+ destination[0] = (source[0] * alpha + 128) / 255;
+ destination[1] = (source[1] * alpha + 128) / 255;
+ destination[2] = (source[2] * alpha + 128) / 255;
+ destination[3] = alpha;
+#else
+ alpha = source[0];
+ destination[0] = alpha;
+ destination[1] = (source[1] * alpha + 128) / 255;
+ destination[2] = (source[2] * alpha + 128) / 255;
+ destination[3] = (source[3] * alpha + 128) / 255;
+#endif
+ source += 4;
+ destination += 4;
+ }
+ }
+ gst_buffer_unref(buffer);
+ buffer = priv->buffer = newBuffer;
+ }
+
// Use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations.
priv->timeout_id = g_timeout_add_full(G_PRIORITY_HIGH_IDLE + 20, 0,
webkit_video_sink_timeout_func,
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
index c23b8a9..4728d56 100644
--- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -152,7 +152,7 @@ void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* p
m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle());
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -169,7 +169,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled() || !color.alpha())
return;
@@ -477,7 +477,7 @@ void GraphicsContext::setPlatformFont(const Font& font)
m_data->m_view->SetFont(font.primaryFont()->platformData().font());
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -519,7 +519,7 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
m_data->m_view->SetPenSize(thickness);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -532,7 +532,7 @@ void GraphicsContext::clearPlatformShadow()
notImplemented();
}
-void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&)
+void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&, ColorSpace)
{
notImplemented();
}
diff --git a/WebCore/platform/graphics/haiku/IconHaiku.cpp b/WebCore/platform/graphics/haiku/IconHaiku.cpp
index dccac4a..3663ee2 100644
--- a/WebCore/platform/graphics/haiku/IconHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/IconHaiku.cpp
@@ -36,12 +36,6 @@ Icon::~Icon()
notImplemented();
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
-{
- notImplemented();
- return 0;
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
notImplemented();
diff --git a/WebCore/platform/graphics/haiku/ImageHaiku.cpp b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
index 323d6ab..df08822 100644
--- a/WebCore/platform/graphics/haiku/ImageHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
@@ -83,7 +83,7 @@ void BitmapImage::invalidatePlatformData()
}
// Drawing Routines
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
startAnimation();
@@ -92,7 +92,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dst, solidColor(), op);
+ fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
return;
}
@@ -109,7 +109,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
ctxt->restore();
}
-void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& srcPoint, CompositeOperator op, const FloatRect& dstRect)
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& srcPoint, ColorSpace, CompositeOperator op, const FloatRect& dstRect)
{
// FIXME: finish this to support also phased position (srcPoint)
startAnimation();
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp
index b2682e4..265b2c3 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,30 +10,24 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
-#include "CoreTextController.h"
-
-#if USE(CORE_TEXT)
+#include "ComplexTextController.h"
#include "CharacterNames.h"
#include "Font.h"
-#include "FontCache.h"
-#include "SimpleFontData.h"
#include "TextBreakIterator.h"
-#include <wtf/MathExtras.h>
using namespace std;
@@ -53,54 +47,7 @@ static inline CGFloat ceilCGFloat(CGFloat f)
return static_cast<CGFloat>(ceil(f));
}
-CoreTextController::CoreTextRun::CoreTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
- : m_CTRun(ctRun)
- , m_fontData(fontData)
- , m_characters(characters)
- , m_stringLocation(stringLocation)
- , m_stringLength(stringLength)
-{
- m_glyphCount = CTRunGetGlyphCount(ctRun);
- m_indices = CTRunGetStringIndicesPtr(ctRun);
- if (!m_indices) {
- m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
- CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex));
- m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get()));
- CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices));
- }
-}
-
-// Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
-// glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path.
-CoreTextController::CoreTextRun::CoreTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
- : m_fontData(fontData)
- , m_characters(characters)
- , m_stringLocation(stringLocation)
- , m_stringLength(stringLength)
-{
- Vector<CFIndex, 16> indices;
- unsigned r = 0;
- while (r < stringLength) {
- indices.append(r);
- if (U_IS_SURROGATE(characters[r])) {
- ASSERT(r + 1 < stringLength);
- ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
- ASSERT(U_IS_TRAIL(characters[r + 1]));
- r += 2;
- } else
- r++;
- }
- m_glyphCount = indices.size();
- if (!ltr) {
- for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
- std::swap(indices[r], indices[end]);
- }
- m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
- CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex));
- m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
-}
-
-CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
+ComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
: m_font(*font)
, m_run(run)
, m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
@@ -111,6 +58,7 @@ CoreTextController::CoreTextController(const Font* font, const TextRun& run, boo
, m_numGlyphsSoFar(0)
, m_currentRun(0)
, m_glyphInCurrentRun(0)
+ , m_characterInCurrentGlyph(0)
, m_finalRoundingWidth(0)
, m_fallbackFonts(fallbackFonts)
, m_lastRoundingGlyph(0)
@@ -130,16 +78,12 @@ CoreTextController::CoreTextController(const Font* font, const TextRun& run, boo
m_padPerSpace = ceilf(m_run.padding() / numSpaces);
}
- collectCoreTextRuns();
+ collectComplexTextRuns();
adjustGlyphsAndAdvances();
}
-int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
+int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
{
- // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
- // approximate it by dividing the width of the ligature by the number of characters it encompasses.
- // However, Core Text does not expose a low-level API for directly finding
- // out how many characters a ligature encompasses (the "attachment count").
if (h >= m_totalWidth)
return m_run.ltr() ? m_end : 0;
if (h < 0)
@@ -147,17 +91,27 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
CGFloat x = h;
- size_t runCount = m_coreTextRuns.size();
+ size_t runCount = m_complexTextRuns.size();
size_t offsetIntoAdjustedGlyphs = 0;
for (size_t r = 0; r < runCount; ++r) {
- const CoreTextRun& coreTextRun = m_coreTextRuns[r];
- for (unsigned j = 0; j < coreTextRun.glyphCount(); ++j) {
+ const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
+ for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
- if (x <= adjustedAdvance) {
- CFIndex hitIndex = coreTextRun.indexAt(j);
- int stringLength = coreTextRun.stringLength();
- TextBreakIterator* cursorPositionIterator = cursorMovementIterator(coreTextRun.characters(), stringLength);
+ if (x < adjustedAdvance) {
+ CFIndex hitGlyphStart = complexTextRun.indexAt(j);
+ CFIndex hitGlyphEnd;
+ if (m_run.ltr())
+ hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : complexTextRun.stringLength());
+ else
+ hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.stringLength());
+
+ // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+ // could use the glyph's "ligature carets". However, there is no Core Text API to get the
+ // ligature carets.
+ CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
+ int stringLength = complexTextRun.stringLength();
+ TextBreakIterator* cursorPositionIterator = cursorMovementIterator(complexTextRun.characters(), stringLength);
int clusterStart;
if (isTextBreak(cursorPositionIterator, hitIndex))
clusterStart = hitIndex;
@@ -168,45 +122,49 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
}
if (!includePartialGlyphs)
- return coreTextRun.stringLocation() + clusterStart;
+ return complexTextRun.stringLocation() + clusterStart;
int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
if (clusterEnd == TextBreakDone)
clusterEnd = stringLength;
- CGFloat clusterWidth = adjustedAdvance;
- // FIXME: The search stops at the boundaries of coreTextRun. In theory, it should go on into neighboring CoreTextRuns
+ CGFloat clusterWidth;
+ // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
// derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
// reordering and on font fallback should occur within a CTLine.
if (clusterEnd - clusterStart > 1) {
+ clusterWidth = adjustedAdvance;
int firstGlyphBeforeCluster = j - 1;
- while (firstGlyphBeforeCluster >= 0 && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
+ while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
clusterWidth += width;
x += width;
firstGlyphBeforeCluster--;
}
unsigned firstGlyphAfterCluster = j + 1;
- while (firstGlyphAfterCluster < coreTextRun.glyphCount() && coreTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
+ while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
firstGlyphAfterCluster++;
}
+ } else {
+ clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart);
+ x -= clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1);
}
if (x <= clusterWidth / 2)
- return coreTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
+ return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
else
- return coreTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
+ return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
}
x -= adjustedAdvance;
}
- offsetIntoAdjustedGlyphs += coreTextRun.glyphCount();
+ offsetIntoAdjustedGlyphs += complexTextRun.glyphCount();
}
ASSERT_NOT_REACHED();
return 0;
}
-void CoreTextController::collectCoreTextRuns()
+void ComplexTextController::collectComplexTextRuns()
{
if (!m_end)
return;
@@ -227,7 +185,7 @@ void CoreTextController::collectCoreTextRuns()
static const UChar hyphen = '-';
if (hasTrailingSoftHyphen && m_run.rtl()) {
- collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
+ collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
indexOfFontTransition--;
curr--;
}
@@ -290,7 +248,7 @@ void CoreTextController::collectCoreTextRuns()
if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) {
int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;
int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
- collectCoreTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);
+ collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);
indexOfFontTransition = index;
}
}
@@ -298,19 +256,15 @@ void CoreTextController::collectCoreTextRuns()
int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition - (hasTrailingSoftHyphen ? 1 : 0);
if (itemLength) {
int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
- collectCoreTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);
+ collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);
}
if (hasTrailingSoftHyphen && m_run.ltr())
- collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
+ collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
}
-void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
+void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
{
- // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"
- // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional
- // to the offsets into the ligature. However, Core Text does not expose a low-level API for
- // directly finding out how many characters a ligature encompasses (the "attachment count").
if (static_cast<int>(offset) > m_end)
offset = m_end;
@@ -319,24 +273,44 @@ void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
m_currentCharacter = offset;
- size_t runCount = m_coreTextRuns.size();
+ size_t runCount = m_complexTextRuns.size();
bool ltr = m_run.ltr();
unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar;
while (m_currentRun < runCount) {
- const CoreTextRun& coreTextRun = m_coreTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];
- size_t glyphCount = coreTextRun.glyphCount();
+ const ComplexTextRun& complexTextRun = *m_complexTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];
+ size_t glyphCount = complexTextRun.glyphCount();
unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
while (m_glyphInCurrentRun < glyphCount) {
- if (coreTextRun.indexAt(g) + coreTextRun.stringLocation() >= m_currentCharacter)
- return;
+ unsigned glyphStartOffset = complexTextRun.indexAt(g);
+ unsigned glyphEndOffset;
+ if (ltr)
+ glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength());
+ else
+ glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength());
+
CGSize adjustedAdvance = m_adjustedAdvances[k];
- if (glyphBuffer)
- glyphBuffer->add(m_adjustedGlyphs[k], coreTextRun.fontData(), adjustedAdvance);
- m_runWidthSoFar += adjustedAdvance.width;
+
+ if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
+ return;
+
+ if (glyphBuffer && !m_characterInCurrentGlyph)
+ glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
+
+ unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
+ m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
+ // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+ // could use the glyph's "ligature carets". However, there is no Core Text API to get the
+ // ligature carets.
+ m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
+
+ if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
+ return;
+
m_numGlyphsSoFar++;
m_glyphInCurrentRun++;
+ m_characterInCurrentGlyph = 0;
if (ltr) {
g++;
k++;
@@ -352,100 +326,35 @@ void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
m_runWidthSoFar += m_finalRoundingWidth;
}
-void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
-{
- if (!fontData) {
- // Create a run of missing glyphs from the primary font.
- m_coreTextRuns.append(CoreTextRun(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
- return;
- }
-
- if (m_fallbackFonts && fontData != m_font.primaryFont())
- m_fallbackFonts->add(fontData);
-
- RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
-
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
-
- RetainPtr<CTTypesetterRef> typesetter;
-
- if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
- static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
- static const void* ltrOptionValues[] = { kCFBooleanFalse };
- static const void* rtlOptionValues[] = { kCFBooleanTrue };
- static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
- } else
- typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get()));
-
- RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
-
- CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
-
- CFIndex runCount = CFArrayGetCount(runArray);
-
- for (CFIndex r = 0; r < runCount; r++) {
- CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
- ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
- m_coreTextRuns.append(CoreTextRun(ctRun, fontData, cp, stringLocation, length));
- }
-}
-
-void CoreTextController::adjustGlyphsAndAdvances()
+void ComplexTextController::adjustGlyphsAndAdvances()
{
- size_t runCount = m_coreTextRuns.size();
+ size_t runCount = m_complexTextRuns.size();
for (size_t r = 0; r < runCount; ++r) {
- const CoreTextRun& coreTextRun = m_coreTextRuns[r];
- unsigned glyphCount = coreTextRun.glyphCount();
- const SimpleFontData* fontData = coreTextRun.fontData();
-
- Vector<CGGlyph, 256> glyphsVector;
- const CGGlyph* glyphs;
-
- Vector<CGSize, 256> advancesVector;
- const CGSize* advances;
-
- if (coreTextRun.ctRun()) {
- glyphs = CTRunGetGlyphsPtr(coreTextRun.ctRun());
- if (!glyphs) {
- glyphsVector.grow(glyphCount);
- CTRunGetGlyphs(coreTextRun.ctRun(), CFRangeMake(0, 0), glyphsVector.data());
- glyphs = glyphsVector.data();
- }
+ const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
+ unsigned glyphCount = complexTextRun.glyphCount();
+ const SimpleFontData* fontData = complexTextRun.fontData();
- advances = CTRunGetAdvancesPtr(coreTextRun.ctRun());
- if (!advances) {
- advancesVector.grow(glyphCount);
- CTRunGetAdvances(coreTextRun.ctRun(), CFRangeMake(0, 0), advancesVector.data());
- advances = advancesVector.data();
- }
- } else {
- // Synthesize a run of missing glyphs.
- glyphsVector.fill(0, glyphCount);
- glyphs = glyphsVector.data();
- advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), glyphCount);
- advances = advancesVector.data();
- }
+ const CGGlyph* glyphs = complexTextRun.glyphs();
+ const CGSize* advances = complexTextRun.advances();
bool lastRun = r + 1 == runCount;
- const UChar* cp = coreTextRun.characters();
+ const UChar* cp = complexTextRun.characters();
CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
for (unsigned i = 0; i < glyphCount; i++) {
- CFIndex characterIndex = coreTextRun.indexAt(i);
+ CFIndex characterIndex = complexTextRun.indexAt(i);
UChar ch = *(cp + characterIndex);
bool lastGlyph = lastRun && i + 1 == glyphCount;
UChar nextCh;
if (lastGlyph)
nextCh = ' ';
else if (i + 1 < glyphCount)
- nextCh = *(cp + coreTextRun.indexAt(i + 1));
+ nextCh = *(cp + complexTextRun.indexAt(i + 1));
else
- nextCh = *(m_coreTextRuns[r + 1].characters() + m_coreTextRuns[r + 1].indexAt(0));
+ nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0));
bool treatAsSpace = Font::treatAsSpace(ch);
CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
@@ -533,5 +442,3 @@ void CoreTextController::adjustGlyphsAndAdvances()
}
} // namespace WebCore
-
-#endif // USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h
new file mode 100644
index 0000000..7a915e2
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ComplexTextController_h
+#define ComplexTextController_h
+
+#include "GlyphBuffer.h"
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class Font;
+class SimpleFontData;
+class TextRun;
+
+class ComplexTextController {
+public:
+ ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
+
+ // Advance and emit glyphs up to the specified character.
+ void advance(unsigned to, GlyphBuffer* = 0);
+
+ // Compute the character offset for a given x coordinate.
+ int offsetForPosition(int x, bool includePartialGlyphs);
+
+ // Returns the width of everything we've consumed so far.
+ float runWidthSoFar() const { return m_runWidthSoFar; }
+
+ float totalWidth() const { return m_totalWidth; }
+
+ // Extra width to the left of the leftmost glyph.
+ float finalRoundingWidth() const { return m_finalRoundingWidth; }
+
+private:
+ class ComplexTextRun : public RefCounted<ComplexTextRun> {
+ public:
+#if USE(CORE_TEXT)
+ static PassRefPtr<ComplexTextRun> create(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+ {
+ return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength));
+ }
+#elif USE(ATSUI)
+ static PassRefPtr<ComplexTextRun> create(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
+ {
+ return adoptRef(new ComplexTextRun(atsuTextLayout, fontData, characters, stringLocation, stringLength, ltr, directionalOverride));
+ }
+#endif
+ static PassRefPtr<ComplexTextRun> create(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+ {
+ return adoptRef(new ComplexTextRun(fontData, characters, stringLocation, stringLength, ltr));
+ }
+
+ unsigned glyphCount() const { return m_glyphCount; }
+ const SimpleFontData* fontData() const { return m_fontData; }
+ const UChar* characters() const { return m_characters; }
+ unsigned stringLocation() const { return m_stringLocation; }
+ size_t stringLength() const { return m_stringLength; }
+ CFIndex indexAt(size_t i) const { return m_indices[i]; }
+ const CGGlyph* glyphs() const { return m_glyphs; }
+ const CGSize* advances() const { return m_advances; }
+
+ private:
+#if USE(CORE_TEXT)
+ ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
+#elif USE(ATSUI)
+ ComplexTextRun(ATSUTextLayout, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride);
+#endif
+ ComplexTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
+
+#if USE(ATSUI)
+#ifdef BUILDING_ON_TIGER
+ typedef UInt32 URefCon;
+#endif
+ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef, URefCon, void*, ATSULayoutOperationCallbackStatus*);
+#endif
+
+#if USE(CORE_TEXT)
+ RetainPtr<CTRunRef> m_CTRun;
+#endif
+ unsigned m_glyphCount;
+ const SimpleFontData* m_fontData;
+ const UChar* m_characters;
+ unsigned m_stringLocation;
+ size_t m_stringLength;
+#if USE(CORE_TEXT)
+ RetainPtr<CFMutableDataRef> m_indicesData;
+ const CFIndex* m_indices;
+#elif USE(ATSUI)
+ Vector<CFIndex, 64> m_indices;
+#endif
+ Vector<CGGlyph, 64> m_glyphsVector;
+ const CGGlyph* m_glyphs;
+ Vector<CGSize, 64> m_advancesVector;
+ const CGSize* m_advances;
+#if USE(ATSUI)
+ bool m_ltr;
+ bool m_directionalOverride;
+#endif
+ };
+
+ void collectComplexTextRuns();
+ void collectComplexTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
+ void adjustGlyphsAndAdvances();
+
+ const Font& m_font;
+ const TextRun& m_run;
+ bool m_mayUseNaturalWritingDirection;
+
+ Vector<UChar, 256> m_smallCapsBuffer;
+
+ Vector<RefPtr<ComplexTextRun>, 16> m_complexTextRuns;
+ Vector<CGSize, 256> m_adjustedAdvances;
+ Vector<CGGlyph, 256> m_adjustedGlyphs;
+
+ unsigned m_currentCharacter;
+ int m_end;
+
+ CGFloat m_totalWidth;
+
+ float m_runWidthSoFar;
+ unsigned m_numGlyphsSoFar;
+ size_t m_currentRun;
+ unsigned m_glyphInCurrentRun;
+ unsigned m_characterInCurrentGlyph;
+ float m_finalRoundingWidth;
+ float m_padding;
+ float m_padPerSpace;
+
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
+
+ unsigned m_lastRoundingGlyph;
+};
+
+} // namespace WebCore
+
+#endif // ComplexTextController_h
diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
new file mode 100644
index 0000000..78c588f
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple 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.
+ */
+
+#include "config.h"
+#include "ComplexTextController.h"
+
+#if USE(ATSUI)
+
+#include "CharacterNames.h"
+#include "Font.h"
+#include "ShapeArabic.h"
+
+#ifdef __LP64__
+// ATSUTextInserted() is SPI in 64-bit.
+extern "C" {
+OSStatus ATSUTextInserted(ATSUTextLayout iTextLayout, UniCharArrayOffset iInsertionLocation, UniCharCount iInsertionLength);
+}
+#endif
+
+using namespace WTF::Unicode;
+
+namespace WebCore {
+
+OSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef atsuLineRef, URefCon refCon, void*, ATSULayoutOperationCallbackStatus* callbackStatus)
+{
+ ComplexTextRun* complexTextRun = reinterpret_cast<ComplexTextRun*>(refCon);
+ OSStatus status;
+ ItemCount count;
+ ATSLayoutRecord *layoutRecords;
+
+ status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, reinterpret_cast<void**>(&layoutRecords), &count);
+ if (status != noErr) {
+ *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
+ return status;
+ }
+
+ count--;
+ ItemCount j = 0;
+ CFIndex indexOffset = 0;
+
+ if (complexTextRun->m_directionalOverride) {
+ j++;
+ count -= 2;
+ indexOffset = -1;
+ }
+
+ complexTextRun->m_glyphCount = count;
+ complexTextRun->m_glyphsVector.reserveCapacity(count);
+ complexTextRun->m_advancesVector.reserveCapacity(count);
+ complexTextRun->m_indices.reserveCapacity(count);
+
+ bool atBeginning = true;
+ CGFloat lastX = 0;
+
+ for (ItemCount i = 0; i < count; ++i, ++j) {
+ if (layoutRecords[j].glyphID == kATSDeletedGlyphcode) {
+ complexTextRun->m_glyphCount--;
+ continue;
+ }
+ complexTextRun->m_glyphsVector.uncheckedAppend(layoutRecords[j].glyphID);
+ complexTextRun->m_indices.uncheckedAppend(layoutRecords[j].originalOffset / 2 + indexOffset);
+ CGFloat x = FixedToFloat(layoutRecords[j].realPos);
+ if (!atBeginning)
+ complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(x - lastX, 0));
+ lastX = x;
+ atBeginning = false;
+ }
+
+ complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(FixedToFloat(layoutRecords[j].realPos) - lastX, 0));
+
+ complexTextRun->m_glyphs = complexTextRun->m_glyphsVector.data();
+ complexTextRun->m_advances = complexTextRun->m_advancesVector.data();
+
+ status = ATSUDirectReleaseLayoutDataArrayPtr(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, reinterpret_cast<void**>(&layoutRecords));
+ *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
+ return noErr;
+}
+
+static inline bool isArabicLamWithAlefLigature(UChar c)
+{
+ return c >= 0xfef5 && c <= 0xfefc;
+}
+
+static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength)
+{
+ unsigned shapingStart = 0;
+ while (shapingStart < totalLength) {
+ unsigned shapingEnd;
+ // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
+ // since we want to be able to identify this sequence as the result of shaping a Lam
+ // followed by an Alef and padding with a space.
+ bool foundLigatureSpace = false;
+ for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
+ foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
+ shapingEnd++;
+
+ UErrorCode shapingError = U_ZERO_ERROR;
+ unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
+
+ if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
+ for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
+ if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
+ dest[++j] = zeroWidthSpace;
+ }
+ if (foundLigatureSpace) {
+ dest[shapingEnd] = ' ';
+ shapingEnd++;
+ } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
+ // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
+ // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
+ ASSERT(dest[shapingStart] == ' ');
+ dest[shapingStart] = zeroWidthSpace;
+ }
+ } else {
+ // Something went wrong. Abandon shaping and just copy the rest of the buffer.
+ LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
+ shapingEnd = totalLength;
+ memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
+ }
+ shapingStart = shapingEnd;
+ }
+}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
+ : m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+ , m_ltr(ltr)
+ , m_directionalOverride(directionalOverride)
+{
+ OSStatus status;
+
+ status = ATSUSetTextLayoutRefCon(atsuTextLayout, reinterpret_cast<URefCon>(this));
+
+ ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
+
+ Boolean rtl = !ltr;
+
+ Vector<UChar, 256> substituteCharacters;
+ bool shouldCheckForMirroring = !ltr && !fontData->m_ATSUMirrors;
+ bool shouldCheckForArabic = !fontData->shapesArabic();
+ bool shouldShapeArabic = false;
+
+ bool mirrored = false;
+ for (size_t i = 0; i < stringLength; ++i) {
+ if (shouldCheckForMirroring) {
+ UChar mirroredChar = u_charMirror(characters[i]);
+ if (mirroredChar != characters[i]) {
+ if (!mirrored) {
+ mirrored = true;
+ substituteCharacters.grow(stringLength);
+ memcpy(substituteCharacters.data(), characters, stringLength * sizeof(UChar));
+ ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+ }
+ substituteCharacters[i] = mirroredChar;
+ }
+ }
+ if (shouldCheckForArabic && isArabicChar(characters[i])) {
+ shouldCheckForArabic = false;
+ shouldShapeArabic = true;
+ }
+ }
+
+ if (shouldShapeArabic) {
+ Vector<UChar, 256> shapedArabic(stringLength);
+ shapeArabic(substituteCharacters.isEmpty() ? characters : substituteCharacters.data(), shapedArabic.data(), stringLength);
+ substituteCharacters.swap(shapedArabic);
+ ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+ }
+
+ if (directionalOverride) {
+ UChar override = ltr ? leftToRightOverride : rightToLeftOverride;
+ if (substituteCharacters.isEmpty()) {
+ substituteCharacters.grow(stringLength + 2);
+ substituteCharacters[0] = override;
+ memcpy(substituteCharacters.data() + 1, characters, stringLength * sizeof(UChar));
+ substituteCharacters[stringLength + 1] = popDirectionalFormatting;
+ ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+ } else {
+ substituteCharacters.prepend(override);
+ substituteCharacters.append(popDirectionalFormatting);
+ }
+ ATSUTextInserted(atsuTextLayout, 0, 2);
+ }
+
+ ATSULayoutOperationOverrideSpecifier overrideSpecifier;
+ overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
+ overrideSpecifier.overrideUPP = overrideLayoutOperation;
+
+ ATSUAttributeTag tags[] = { kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
+ ByteCount sizes[] = { sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
+ ATSUAttributeValuePtr values[] = { &lineLayoutOptions, &rtl, &overrideSpecifier };
+
+ status = ATSUSetLayoutControls(atsuTextLayout, 3, tags, sizes, values);
+
+ ItemCount boundsCount;
+ status = ATSUGetGlyphBounds(atsuTextLayout, 0, 0, 0, m_stringLength, kATSUseFractionalOrigins, 0, 0, &boundsCount);
+
+ status = ATSUDisposeTextLayout(atsuTextLayout);
+}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+ : m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+{
+ m_indices.reserveCapacity(stringLength);
+ unsigned r = 0;
+ while (r < stringLength) {
+ m_indices.uncheckedAppend(r);
+ if (U_IS_SURROGATE(characters[r])) {
+ ASSERT(r + 1 < stringLength);
+ ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
+ ASSERT(U_IS_TRAIL(characters[r + 1]));
+ r += 2;
+ } else
+ r++;
+ }
+ m_glyphCount = m_indices.size();
+ if (!ltr) {
+ for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
+ std::swap(m_indices[r], m_indices[end]);
+ }
+
+ m_glyphsVector.fill(0, m_glyphCount);
+ m_glyphs = m_glyphsVector.data();
+ m_advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), m_glyphCount);
+ m_advances = m_advancesVector.data();
+}
+
+static bool fontHasMirroringInfo(ATSUFontID fontID)
+{
+ ByteCount propTableSize;
+ OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
+ if (status == noErr) // naively assume that if a 'prop' table exists then it contains mirroring info
+ return true;
+ else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
+ LOG_ERROR("ATSFontGetTable failed (%d)", static_cast<int>(status));
+
+ return false;
+}
+
+static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode)
+{
+ // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
+ // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
+ // See bugzilla 5166.
+ if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
+ return;
+
+ ATSUFontFeatureType featureTypes[] = { kLigaturesType };
+ ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
+ OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", static_cast<int>(status));
+}
+
+static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
+{
+ if (fontData->m_ATSUStyleInitialized)
+ return;
+
+ ATSUFontID fontID = fontData->platformData().m_atsuFontID;
+ if (!fontID) {
+ LOG_ERROR("unable to get ATSUFontID for %p", fontData->platformData().font());
+ return;
+ }
+
+ OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle);
+ if (status != noErr)
+ LOG_ERROR("ATSUCreateStyle failed (%d)", static_cast<int>(status));
+
+ Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
+ Fract kerningInhibitFactor = FloatToFract(1);
+ static CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1, -1);
+
+ ByteCount styleSizes[4] = { sizeof(fontSize), sizeof(fontID), sizeof(verticalFlip), sizeof(kerningInhibitFactor) };
+ ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
+ ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &verticalFlip, &kerningInhibitFactor };
+
+ bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+ status = ATSUSetAttributes(fontData->m_ATSUStyle, allowKerning ? 3 : 4, styleTags, styleSizes, styleValues);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetAttributes failed (%d)", static_cast<int>(status));
+
+ fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
+
+ disableLigatures(fontData, textMode);
+
+ fontData->m_ATSUStyleInitialized = true;
+}
+
+void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
+{
+ if (!fontData) {
+ // Create a run of missing glyphs from the primary font.
+ m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
+ return;
+ }
+
+ if (m_fallbackFonts && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
+ initializeATSUStyle(fontData, m_font.fontDescription().textRenderingMode());
+
+ OSStatus status;
+ ATSUTextLayout atsuTextLayout;
+ UniCharCount runLength = length;
+
+ status = ATSUCreateTextLayoutWithTextPtr(cp, 0, length, length, 1, &runLength, &fontData->m_ATSUStyle, &atsuTextLayout);
+ if (status != noErr) {
+ LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed with error %d", static_cast<int>(status));
+ return;
+ }
+ m_complexTextRuns.append(ComplexTextRun::create(atsuTextLayout, fontData, cp, stringLocation, length, m_run.ltr(), m_run.directionalOverride()));
+}
+
+} // namespace WebCore
+
+#endif // USE(ATSUI)
diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
new file mode 100644
index 0000000..c9daf84
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ComplexTextController.h"
+
+#if USE(CORE_TEXT)
+
+#include "Font.h"
+
+namespace WebCore {
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+ : m_CTRun(ctRun)
+ , m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+{
+ m_glyphCount = CTRunGetGlyphCount(m_CTRun.get());
+ m_indices = CTRunGetStringIndicesPtr(m_CTRun.get());
+ if (!m_indices) {
+ m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
+ CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex));
+ m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get()));
+ CTRunGetStringIndices(m_CTRun.get(), CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices));
+ }
+
+ m_glyphs = CTRunGetGlyphsPtr(m_CTRun.get());
+ if (!m_glyphs) {
+ m_glyphsVector.grow(m_glyphCount);
+ CTRunGetGlyphs(m_CTRun.get(), CFRangeMake(0, 0), m_glyphsVector.data());
+ m_glyphs = m_glyphsVector.data();
+ }
+
+ m_advances = CTRunGetAdvancesPtr(m_CTRun.get());
+ if (!m_advances) {
+ m_advancesVector.grow(m_glyphCount);
+ CTRunGetAdvances(m_CTRun.get(), CFRangeMake(0, 0), m_advancesVector.data());
+ m_advances = m_advancesVector.data();
+ }
+
+}
+
+// Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
+// glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path.
+ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+ : m_fontData(fontData)
+ , m_characters(characters)
+ , m_stringLocation(stringLocation)
+ , m_stringLength(stringLength)
+{
+ Vector<CFIndex, 16> indices;
+ unsigned r = 0;
+ while (r < stringLength) {
+ indices.append(r);
+ if (U_IS_SURROGATE(characters[r])) {
+ ASSERT(r + 1 < stringLength);
+ ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
+ ASSERT(U_IS_TRAIL(characters[r + 1]));
+ r += 2;
+ } else
+ r++;
+ }
+ m_glyphCount = indices.size();
+ if (!ltr) {
+ for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
+ std::swap(indices[r], indices[end]);
+ }
+ m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
+ CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex));
+ m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
+
+ // Synthesize a run of missing glyphs.
+ m_glyphsVector.fill(0, m_glyphCount);
+ m_glyphs = m_glyphsVector.data();
+ m_advancesVector.fill(CGSizeMake(m_fontData->widthForGlyph(0), 0), m_glyphCount);
+ m_advances = m_advancesVector.data();
+}
+
+void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
+{
+ if (!fontData) {
+ // Create a run of missing glyphs from the primary font.
+ m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
+ return;
+ }
+
+ if (m_fallbackFonts && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
+ RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
+
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
+
+ RetainPtr<CTTypesetterRef> typesetter;
+
+ if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
+ static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
+ static const void* ltrOptionValues[] = { kCFBooleanFalse };
+ static const void* rtlOptionValues[] = { kCFBooleanTrue };
+ static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
+ } else
+ typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get()));
+
+ RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
+
+ CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
+
+ CFIndex runCount = CFArrayGetCount(runArray);
+
+ for (CFIndex r = 0; r < runCount; r++) {
+ CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
+ ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
+ m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length));
+ }
+}
+
+} // namespace WebCore
+
+#endif // USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.h b/WebCore/platform/graphics/mac/CoreTextController.h
deleted file mode 100644
index 4dd6f93..0000000
--- a/WebCore/platform/graphics/mac/CoreTextController.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CoreTextController_h
-#define CoreTextController_h
-
-#if USE(CORE_TEXT)
-
-#include "Font.h"
-#include "GlyphBuffer.h"
-#include <wtf/RetainPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class CoreTextController {
-public:
- CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
-
- // Advance and emit glyphs up to the specified character.
- void advance(unsigned to, GlyphBuffer* = 0);
-
- // Compute the character offset for a given x coordinate.
- int offsetForPosition(int x, bool includePartialGlyphs);
-
- // Returns the width of everything we've consumed so far.
- float runWidthSoFar() const { return m_runWidthSoFar; }
-
- float totalWidth() const { return m_totalWidth; }
-
- // Extra width to the left of the leftmost glyph.
- float finalRoundingWidth() const { return m_finalRoundingWidth; }
-
-private:
- class CoreTextRun {
- public:
- CoreTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
- CoreTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
-
- CTRunRef ctRun() const { return m_CTRun.get(); }
- unsigned glyphCount() const { return m_glyphCount; }
- const SimpleFontData* fontData() const { return m_fontData; }
- const UChar* characters() const { return m_characters; }
- unsigned stringLocation() const { return m_stringLocation; }
- size_t stringLength() const { return m_stringLength; }
- CFIndex indexAt(size_t i) const { return m_indices[i]; }
-
- private:
- RetainPtr<CTRunRef> m_CTRun;
- unsigned m_glyphCount;
- const SimpleFontData* m_fontData;
- const UChar* m_characters;
- unsigned m_stringLocation;
- size_t m_stringLength;
- const CFIndex* m_indices;
- // Used only if CTRunGet*Ptr fails or if this is a missing glyphs run.
- RetainPtr<CFMutableDataRef> m_indicesData;
- };
-
- void collectCoreTextRuns();
- void collectCoreTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
- void adjustGlyphsAndAdvances();
-
- const Font& m_font;
- const TextRun& m_run;
- bool m_mayUseNaturalWritingDirection;
-
- Vector<UChar, 256> m_smallCapsBuffer;
-
- Vector<CoreTextRun, 16> m_coreTextRuns;
- Vector<CGSize, 256> m_adjustedAdvances;
- Vector<CGGlyph, 256> m_adjustedGlyphs;
-
- unsigned m_currentCharacter;
- int m_end;
-
- CGFloat m_totalWidth;
-
- float m_runWidthSoFar;
- unsigned m_numGlyphsSoFar;
- size_t m_currentRun;
- unsigned m_glyphInCurrentRun;
- float m_finalRoundingWidth;
- float m_padding;
- float m_padPerSpace;
-
- HashSet<const SimpleFontData*>* m_fallbackFonts;
-
- unsigned m_lastRoundingGlyph;
-};
-
-} // namespace WebCore
-#endif // USE(CORE_TEXT)
-#endif // CoreTextController_h
diff --git a/WebCore/platform/graphics/mac/FontMacCoreText.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
index 9dffc7a..0db2601 100644
--- a/WebCore/platform/graphics/mac/FontMacCoreText.cpp
+++ b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,25 +10,22 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "Font.h"
-#if USE(CORE_TEXT)
-
-#include "CoreTextController.h"
+#include "ComplexTextController.h"
#include "FontFallbackList.h"
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
@@ -41,7 +38,7 @@ namespace WebCore {
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
int from, int to) const
{
- CoreTextController controller(this, run);
+ ComplexTextController controller(this, run);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to);
@@ -63,7 +60,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
GlyphBuffer glyphBuffer;
float startX = point.x();
- CoreTextController controller(this, run);
+ ComplexTextController controller(this, run);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to, &glyphBuffer);
@@ -88,15 +85,14 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- CoreTextController controller(this, run, true, fallbackFonts);
+ ComplexTextController controller(this, run, true, fallbackFonts);
return controller.totalWidth();
}
int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
{
- CoreTextController controller(this, run);
+ ComplexTextController controller(this, run);
return controller.offsetForPosition(x, includePartialGlyphs);
}
-}
-#endif // USE(CORE_TEXT)
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index 5e72101..256b5a4 100644
--- a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -24,6 +24,7 @@
#include <ApplicationServices/ApplicationServices.h>
#include "SharedBuffer.h"
#include "FontPlatformData.h"
+#include "OpenTypeSanitizer.h"
namespace WebCore {
@@ -43,6 +44,14 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
+#if ENABLE(OPENTYPE_SANITIZER)
+ OpenTypeSanitizer sanitizer(buffer);
+ RefPtr<SharedBuffer> transcodeBuffer = sanitizer.sanitize();
+ if (!transcodeBuffer)
+ return 0; // validation failed.
+ buffer = transcodeBuffer.get();
+#endif
+
ATSFontContainerRef containerRef = 0;
ATSFontRef fontRef = 0;
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index b2b9a5c..bb9561e 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -115,6 +115,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
+ ColorSpace fillColorSpace = context->fillColorSpace();
context->getShadow(shadowSize, shadowBlur, shadowColor);
bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
@@ -123,14 +124,14 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
context->clearShadow();
Color fillColor = context->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- context->setFillColor(shadowFillColor);
+ context->setFillColor(shadowFillColor, fillColorSpace);
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
- context->setFillColor(fillColor);
+ context->setFillColor(fillColor, fillColorSpace);
}
CGContextSetTextPosition(cgContext, point.x(), point.y());
@@ -141,7 +142,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
}
if (hasSimpleShadow)
- context->setShadow(shadowSize, shadowBlur, shadowColor);
+ context->setShadow(shadowSize, shadowBlur, shadowColor, fillColorSpace);
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
deleted file mode 100644
index 409bda4..0000000
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
- *
- * 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.
- */
-
-#import "config.h"
-#import "Font.h"
-
-#if USE(ATSUI)
-
-#import "CharacterNames.h"
-#import "GraphicsContext.h"
-#import "Logging.h"
-#import "ShapeArabic.h"
-#import "SimpleFontData.h"
-#import <AppKit/NSGraphicsContext.h>
-#import <wtf/OwnArrayPtr.h>
-
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
-#ifdef __LP64__
-#define URefCon void*
-#else
-#define URefCon UInt32
-#endif
-
-using namespace std;
-
-namespace WebCore {
-
-struct ATSULayoutParameters : Noncopyable
-{
- ATSULayoutParameters(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0)
- : m_run(run)
- , m_font(0)
- , m_hasSyntheticBold(false)
- , m_syntheticBoldPass(false)
- , m_padPerSpace(0)
- , m_fallbackFonts(fallbackFonts)
- {
- }
-
- ~ATSULayoutParameters()
- {
- ATSUDisposeTextLayout(m_layout);
- }
-
- void initialize(const Font*, const GraphicsContext* = 0);
-
- const TextRun& m_run;
-
- const Font* m_font;
-
- ATSUTextLayout m_layout;
- OwnArrayPtr<const SimpleFontData*> m_fonts;
-
- OwnArrayPtr<UChar> m_charBuffer;
- bool m_hasSyntheticBold;
- bool m_syntheticBoldPass;
- float m_padPerSpace;
- HashSet<const SimpleFontData*>* m_fallbackFonts;
-};
-
-static TextRun copyRunForDirectionalOverrideIfNecessary(const TextRun& run, OwnArrayPtr<UChar>& charactersWithOverride)
-{
- if (!run.directionalOverride())
- return run;
-
- charactersWithOverride.set(new UChar[run.length() + 2]);
- charactersWithOverride[0] = run.rtl() ? rightToLeftOverride : leftToRightOverride;
- memcpy(&charactersWithOverride[1], run.data(0), sizeof(UChar) * run.length());
- charactersWithOverride[run.length() + 1] = popDirectionalFormatting;
-
- TextRun result = run;
- result.setText(charactersWithOverride.get(), run.length() + 2);
- return result;
-}
-
-static bool fontHasMirroringInfo(ATSUFontID fontID)
-{
- ByteCount propTableSize;
- OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
- if (status == noErr) // naively assume that if a 'prop' table exists then it contains mirroring info
- return true;
- else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
- LOG_ERROR("ATSFontGetTable failed (%d)", status);
-
- return false;
-}
-
-static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode)
-{
- // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
- // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
- // See bugzilla 5166.
- if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
- return;
-
- ATSUFontFeatureType featureTypes[] = { kLigaturesType };
- ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
- OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
- if (status != noErr)
- LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", status);
-}
-
-static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
-{
- if (fontData->m_ATSUStyleInitialized)
- return;
-
- ATSUFontID fontID = fontData->platformData().m_atsuFontID;
- if (!fontID) {
- LOG_ERROR("unable to get ATSUFontID for %@", fontData->platformData().font());
- return;
- }
-
- OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle);
- if (status != noErr)
- // Who knows how many ATSU functions will crash when passed a NULL style...
- LOG_ERROR("ATSUCreateStyle failed (%d)", status);
-
- CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
- if (fontData->platformData().m_syntheticOblique)
- transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
- Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
- ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
-
- bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
- if (!allowKerning) {
- // Turn off automatic kerning until it is supported in the CG code path (bug 6136)
- Fract kerningInhibitFactor = FloatToFract(1.0);
- ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
- ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &transform, &kerningInhibitFactor };
- status = ATSUSetAttributes(fontData->m_ATSUStyle, 4, styleTags, styleSizes, styleValues);
- if (status != noErr)
- LOG_ERROR("ATSUSetAttributes failed (%d)", status);
- } else {
- ATSUAttributeTag styleTags[3] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag };
- ATSUAttributeValuePtr styleValues[3] = { &fontSize, &fontID, &transform, };
- status = ATSUSetAttributes(fontData->m_ATSUStyle, 3, styleTags, styleSizes, styleValues);
- if (status != noErr)
- LOG_ERROR("ATSUSetAttributes failed (%d)", status);
- }
-
- fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
-
- // Turn off ligatures such as 'fi' to match the CG code path's behavior, until bug 6135 is fixed.
- disableLigatures(fontData, textMode);
-
- fontData->m_ATSUStyleInitialized = true;
-}
-
-static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef iLineRef, URefCon iRefCon, void*, ATSULayoutOperationCallbackStatus* oCallbackStatus)
-{
- ATSULayoutParameters* params = reinterpret_cast<ATSULayoutParameters*>(iRefCon);
- OSStatus status;
- ItemCount count;
- ATSLayoutRecord *layoutRecords;
-
- if (params->m_run.applyWordRounding()) {
- status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, (void **)&layoutRecords, &count);
- if (status != noErr) {
- *oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
- return status;
- }
-
- Fixed lastNativePos = 0;
- float lastAdjustedPos = 0;
- const UChar* characters = params->m_charBuffer ? params->m_charBuffer.get() : params->m_run.characters();
- const SimpleFontData** renderers = params->m_fonts.get();
- const SimpleFontData* renderer;
- const SimpleFontData* lastRenderer = 0;
- ByteCount offset = layoutRecords[0].originalOffset;
- UChar nextCh = *(UChar *)(((char *)characters)+offset);
- bool shouldRound = false;
- bool syntheticBoldPass = params->m_syntheticBoldPass;
- Fixed syntheticBoldOffset = 0;
- bool hasExtraSpacing = (params->m_font->letterSpacing() || params->m_font->wordSpacing() || params->m_run.padding()) && !params->m_run.spacingDisabled();
- float padding = params->m_run.padding();
- // In the CoreGraphics code path, the rounding hack is applied in logical order.
- // Here it is applied in visual left-to-right order, which may be better.
- ItemCount lastRoundingChar = 0;
- ItemCount i;
- for (i = 1; i < count; i++) {
- bool isLastChar = i == count - 1;
- renderer = renderers[offset / 2];
- float width;
- if (nextCh == zeroWidthSpace || Font::treatAsZeroWidthSpace(nextCh) && !Font::treatAsSpace(nextCh)) {
- width = 0;
- layoutRecords[i-1].glyphID = renderer->spaceGlyph();
- } else {
- width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
- if (renderer != lastRenderer && width) {
- lastRenderer = renderer;
- // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
- // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
- // does in any of its device-metrics modes.
- shouldRound = renderer->platformData().roundsGlyphAdvances();
- if (syntheticBoldPass)
- syntheticBoldOffset = FloatToFixed(renderer->syntheticBoldOffset());
- if (params->m_fallbackFonts && renderer != params->m_font->primaryFont())
- params->m_fallbackFonts->add(renderer);
- }
- if (shouldRound)
- width = roundf(width);
- width += renderer->syntheticBoldOffset();
- if (renderer->pitch() == FixedPitch ? width == renderer->spaceWidth() : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
- width = renderer->adjustedSpaceWidth();
- }
- lastNativePos = layoutRecords[i].realPos;
-
- if (hasExtraSpacing) {
- if (width && params->m_font->letterSpacing())
- width +=params->m_font->letterSpacing();
- if (Font::treatAsSpace(nextCh)) {
- if (params->m_run.padding()) {
- if (padding < params->m_padPerSpace) {
- width += padding;
- padding = 0;
- } else {
- width += params->m_padPerSpace;
- padding -= params->m_padPerSpace;
- }
- }
- if (offset != 0 && !Font::treatAsSpace(*((UChar *)(((char *)characters)+offset) - 1)) && params->m_font->wordSpacing())
- width += params->m_font->wordSpacing();
- }
- }
-
- UChar ch = nextCh;
- offset = layoutRecords[i].originalOffset;
- // Use space for nextCh at the end of the loop so that we get inside the rounding hack code.
- // We won't actually round unless the other conditions are satisfied.
- nextCh = isLastChar ? ' ' : *(UChar *)(((char *)characters)+offset);
-
- if (Font::isRoundingHackCharacter(ch))
- width = ceilf(width);
- lastAdjustedPos = lastAdjustedPos + width;
- if (Font::isRoundingHackCharacter(nextCh) && (!isLastChar || params->m_run.applyRunRounding())){
- if (params->m_run.ltr())
- lastAdjustedPos = ceilf(lastAdjustedPos);
- else {
- float roundingWidth = ceilf(lastAdjustedPos) - lastAdjustedPos;
- Fixed rw = FloatToFixed(roundingWidth);
- ItemCount j;
- for (j = lastRoundingChar; j < i; j++)
- layoutRecords[j].realPos += rw;
- lastRoundingChar = i;
- lastAdjustedPos += roundingWidth;
- }
- }
- if (syntheticBoldPass) {
- if (syntheticBoldOffset)
- layoutRecords[i-1].realPos += syntheticBoldOffset;
- else
- layoutRecords[i-1].glyphID = renderer->spaceGlyph();
- }
- layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
- }
-
- status = ATSUDirectReleaseLayoutDataArrayPtr(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords);
- }
- *oCallbackStatus = kATSULayoutOperationCallbackStatusHandled;
- return noErr;
-}
-
-static inline bool isArabicLamWithAlefLigature(UChar c)
-{
- return c >= 0xfef5 && c <= 0xfefc;
-}
-
-static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength, unsigned shapingStart)
-{
- while (shapingStart < totalLength) {
- unsigned shapingEnd;
- // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
- // since we want to be able to identify this sequence as the result of shaping a Lam
- // followed by an Alef and padding with a space.
- bool foundLigatureSpace = false;
- for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
- foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
- shapingEnd++;
-
- UErrorCode shapingError = U_ZERO_ERROR;
- unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
-
- if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
- for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
- if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
- dest[++j] = zeroWidthSpace;
- }
- if (foundLigatureSpace) {
- dest[shapingEnd] = ' ';
- shapingEnd++;
- } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
- // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
- // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
- ASSERT(dest[shapingStart] == ' ');
- dest[shapingStart] = zeroWidthSpace;
- }
- } else {
- // Something went wrong. Abandon shaping and just copy the rest of the buffer.
- LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
- shapingEnd = totalLength;
- memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
- }
- shapingStart = shapingEnd;
- }
-}
-
-void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* graphicsContext)
-{
- m_font = font;
-
- const SimpleFontData* fontData = font->primaryFont();
- m_fonts.set(new const SimpleFontData*[m_run.length()]);
- if (font->isSmallCaps())
- m_charBuffer.set(new UChar[m_run.length()]);
-
- ATSUTextLayout layout;
- OSStatus status;
- ATSULayoutOperationOverrideSpecifier overrideSpecifier;
-
- initializeATSUStyle(fontData, m_font->fontDescription().textRenderingMode());
-
- // FIXME: This is currently missing the following required features that the CoreGraphics code path has:
- // - \n, \t, and nonbreaking space render as a space.
-
- UniCharCount runLength = m_run.length();
-
- if (m_charBuffer)
- memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));
-
- status = ATSUCreateTextLayoutWithTextPtr(
- (m_charBuffer ? m_charBuffer.get() : m_run.characters()),
- 0, // offset
- runLength, // length
- runLength, // total length
- 1, // styleRunCount
- &runLength, // length of style run
- &fontData->m_ATSUStyle,
- &layout);
- if (status != noErr)
- LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed(%d)", status);
- m_layout = layout;
- ATSUSetTextLayoutRefCon(m_layout, (URefCon)this);
-
- // FIXME: There are certain times when this method is called, when we don't have access to a GraphicsContext
- // measuring text runs with floatWidthForComplexText is one example.
- // ATSUI requires that we pass a valid CGContextRef to it when specifying kATSUCGContextTag (crashes when passed 0)
- // ATSUI disables sub-pixel rendering if kATSUCGContextTag is not specified! So we're in a bind.
- // Sometimes [[NSGraphicsContext currentContext] graphicsPort] may return the wrong (or no!) context. Nothing we can do about it (yet).
- CGContextRef cgContext = graphicsContext ? graphicsContext->platformContext() : (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-
- ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
- Boolean rtl = m_run.rtl();
- overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
- overrideSpecifier.overrideUPP = overrideLayoutOperation;
- ATSUAttributeTag tags[] = { kATSUCGContextTag, kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
- ByteCount sizes[] = { sizeof(CGContextRef), sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
- ATSUAttributeValuePtr values[] = { &cgContext, &lineLayoutOptions, &rtl, &overrideSpecifier };
-
- status = ATSUSetLayoutControls(layout, (m_run.applyWordRounding() ? 4 : 3), tags, sizes, values);
- if (status != noErr)
- LOG_ERROR("ATSUSetLayoutControls failed(%d)", status);
-
- status = ATSUSetTransientFontMatching(layout, YES);
- if (status != noErr)
- LOG_ERROR("ATSUSetTransientFontMatching failed(%d)", status);
-
- m_hasSyntheticBold = false;
- ATSUFontID ATSUSubstituteFont;
- UniCharArrayOffset substituteOffset = 0;
- UniCharCount substituteLength;
- UniCharArrayOffset lastOffset;
- const SimpleFontData* substituteFontData = 0;
-
- while (substituteOffset < runLength) {
- // FIXME: Using ATSUMatchFontsToText() here results in several problems: the CSS font family list is not necessarily followed for the 2nd
- // and onwards unmatched characters; segmented fonts do not work correctly; behavior does not match the simple text and Uniscribe code
- // paths. Change this function to use Font::glyphDataForCharacter() for each character instead.
- lastOffset = substituteOffset;
- status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);
- if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {
- const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);
- substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;
- if (substituteFontData) {
- initializeATSUStyle(substituteFontData, m_font->fontDescription().textRenderingMode());
- if (substituteFontData->m_ATSUStyle)
- ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);
- } else
- substituteFontData = fontData;
- } else {
- substituteOffset = runLength;
- substituteLength = 0;
- }
-
- bool shapedArabic = false;
- bool isSmallCap = false;
- UniCharArrayOffset firstSmallCap = 0;
- const SimpleFontData *r = fontData;
- UniCharArrayOffset i;
- for (i = lastOffset; ; i++) {
- if (i == substituteOffset || i == substituteOffset + substituteLength) {
- if (isSmallCap) {
- isSmallCap = false;
- initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()), m_font->fontDescription().textRenderingMode());
- ATSUSetRunStyle(layout, r->smallCapsFontData(m_font->fontDescription())->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
- }
- if (i == substituteOffset && substituteLength > 0)
- r = substituteFontData;
- else
- break;
- }
- if (!shapedArabic && WTF::Unicode::isArabicChar(m_run[i]) && !r->shapesArabic()) {
- shapedArabic = true;
- if (!m_charBuffer) {
- m_charBuffer.set(new UChar[runLength]);
- memcpy(m_charBuffer.get(), m_run.characters(), i * sizeof(UChar));
- ATSUTextMoved(layout, m_charBuffer.get());
- }
- shapeArabic(m_run.characters(), m_charBuffer.get(), runLength, i);
- }
- if (m_run.rtl() && !r->m_ATSUMirrors) {
- UChar mirroredChar = u_charMirror(m_run[i]);
- if (mirroredChar != m_run[i]) {
- if (!m_charBuffer) {
- m_charBuffer.set(new UChar[runLength]);
- memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));
- ATSUTextMoved(layout, m_charBuffer.get());
- }
- m_charBuffer[i] = mirroredChar;
- }
- }
- if (m_font->isSmallCaps()) {
- const SimpleFontData* smallCapsData = r->smallCapsFontData(m_font->fontDescription());
- UChar c = m_charBuffer[i];
- UChar newC;
- if (U_GET_GC_MASK(c) & U_GC_M_MASK)
- m_fonts[i] = isSmallCap ? smallCapsData : r;
- else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
- m_charBuffer[i] = newC;
- if (!isSmallCap) {
- isSmallCap = true;
- firstSmallCap = i;
- }
- m_fonts[i] = smallCapsData;
- } else {
- if (isSmallCap) {
- isSmallCap = false;
- initializeATSUStyle(smallCapsData, m_font->fontDescription().textRenderingMode());
- ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
- }
- m_fonts[i] = r;
- }
- } else
- m_fonts[i] = r;
- if (m_fonts[i]->syntheticBoldOffset())
- m_hasSyntheticBold = true;
- }
- substituteOffset += substituteLength;
- }
- if (m_run.padding()) {
- float numSpaces = 0;
- unsigned k;
- for (k = 0; k < runLength; k++)
- if (Font::treatAsSpace(m_run[k]))
- numSpaces++;
-
- if (numSpaces == 0)
- m_padPerSpace = 0;
- else
- m_padPerSpace = ceilf(m_run.padding() / numSpaces);
- } else
- m_padPerSpace = 0;
-}
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
- OwnArrayPtr<UChar> charactersWithOverride;
- TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
- if (run.directionalOverride()) {
- from++;
- to++;
- }
-
- ATSULayoutParameters params(adjustedRun);
- params.initialize(this);
-
- ATSTrapezoid firstGlyphBounds;
- ItemCount actualNumBounds;
-
- OSStatus status = ATSUGetGlyphBounds(params.m_layout, 0, 0, from, to - from, kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
- if (status != noErr || actualNumBounds != 1) {
- static ATSTrapezoid zeroTrapezoid = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
- firstGlyphBounds = zeroTrapezoid;
- }
-
- float beforeWidth = min(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
- float afterWidth = max(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
-
- FloatRect rect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
-
- return rect;
-}
-
-void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- OSStatus status;
-
- int drawPortionLength = to - from;
- OwnArrayPtr<UChar> charactersWithOverride;
- TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
- if (run.directionalOverride())
- from++;
-
- ATSULayoutParameters params(adjustedRun);
- params.initialize(this, graphicsContext);
-
- // ATSUI can't draw beyond -32768 to +32767 so we translate the CTM and tell ATSUI to draw at (0, 0).
- CGContextRef context = graphicsContext->platformContext();
- CGContextTranslateCTM(context, point.x(), point.y());
-
- IntSize shadowSize;
- int shadowBlur;
- Color shadowColor;
- graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor);
-
- bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
- if (hasSimpleShadow) {
- // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
- graphicsContext->clearShadow();
- Color fillColor = graphicsContext->fillColor();
- Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- graphicsContext->setFillColor(shadowFillColor);
- CGContextTranslateCTM(context, shadowSize.width(), shadowSize.height());
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- if (status == noErr && params.m_hasSyntheticBold) {
- // Force relayout for the bold pass
- ATSUClearLayoutCache(params.m_layout, 0);
- params.m_syntheticBoldPass = true;
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- // Force relayout for the next pass
- ATSUClearLayoutCache(params.m_layout, 0);
- params.m_syntheticBoldPass = false;
- }
- CGContextTranslateCTM(context, -shadowSize.width(), -shadowSize.height());
- graphicsContext->setFillColor(fillColor);
- }
-
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- if (status == noErr && params.m_hasSyntheticBold) {
- // Force relayout for the bold pass
- ATSUClearLayoutCache(params.m_layout, 0);
- params.m_syntheticBoldPass = true;
- status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
- }
- CGContextTranslateCTM(context, -point.x(), -point.y());
-
- if (status != noErr)
- // Nothing to do but report the error (dev build only).
- LOG_ERROR("ATSUDrawText() failed(%d)", status);
-
- if (hasSimpleShadow)
- graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
-}
-
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
-{
- if (run.length() == 0)
- return 0;
-
- ATSULayoutParameters params(run, fallbackFonts);
- params.initialize(this);
-
- OSStatus status;
-
- ATSTrapezoid firstGlyphBounds;
- ItemCount actualNumBounds;
- status = ATSUGetGlyphBounds(params.m_layout, 0, 0, 0, run.length(), kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
- if (status != noErr)
- LOG_ERROR("ATSUGetGlyphBounds() failed(%d)", status);
- if (actualNumBounds != 1)
- LOG_ERROR("unexpected result from ATSUGetGlyphBounds(): actualNumBounds(%d) != 1", actualNumBounds);
-
- return max(FixedToFloat(firstGlyphBounds.upperRight.x), FixedToFloat(firstGlyphBounds.lowerRight.x)) -
- min(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool /*includePartialGlyphs*/) const
-{
- OwnArrayPtr<UChar> charactersWithOverride;
- TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
-
- ATSULayoutParameters params(adjustedRun);
- params.initialize(this);
-
- UniCharArrayOffset primaryOffset = 0;
-
- // FIXME: No idea how to avoid including partial glyphs.
- // Not even sure if that's the behavior this yields now.
- Boolean isLeading;
- UniCharArrayOffset secondaryOffset = 0;
- OSStatus status = ATSUPositionToOffset(params.m_layout, FloatToFixed(x), FloatToFixed(-1), &primaryOffset, &isLeading, &secondaryOffset);
- unsigned offset;
- if (status == noErr) {
- offset = (unsigned)primaryOffset;
- if (run.directionalOverride() && offset > 0)
- offset--;
- } else
- // Failed to find offset! Return 0 offset.
- offset = 0;
-
- return offset;
-}
-
-}
-#endif // USE(ATSUI)
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
index 47617d8..41f63a9 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
@@ -30,18 +30,18 @@
#include "GraphicsContext3D.h"
#include "CachedImage.h"
-#include "CanvasActiveInfo.h"
-#include "CanvasArray.h"
-#include "CanvasBuffer.h"
-#include "CanvasFramebuffer.h"
-#include "CanvasFloatArray.h"
-#include "CanvasIntArray.h"
+#include "WebGLActiveInfo.h"
+#include "WebGLArray.h"
+#include "WebGLBuffer.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLFloatArray.h"
+#include "WebGLIntArray.h"
#include "CanvasObject.h"
-#include "CanvasProgram.h"
-#include "CanvasRenderbuffer.h"
-#include "CanvasShader.h"
-#include "CanvasTexture.h"
-#include "CanvasUnsignedByteArray.h"
+#include "WebGLProgram.h"
+#include "WebGLRenderbuffer.h"
+#include "WebGLShader.h"
+#include "WebGLTexture.h"
+#include "WebGLUnsignedByteArray.h"
#include "CString.h"
#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
@@ -175,21 +175,12 @@ GraphicsContext3D::~GraphicsContext3D()
}
}
-void GraphicsContext3D::checkError() const
-{
- // FIXME: This needs to only be done in the debug context. It will probably throw an exception
- // on error and print the error message to the debug console
- GLenum error = ::glGetError();
- if (error != GL_NO_ERROR)
- notImplemented();
-}
-
void GraphicsContext3D::makeContextCurrent()
{
CGLSetCurrentContext(m_contextObj);
}
-void GraphicsContext3D::beginPaint(CanvasRenderingContext3D* context)
+void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
{
UNUSED_PARAM(context);
}
@@ -246,43 +237,42 @@ void GraphicsContext3D::activeTexture(unsigned long texture)
::glActiveTexture(texture);
}
-void GraphicsContext3D::attachShader(CanvasProgram* program, CanvasShader* shader)
+void GraphicsContext3D::attachShader(WebGLProgram* program, WebGLShader* shader)
{
- if (!program || !shader)
- return;
+ ASSERT(program);
+ ASSERT(shader);
ensureContext(m_contextObj);
::glAttachShader((GLuint) program->object(), (GLuint) shader->object());
}
-void GraphicsContext3D::bindAttribLocation(CanvasProgram* program, unsigned long index, const String& name)
+void GraphicsContext3D::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name)
{
- if (!program)
- return;
+ ASSERT(program);
ensureContext(m_contextObj);
::glBindAttribLocation((GLuint) program->object(), index, name.utf8().data());
}
-void GraphicsContext3D::bindBuffer(unsigned long target, CanvasBuffer* buffer)
+void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer)
{
ensureContext(m_contextObj);
::glBindBuffer(target, buffer ? (GLuint) buffer->object() : 0);
}
-void GraphicsContext3D::bindFramebuffer(unsigned long target, CanvasFramebuffer* buffer)
+void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer)
{
ensureContext(m_contextObj);
::glBindFramebufferEXT(target, buffer ? (GLuint) buffer->object() : m_fbo);
}
-void GraphicsContext3D::bindRenderbuffer(unsigned long target, CanvasRenderbuffer* renderbuffer)
+void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer)
{
ensureContext(m_contextObj);
- ::glBindBuffer(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
+ ::glBindRenderbufferEXT(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
}
-void GraphicsContext3D::bindTexture(unsigned long target, CanvasTexture* texture)
+void GraphicsContext3D::bindTexture(unsigned long target, WebGLTexture* texture)
{
ensureContext(m_contextObj);
::glBindTexture(target, texture ? (GLuint) texture->object() : 0);
@@ -324,22 +314,22 @@ void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long
ensureContext(m_contextObj);
::glBufferData(target, size, 0, usage);
}
-void GraphicsContext3D::bufferData(unsigned long target, CanvasArray* array, unsigned long usage)
+void GraphicsContext3D::bufferData(unsigned long target, WebGLArray* array, unsigned long usage)
{
if (!array || !array->length())
return;
ensureContext(m_contextObj);
- ::glBufferData(target, array->sizeInBytes(), array->baseAddress(), usage);
+ ::glBufferData(target, array->byteLength(), array->baseAddress(), usage);
}
-void GraphicsContext3D::bufferSubData(unsigned long target, long offset, CanvasArray* array)
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, WebGLArray* array)
{
if (!array || !array->length())
return;
ensureContext(m_contextObj);
- ::glBufferSubData(target, offset, array->sizeInBytes(), array->baseAddress());
+ ::glBufferSubData(target, offset, array->byteLength(), array->baseAddress());
}
unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
@@ -378,11 +368,9 @@ void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
::glColorMask(red, green, blue, alpha);
}
-void GraphicsContext3D::compileShader(CanvasShader* shader)
+void GraphicsContext3D::compileShader(WebGLShader* shader)
{
- if (!shader)
- return;
-
+ ASSERT(shader);
ensureContext(m_contextObj);
::glCompileShader((GLuint) shader->object());
}
@@ -423,11 +411,10 @@ void GraphicsContext3D::depthRange(double zNear, double zFar)
::glDepthRange(zNear, zFar);
}
-void GraphicsContext3D::detachShader(CanvasProgram* program, CanvasShader* shader)
+void GraphicsContext3D::detachShader(WebGLProgram* program, WebGLShader* shader)
{
- if (!program || !shader)
- return;
-
+ ASSERT(program);
+ ASSERT(shader);
ensureContext(m_contextObj);
::glDetachShader((GLuint) program->object(), (GLuint) shader->object());
}
@@ -480,22 +467,16 @@ void GraphicsContext3D::flush()
::glFlush();
}
-void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, CanvasRenderbuffer* buffer)
+void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer)
{
- if (!buffer)
- return;
-
ensureContext(m_contextObj);
- ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, (GLuint) buffer->object());
+ ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer ? (GLuint) buffer->object() : 0);
}
-void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, CanvasTexture* texture, long level)
+void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level)
{
- if (!texture)
- return;
-
ensureContext(m_contextObj);
- ::glFramebufferTexture2DEXT(target, attachment, textarget, (GLuint) texture->object(), level);
+ ::glFramebufferTexture2DEXT(target, attachment, textarget, texture ? (GLuint) texture->object() : 0, level);
}
void GraphicsContext3D::frontFace(unsigned long mode)
@@ -510,10 +491,12 @@ void GraphicsContext3D::generateMipmap(unsigned long target)
::glGenerateMipmapEXT(target);
}
-bool GraphicsContext3D::getActiveAttrib(CanvasProgram* program, unsigned long index, ActiveInfo& info)
+bool GraphicsContext3D::getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo& info)
{
- if (!program->object())
+ if (!program->object()) {
+ synthesizeGLError(INVALID_VALUE);
return false;
+ }
ensureContext(m_contextObj);
GLint maxAttributeSize = 0;
::glGetProgramiv(static_cast<GLuint>(program->object()), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
@@ -530,10 +513,12 @@ bool GraphicsContext3D::getActiveAttrib(CanvasProgram* program, unsigned long in
return true;
}
-bool GraphicsContext3D::getActiveUniform(CanvasProgram* program, unsigned long index, ActiveInfo& info)
+bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo& info)
{
- if (!program->object())
+ if (!program->object()) {
+ synthesizeGLError(INVALID_VALUE);
return false;
+ }
ensureContext(m_contextObj);
GLint maxUniformSize = 0;
::glGetProgramiv(static_cast<GLuint>(program->object()), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
@@ -550,7 +535,7 @@ bool GraphicsContext3D::getActiveUniform(CanvasProgram* program, unsigned long i
return true;
}
-int GraphicsContext3D::getAttribLocation(CanvasProgram* program, const String& name)
+int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name)
{
if (!program)
return -1;
@@ -561,6 +546,13 @@ int GraphicsContext3D::getAttribLocation(CanvasProgram* program, const String& n
unsigned long GraphicsContext3D::getError()
{
+ if (m_syntheticErrors.size() > 0) {
+ ListHashSet<unsigned long>::iterator iter = m_syntheticErrors.begin();
+ unsigned long err = *iter;
+ m_syntheticErrors.remove(iter);
+ return err;
+ }
+
ensureContext(m_contextObj);
return ::glGetError();
}
@@ -577,7 +569,7 @@ void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
::glHint(target, mode);
}
-bool GraphicsContext3D::isBuffer(CanvasBuffer* buffer)
+bool GraphicsContext3D::isBuffer(WebGLBuffer* buffer)
{
if (!buffer)
return false;
@@ -592,7 +584,7 @@ bool GraphicsContext3D::isEnabled(unsigned long cap)
return ::glIsEnabled(cap);
}
-bool GraphicsContext3D::isFramebuffer(CanvasFramebuffer* framebuffer)
+bool GraphicsContext3D::isFramebuffer(WebGLFramebuffer* framebuffer)
{
if (!framebuffer)
return false;
@@ -601,7 +593,7 @@ bool GraphicsContext3D::isFramebuffer(CanvasFramebuffer* framebuffer)
return ::glIsFramebufferEXT((GLuint) framebuffer->object());
}
-bool GraphicsContext3D::isProgram(CanvasProgram* program)
+bool GraphicsContext3D::isProgram(WebGLProgram* program)
{
if (!program)
return false;
@@ -610,7 +602,7 @@ bool GraphicsContext3D::isProgram(CanvasProgram* program)
return ::glIsProgram((GLuint) program->object());
}
-bool GraphicsContext3D::isRenderbuffer(CanvasRenderbuffer* renderbuffer)
+bool GraphicsContext3D::isRenderbuffer(WebGLRenderbuffer* renderbuffer)
{
if (!renderbuffer)
return false;
@@ -619,7 +611,7 @@ bool GraphicsContext3D::isRenderbuffer(CanvasRenderbuffer* renderbuffer)
return ::glIsRenderbufferEXT((GLuint) renderbuffer->object());
}
-bool GraphicsContext3D::isShader(CanvasShader* shader)
+bool GraphicsContext3D::isShader(WebGLShader* shader)
{
if (!shader)
return false;
@@ -628,7 +620,7 @@ bool GraphicsContext3D::isShader(CanvasShader* shader)
return ::glIsShader((GLuint) shader->object());
}
-bool GraphicsContext3D::isTexture(CanvasTexture* texture)
+bool GraphicsContext3D::isTexture(WebGLTexture* texture)
{
if (!texture)
return false;
@@ -643,11 +635,9 @@ void GraphicsContext3D::lineWidth(double width)
::glLineWidth(static_cast<float>(width));
}
-void GraphicsContext3D::linkProgram(CanvasProgram* program)
+void GraphicsContext3D::linkProgram(WebGLProgram* program)
{
- if (!program)
- return;
-
+ ASSERT(program);
ensureContext(m_contextObj);
::glLinkProgram((GLuint) program->object());
}
@@ -664,7 +654,7 @@ void GraphicsContext3D::polygonOffset(double factor, double units)
::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units));
}
-PassRefPtr<CanvasArray> GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
+PassRefPtr<WebGLArray> GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type)
{
ensureContext(m_contextObj);
@@ -675,7 +665,7 @@ PassRefPtr<CanvasArray> GraphicsContext3D::readPixels(long x, long y, unsigned l
if (type != GL_UNSIGNED_BYTE || format != GL_RGBA)
return 0;
- RefPtr<CanvasUnsignedByteArray> array = CanvasUnsignedByteArray::create(width * height * 4);
+ RefPtr<WebGLUnsignedByteArray> array = WebGLUnsignedByteArray::create(width * height * 4);
::glReadPixels(x, y, width, height, format, type, (GLvoid*) array->data());
return array;
}
@@ -705,10 +695,9 @@ void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned lo
::glScissor(x, y, width, height);
}
-void GraphicsContext3D::shaderSource(CanvasShader* shader, const String& string)
+void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& string)
{
- if (!shader)
- return;
+ ASSERT(shader);
ensureContext(m_contextObj);
const CString& cs = string.utf8();
@@ -889,19 +878,17 @@ void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* a
::glUniformMatrix4fv(location, size, transpose, array);
}
-void GraphicsContext3D::useProgram(CanvasProgram* program)
+void GraphicsContext3D::useProgram(WebGLProgram* program)
{
- if (!program)
- return;
+ ASSERT(program);
ensureContext(m_contextObj);
::glUseProgram((GLuint) program->object());
}
-void GraphicsContext3D::validateProgram(CanvasProgram* program)
+void GraphicsContext3D::validateProgram(WebGLProgram* program)
{
- if (!program)
- return;
+ ASSERT(program);
ensureContext(m_contextObj);
::glValidateProgram((GLuint) program->object());
@@ -967,567 +954,156 @@ void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned l
::glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
}
-static int sizeForGetParam(unsigned long pname)
-{
- switch(pname) {
- case GL_ACTIVE_TEXTURE: return 1;
- case GL_ALIASED_LINE_WIDTH_RANGE: return 2;
- case GL_ALIASED_POINT_SIZE_RANGE: return 2;
- case GL_ALPHA_BITS: return 1;
- case GL_ARRAY_BUFFER_BINDING: return 1; // (* actually a CanvasBuffer*)
- case GL_BLEND: return 1;
- case GL_BLEND_COLOR: return 4;
- case GL_BLEND_DST_ALPHA: return 1;
- case GL_BLEND_DST_RGB: return 1;
- case GL_BLEND_EQUATION_ALPHA: return 1;
- case GL_BLEND_EQUATION_RGB: return 1;
- case GL_BLEND_SRC_ALPHA: return 1;
- case GL_BLEND_SRC_RGB: return 1;
- case GL_BLUE_BITS: return 1;
- case GL_COLOR_CLEAR_VALUE: return 4;
- case GL_COLOR_WRITEMASK: return 4;
- case GL_COMPRESSED_TEXTURE_FORMATS: return GL_NUM_COMPRESSED_TEXTURE_FORMATS;
- case GL_CULL_FACE: return 1;
- case GL_CULL_FACE_MODE: return 1;
- case GL_CURRENT_PROGRAM: return 1; // (* actually a CanvasProgram*)
- case GL_DEPTH_BITS: return 1;
- case GL_DEPTH_CLEAR_VALUE: return 1;
- case GL_DEPTH_FUNC: return 1;
- case GL_DEPTH_RANGE: return 2;
- case GL_DEPTH_TEST: return 1;
- case GL_DEPTH_WRITEMASK: return 1;
- case GL_DITHER: return 1;
- case GL_ELEMENT_ARRAY_BUFFER_BINDING: return 1; // (* actually a CanvasBuffer*)
- case GL_FRAMEBUFFER_BINDING_EXT: return 1; // (* actually a CanvasFramebuffer*)
- case GL_FRONT_FACE: return 1;
- case GL_GENERATE_MIPMAP_HINT: return 1;
- case GL_GREEN_BITS: return 1;
- //case GL_IMPLEMENTATION_COLOR_READ_FORMAT:return 1;
- //case GL_IMPLEMENTATION_COLOR_READ_TYPE: return 1;
- case GL_LINE_WIDTH: return 1;
- case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:return 1;
- case GL_MAX_CUBE_MAP_TEXTURE_SIZE: return 1;
- //case GL_MAX_FRAGMENT_UNIFORM_VECTORS: return 1;
- case GL_MAX_RENDERBUFFER_SIZE_EXT: return 1;
- case GL_MAX_TEXTURE_IMAGE_UNITS: return 1;
- case GL_MAX_TEXTURE_SIZE: return 1;
- //case GL_MAX_VARYING_VECTORS: return 1;
- case GL_MAX_VERTEX_ATTRIBS: return 1;
- case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: return 1;
- //case GL_MAX_VERTEX_UNIFORM_VECTORS: return 1;
- case GL_MAX_VIEWPORT_DIMS: return 2;
- case GL_NUM_COMPRESSED_TEXTURE_FORMATS: return 1;
- //case GL_NUM_SHADER_BINARY_FORMATS: return 1;
- case GL_PACK_ALIGNMENT: return 1;
- case GL_POLYGON_OFFSET_FACTOR: return 1;
- case GL_POLYGON_OFFSET_FILL: return 1;
- case GL_POLYGON_OFFSET_UNITS: return 1;
- case GL_RED_BITS: return 1;
- case GL_RENDERBUFFER_BINDING_EXT: return 1; // (* actually a CanvasRenderbuffer*)
- case GL_SAMPLE_BUFFERS: return 1;
- case GL_SAMPLE_COVERAGE_INVERT: return 1;
- case GL_SAMPLE_COVERAGE_VALUE: return 1;
- case GL_SAMPLES: return 1;
- case GL_SCISSOR_BOX: return 4;
- case GL_SCISSOR_TEST: return 1;
- //case GL_SHADER_BINARY_FORMATS: return GL_NUM_SHADER_BINARY_FORMATS;
- //case GL_SHADER_COMPILER: return 1;
- case GL_STENCIL_BACK_FAIL: return 1;
- case GL_STENCIL_BACK_FUNC: return 1;
- case GL_STENCIL_BACK_PASS_DEPTH_FAIL: return 1;
- case GL_STENCIL_BACK_PASS_DEPTH_PASS: return 1;
- case GL_STENCIL_BACK_REF: return 1;
- case GL_STENCIL_BACK_VALUE_MASK: return 1;
- case GL_STENCIL_BACK_WRITEMASK: return 1;
- case GL_STENCIL_BITS: return 1;
- case GL_STENCIL_CLEAR_VALUE: return 1;
- case GL_STENCIL_FAIL: return 1;
- case GL_STENCIL_FUNC: return 1;
- case GL_STENCIL_PASS_DEPTH_FAIL: return 1;
- case GL_STENCIL_PASS_DEPTH_PASS: return 1;
- case GL_STENCIL_REF: return 1;
- case GL_STENCIL_TEST: return 1;
- case GL_STENCIL_VALUE_MASK: return 1;
- case GL_STENCIL_WRITEMASK: return 1;
- case GL_SUBPIXEL_BITS: return 1;
- case GL_TEXTURE_BINDING_2D: return 1; // (* actually a CanvasTexture*)
- case GL_TEXTURE_BINDING_CUBE_MAP: return 1; // (* actually a CanvasTexture*)
- case GL_UNPACK_ALIGNMENT: return 1;
- case GL_VIEWPORT: return 4;
- }
-
- return -1;
-}
-
-bool GraphicsContext3D::getBoolean(unsigned long pname)
-{
- int size = sizeForGetParam(pname);
- if (size < 1)
- return 0;
-
- ensureContext(m_contextObj);
-
- bool isAlloced = false;
- GLboolean buf[4];
- GLboolean* pbuf = buf;
-
- if (size > 4) {
- pbuf = (GLboolean*) malloc(size * sizeof(GLboolean));
- isAlloced = true;
- }
-
- ::glGetBooleanv(pname, pbuf);
-
- bool value = pbuf[0];
-
- if (isAlloced)
- free(pbuf);
-
- return value;
-}
-
-PassRefPtr<CanvasUnsignedByteArray> GraphicsContext3D::getBooleanv(unsigned long pname)
-{
- int size = sizeForGetParam(pname);
- if (size < 1)
- return 0;
-
- ensureContext(m_contextObj);
-
- RefPtr<CanvasUnsignedByteArray> array = CanvasUnsignedByteArray::create(size);
- bool isAlloced = false;
- GLboolean buf[4];
- GLboolean* pbuf = buf;
-
- if (size > 4) {
- pbuf = (GLboolean*) malloc(size * sizeof(GLboolean));
- isAlloced = true;
- }
-
- ::glGetBooleanv(pname, pbuf);
-
- for (int i = 0; i < size; ++i)
- array->set(i, static_cast<unsigned char>(pbuf[i]));
-
- if (isAlloced)
- free(pbuf);
-
- return array;
-}
-
-float GraphicsContext3D::getFloat(unsigned long pname)
+void GraphicsContext3D::getBooleanv(unsigned long pname, unsigned char* value)
{
- int size = sizeForGetParam(pname);
- if (size < 1)
- return 0;
-
ensureContext(m_contextObj);
-
- bool isAlloced = false;
- GLfloat buf[4];
- GLfloat* pbuf = buf;
-
- if (size > 4) {
- pbuf = (GLfloat*) malloc(size * sizeof(GLfloat));
- isAlloced = true;
- }
-
- ::glGetFloatv(pname, pbuf);
-
- float value = pbuf[0];
-
- if (isAlloced)
- free(pbuf);
-
- return value;
+ ::glGetBooleanv(pname, value);
}
-PassRefPtr<CanvasFloatArray> GraphicsContext3D::getFloatv(unsigned long pname)
+void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname, int* value)
{
- int size = sizeForGetParam(pname);
- if (size < 1)
- return 0;
-
ensureContext(m_contextObj);
-
- RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(size);
- bool isAlloced = false;
- GLfloat buf[4];
- GLfloat* pbuf = buf;
-
- if (size > 4) {
- pbuf = (GLfloat*) malloc(size * sizeof(GLfloat));
- isAlloced = true;
- }
-
- ::glGetFloatv(pname, pbuf);
-
- for (int i = 0; i < size; ++i)
- array->set(i, static_cast<float>(pbuf[i]));
-
- if (isAlloced)
- free(pbuf);
-
- return array;
+ ::glGetBufferParameteriv(target, pname, value);
}
-int GraphicsContext3D::getInteger(unsigned long pname)
+void GraphicsContext3D::getFloatv(unsigned long pname, float* value)
{
- int size = sizeForGetParam(pname);
- if (size < 1)
- return 0;
-
ensureContext(m_contextObj);
-
- bool isAlloced = false;
- GLint buf[4];
- GLint* pbuf = buf;
-
- if (size > 4) {
- pbuf = (GLint*) malloc(size * sizeof(GLint));
- isAlloced = true;
- }
-
- ::glGetIntegerv(pname, pbuf);
-
- int value = pbuf[0];
-
- if (isAlloced)
- free(pbuf);
-
- return value;
+ ::glGetFloatv(pname, value);
}
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getIntegerv(unsigned long pname)
+void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value)
{
- int size = sizeForGetParam(pname);
- if (size < 1)
- return 0;
-
ensureContext(m_contextObj);
-
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(size);
- bool isAlloced = false;
- GLint buf[4];
- GLint* pbuf = buf;
-
- if (size > 4) {
- pbuf = (GLint*) malloc(size * sizeof(GLint));
- isAlloced = true;
- }
-
- ::glGetIntegerv(pname, pbuf);
-
- for (int i = 0; i < size; ++i)
- array->set(i, static_cast<int>(pbuf[i]));
-
- if (isAlloced)
- free(pbuf);
-
- return array;
+ ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
}
-int GraphicsContext3D::getBufferParameteri(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getIntegerv(unsigned long pname, int* value)
{
ensureContext(m_contextObj);
- GLint data;
- ::glGetBufferParameteriv(target, pname, &data);
- return data;
+ ::glGetIntegerv(pname, value);
}
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long pname, int* value)
{
ensureContext(m_contextObj);
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
- GLint data;
- ::glGetBufferParameteriv(target, pname, &data);
- array->set(0, static_cast<int>(data));
-
- return array;
+ ::glGetProgramiv((GLuint) program->object(), pname, value);
}
-int GraphicsContext3D::getFramebufferAttachmentParameteri(unsigned long target, unsigned long attachment, unsigned long pname)
+String GraphicsContext3D::getProgramInfoLog(WebGLProgram* program)
{
- ensureContext(m_contextObj);
- GLint data;
- ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, &data);
- return data;
-}
-
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname)
-{
- ensureContext(m_contextObj);
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
- GLint data;
- ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, &data);
- array->set(0, static_cast<int>(data));
-
- return array;
-}
-
-int GraphicsContext3D::getProgrami(CanvasProgram* program, unsigned long pname)
-{
- ensureContext(m_contextObj);
- GLint data;
- ::glGetProgramiv((GLuint) program->object(), pname, &data);
- return data;
-}
-
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getProgramiv(CanvasProgram* program, unsigned long pname)
-{
- ensureContext(m_contextObj);
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
- GLint data;
- ::glGetProgramiv((GLuint) program->object(), pname, &data);
- array->set(0, static_cast<int>(data));
-
- return array;
-}
-
-String GraphicsContext3D::getProgramInfoLog(CanvasProgram* program)
-{
- if (!program)
- return String();
+ ASSERT(program);
ensureContext(m_contextObj);
GLint length;
::glGetProgramiv((GLuint) program->object(), GL_INFO_LOG_LENGTH, &length);
GLsizei size;
- GLchar* info = (GLchar*) malloc(length);
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
::glGetProgramInfoLog((GLuint) program->object(), length, &size, info);
String s(info);
- free(info);
+ fastFree(info);
return s;
}
-int GraphicsContext3D::getRenderbufferParameteri(unsigned long target, unsigned long pname)
-{
- ensureContext(m_contextObj);
- GLint data;
- ::glGetBufferParameteriv(target, pname, &data);
- return data;
-}
-
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long pname, int* value)
{
ensureContext(m_contextObj);
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
- GLint data;
- ::glGetBufferParameteriv(target, pname, &data);
- array->set(0, static_cast<int>(data));
-
- return array;
+ ::glGetRenderbufferParameterivEXT(target, pname, value);
}
-int GraphicsContext3D::getShaderi(CanvasShader* shader, unsigned long pname)
+void GraphicsContext3D::getShaderiv(WebGLShader* shader, unsigned long pname, int* value)
{
- if (!shader)
- return 0;
-
- ensureContext(m_contextObj);
- GLint data;
- ::glGetShaderiv((GLuint) shader->object(), pname, &data);
- return data;
-}
-
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getShaderiv(CanvasShader* shader, unsigned long pname)
-{
- if (!shader)
- return 0;
+ ASSERT(shader);
ensureContext(m_contextObj);
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
- GLint data;
- ::glGetShaderiv((GLuint) shader->object(), pname, &data);
- array->set(0, static_cast<int>(data));
-
- return array;
+ ::glGetShaderiv((GLuint) shader->object(), pname, value);
}
-String GraphicsContext3D::getShaderInfoLog(CanvasShader* shader)
+String GraphicsContext3D::getShaderInfoLog(WebGLShader* shader)
{
- if (!shader)
- return String();
+ ASSERT(shader);
ensureContext(m_contextObj);
GLint length;
::glGetShaderiv((GLuint) shader->object(), GL_INFO_LOG_LENGTH, &length);
GLsizei size;
- GLchar* info = (GLchar*) malloc(length);
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
::glGetShaderInfoLog((GLuint) shader->object(), length, &size, info);
String s(info);
- free(info);
+ fastFree(info);
return s;
}
-String GraphicsContext3D::getShaderSource(CanvasShader* shader)
+String GraphicsContext3D::getShaderSource(WebGLShader* shader)
{
- if (!shader)
- return String();
-
+ ASSERT(shader);
+
ensureContext(m_contextObj);
GLint length;
::glGetShaderiv((GLuint) shader->object(), GL_SHADER_SOURCE_LENGTH, &length);
GLsizei size;
- GLchar* info = (GLchar*) malloc(length);
+ GLchar* info = (GLchar*) fastMalloc(length);
+ if (!info)
+ return "";
+
::glGetShaderSource((GLuint) shader->object(), length, &size, info);
String s(info);
- free(info);
+ fastFree(info);
return s;
}
-float GraphicsContext3D::getTexParameterf(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname, float* value)
{
ensureContext(m_contextObj);
- GLfloat data;
- ::glGetTexParameterfv(target, pname, &data);
- return data;
+ ::glGetTexParameterfv(target, pname, value);
}
-PassRefPtr<CanvasFloatArray> GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname, int* value)
{
ensureContext(m_contextObj);
- RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(1);
- GLfloat data;
- ::glGetTexParameterfv(target, pname, &data);
- array->set(0, static_cast<float>(data));
-
- return array;
+ ::glGetTexParameteriv(target, pname, value);
}
-int GraphicsContext3D::getTexParameteri(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getUniformfv(WebGLProgram* program, long location, float* value)
{
ensureContext(m_contextObj);
- GLint data;
- ::glGetTexParameteriv(target, pname, &data);
- return data;
+ ::glGetUniformfv((GLuint) program->object(), location, value);
}
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname)
+void GraphicsContext3D::getUniformiv(WebGLProgram* program, long location, int* value)
{
ensureContext(m_contextObj);
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
- GLint data;
- ::glGetTexParameteriv(target, pname, &data);
- array->set(0, static_cast<int>(data));
-
- return array;
-}
-
-float GraphicsContext3D::getUniformf(CanvasProgram* program, long location)
-{
- // FIXME: We need to query glGetUniformLocation to determine the size needed
- UNUSED_PARAM(program);
- UNUSED_PARAM(location);
- notImplemented();
- return 0;
+ ::glGetUniformiv((GLuint) program->object(), location, value);
}
-PassRefPtr<CanvasFloatArray> GraphicsContext3D::getUniformfv(CanvasProgram* program, long location)
+long GraphicsContext3D::getUniformLocation(WebGLProgram* program, const String& name)
{
- // FIXME: We need to query glGetUniformLocation to determine the size needed
- UNUSED_PARAM(program);
- UNUSED_PARAM(location);
- notImplemented();
- return 0;
-}
-
-int GraphicsContext3D::getUniformi(CanvasProgram* program, long location)
-{
- // FIXME: We need to query glGetUniformLocation to determine the size needed
- UNUSED_PARAM(program);
- UNUSED_PARAM(location);
- notImplemented();
- return 0;
-}
-
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getUniformiv(CanvasProgram* program, long location)
-{
- // FIXME: We need to query glGetUniformLocation to determine the size needed
- UNUSED_PARAM(program);
- UNUSED_PARAM(location);
- notImplemented();
- return 0;
-}
-
-long GraphicsContext3D::getUniformLocation(CanvasProgram* program, const String& name)
-{
- if (!program)
- return -1;
+ ASSERT(program);
ensureContext(m_contextObj);
return ::glGetUniformLocation((GLuint) program->object(), name.utf8().data());
}
-static int sizeForGetVertexAttribParam(unsigned long pname)
-{
- switch(pname) {
- case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: return 1; // (* actually a CanvasBuffer*)
- case GL_VERTEX_ATTRIB_ARRAY_ENABLED: return 1;
- case GL_VERTEX_ATTRIB_ARRAY_SIZE: return 1;
- case GL_VERTEX_ATTRIB_ARRAY_STRIDE: return 1;
- case GL_VERTEX_ATTRIB_ARRAY_TYPE: return 1;
- case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: return 1;
- case GL_CURRENT_VERTEX_ATTRIB: return 4;
- }
-
- return -1;
-}
-
-float GraphicsContext3D::getVertexAttribf(unsigned long index, unsigned long pname)
-{
- ensureContext(m_contextObj);
- GLfloat buf[4];
- ::glGetVertexAttribfv(index, pname, buf);
- return buf[0];
-}
-
-PassRefPtr<CanvasFloatArray> GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long pname)
-{
- int size = sizeForGetVertexAttribParam(pname);
- if (size < 1)
- return 0;
-
- ensureContext(m_contextObj);
-
- RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(size);
- GLfloat buf[4];
- ::glGetVertexAttribfv(index, pname, buf);
-
- for (int i = 0; i < size; ++i)
- array->set(i, static_cast<float>(buf[i]));
-
- return array;
-}
-
-int GraphicsContext3D::getVertexAttribi(unsigned long index, unsigned long pname)
+void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long pname, float* value)
{
ensureContext(m_contextObj);
- GLint buf[4];
- ::glGetVertexAttribiv(index, pname, buf);
- return buf[0];
+ ::glGetVertexAttribfv(index, pname, value);
}
-PassRefPtr<CanvasIntArray> GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname)
+void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname, int* value)
{
- int size = sizeForGetVertexAttribParam(pname);
- if (size < 1)
- return 0;
-
ensureContext(m_contextObj);
-
- RefPtr<CanvasIntArray> array = CanvasIntArray::create(size);
- GLint buf[4];
- ::glGetVertexAttribiv(index, pname, buf);
-
- for (int i = 0; i < size; ++i)
- array->set(i, static_cast<int>(buf[i]));
-
- return array;
+ ::glGetVertexAttribiv(index, pname, value);
}
long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname)
@@ -1552,18 +1128,21 @@ static void imageToTexture(Image* image, unsigned target, unsigned level)
size_t textureWidth = CGImageGetWidth(textureImage);
size_t textureHeight = CGImageGetHeight(textureImage);
- GLubyte* textureData = (GLubyte*) malloc(textureWidth * textureHeight * 4);
+ GLubyte* textureData = (GLubyte*) fastMalloc(textureWidth * textureHeight * 4);
+ if (!textureData)
+ return;
+
CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth, textureHeight, 8, textureWidth * 4,
CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast);
-
+ CGContextSetBlendMode(textureContext, kCGBlendModeCopy);
CGContextDrawImage(textureContext, CGRectMake(0, 0, (CGFloat)textureWidth, (CGFloat)textureHeight), textureImage);
CGContextRelease(textureContext);
::glTexImage2D(target, level, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
- free(textureData);
+ fastFree(textureData);
}
-int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, CanvasArray* pixels)
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, WebGLArray* pixels)
{
// FIXME: Need to do bounds checking on the buffer here.
::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels->baseAddress());
@@ -1585,39 +1164,15 @@ int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned inte
return -1;
}
-int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, bool flipY, bool premultiplyAlpha)
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha)
{
// FIXME: need to support flipY and premultiplyAlpha
UNUSED_PARAM(flipY);
UNUSED_PARAM(premultiplyAlpha);
-
- if (!image)
- return -1;
+ ASSERT(image);
ensureContext(m_contextObj);
- CachedImage* cachedImage = image->cachedImage();
- if (!cachedImage)
- return -1;
-
- imageToTexture(cachedImage->image(), target, level);
- return 0;
-}
-
-int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha)
-{
- // FIXME: need to support flipY and premultiplyAlpha
- UNUSED_PARAM(flipY);
- UNUSED_PARAM(premultiplyAlpha);
-
- if (!canvas)
- return -1;
-
- ensureContext(m_contextObj);
- ImageBuffer* buffer = canvas->buffer();
- if (!buffer)
- return -1;
-
- imageToTexture(buffer->image(), target, level);
+ imageToTexture(image, target, level);
return 0;
}
@@ -1634,7 +1189,7 @@ int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElem
return -1;
}
-int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, CanvasArray* pixels)
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, WebGLArray* pixels)
{
// FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
UNUSED_PARAM(target);
@@ -1664,7 +1219,7 @@ int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned x
return -1;
}
-int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLImageElement* image, bool flipY, bool premultiplyAlpha)
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, Image* image, bool flipY, bool premultiplyAlpha)
{
// FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
UNUSED_PARAM(target);
@@ -1681,23 +1236,6 @@ int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned x
return -1;
}
-int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLCanvasElement* canvas, bool flipY, bool premultiplyAlpha)
-{
- // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
- UNUSED_PARAM(target);
- UNUSED_PARAM(level);
- UNUSED_PARAM(xoff);
- UNUSED_PARAM(yoff);
- UNUSED_PARAM(width);
- UNUSED_PARAM(height);
- UNUSED_PARAM(canvas);
-
- // FIXME: need to support flipY and premultiplyAlpha
- UNUSED_PARAM(flipY);
- UNUSED_PARAM(premultiplyAlpha);
- return -1;
-}
-
int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha)
{
// FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
@@ -1745,7 +1283,7 @@ unsigned GraphicsContext3D::createRenderbuffer()
return o;
}
-unsigned GraphicsContext3D::createShader(ShaderType type)
+unsigned GraphicsContext3D::createShader(unsigned long type)
{
ensureContext(m_contextObj);
return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
@@ -1817,6 +1355,11 @@ int GraphicsContext3D::sizeInBytes(int type)
}
}
+void GraphicsContext3D::synthesizeGLError(unsigned long error)
+{
+ m_syntheticErrors.add(error);
+}
+
}
#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index 8cf51b4..8024091 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -54,6 +54,7 @@ public:
// for hosting this GraphicsLayer in a native layer hierarchy
virtual NativeLayer nativeLayer() const;
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
virtual void addChild(GraphicsLayer*);
virtual void addChildAtIndex(GraphicsLayer*, int index);
virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index b351956..dea6bfc 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -47,6 +47,7 @@
#import "WebLayer.h"
#import "WebTiledLayer.h"
#import <limits.h>
+#import <objc/objc-auto.h>
#import <wtf/CurrentTime.h>
#import <wtf/UnusedParam.h>
#import <wtf/RetainPtr.h>
@@ -298,6 +299,18 @@ static void clearLayerBackgroundColor(PlatformLayer* layer)
[layer setBackgroundColor:0];
}
+static void safeSetSublayers(CALayer* layer, NSArray* sublayers)
+{
+ // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
+ if (objc_collectingEnabled() && ![sublayers count]) {
+ while ([[layer sublayers] count])
+ [[[layer sublayers] objectAtIndex:0] removeFromSuperlayer];
+ return;
+ }
+
+ [layer setSublayers:sublayers];
+}
+
static bool caValueFunctionSupported()
{
static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
@@ -315,18 +328,6 @@ GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoord
return CompositingCoordinatesBottomUp;
}
-bool GraphicsLayer::showDebugBorders()
-{
- static bool showDebugBorders = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreLayerBorders"];
- return showDebugBorders;
-}
-
-bool GraphicsLayer::showRepaintCounter()
-{
- static bool showRepaintCounter = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreLayerRepaintCounter"];
- return showRepaintCounter;
-}
-
static NSDictionary* nullActionsDictionary()
{
NSNull* nullValue = [NSNull null];
@@ -352,13 +353,13 @@ PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
}
GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
-: GraphicsLayer(client)
-, m_contentsLayerPurpose(NoContentsLayer)
-, m_contentsLayerHasBackgroundColor(false)
-, m_uncommittedChanges(NoChange)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+ , m_uncommittedChanges(NoChange)
#if ENABLE(3D_CANVAS)
-, m_platformGraphicsContext3D(NullPlatformGraphicsContext3D)
-, m_platformTexture(NullPlatform3DObject)
+ , m_platformGraphicsContext3D(NullPlatformGraphicsContext3D)
+ , m_platformTexture(NullPlatform3DObject)
#endif
{
BEGIN_BLOCK_OBJC_EXCEPTIONS
@@ -409,6 +410,15 @@ NativeLayer GraphicsLayerCA::nativeLayer() const
return m_layer.get();
}
+bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ if (childrenChanged)
+ noteLayerPropertyChanged(ChildrenChanged);
+
+ return childrenChanged;
+}
+
void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
{
GraphicsLayer::addChild(childLayer);
@@ -882,17 +892,16 @@ void GraphicsLayerCA::updateSublayerList()
[newSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
if (m_transformLayer) {
- [m_transformLayer.get() setSublayers:newSublayers];
+ safeSetSublayers(m_transformLayer.get(), newSublayers);
if (m_contentsLayer) {
// If we have a transform layer, then the contents layer is parented in the
// primary layer (which is itself a child of the transform layer).
- [m_layer.get() setSublayers:nil];
+ safeSetSublayers(m_layer.get(), nil);
[m_layer.get() addSublayer:m_contentsLayer.get()];
}
- } else {
- [m_layer.get() setSublayers:newSublayers];
- }
+ } else
+ safeSetSublayers(m_layer.get(), newSublayers);
[newSublayers release];
}
@@ -1757,7 +1766,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
}
[m_layer.get() setLayerOwner:this];
- [m_layer.get() setSublayers:[oldLayer.get() sublayers]];
+ safeSetSublayers(m_layer.get(), [oldLayer.get() sublayers]);
[[oldLayer.get() superlayer] replaceSublayer:oldLayer.get() with:m_layer.get()];
diff --git a/WebCore/platform/graphics/mac/IconMac.mm b/WebCore/platform/graphics/mac/IconMac.mm
index 63abe59..aee7234 100644
--- a/WebCore/platform/graphics/mac/IconMac.mm
+++ b/WebCore/platform/graphics/mac/IconMac.mm
@@ -39,27 +39,32 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- // Don't pass relative filenames -- we don't want a result that depends on the current directory.
- // Need 0U here to disambiguate String::operator[] from operator(NSString*, int)[]
- if (filename.isEmpty() || filename[0U] != '/')
+ if (filenames.isEmpty())
return 0;
- NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile:filename];
- if (!image)
- return 0;
+ bool useIconFromFirstFile;
+#ifdef BUILDING_ON_TIGER
+ // FIXME: find a better image for multiple files to use on Tiger.
+ useIconFromFirstFile = true;
+#else
+ useIconFromFirstFile = filenames.size() == 1;
+#endif
+ if (useIconFromFirstFile) {
+ // Don't pass relative filenames -- we don't want a result that depends on the current directory.
+ // Need 0U here to disambiguate String::operator[] from operator(NSString*, int)[]
+ if (filenames[0].isEmpty() || filenames[0][0U] != '/')
+ return 0;
- return adoptRef(new Icon(image));
-}
+ NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile:filenames[0]];
+ if (!image)
+ return 0;
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
-{
- if (filenames.isEmpty())
- return 0;
+ return adoptRef(new Icon(image));
+ }
#ifdef BUILDING_ON_TIGER
- // FIXME: find a better image to use on Tiger.
- return createIconForFile(filenames[0]);
+ return 0;
#else
NSImage* image = [NSImage imageNamed:NSImageNameMultipleDocuments];
if (!image)
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 0a63626..7aaf95d 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -101,6 +101,9 @@ private:
void setVolume(float);
void setPreservesPitch(bool);
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool);
+
void setEndTime(float time);
int dataRate() const;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 30d0c82..dfb5958 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -736,8 +736,13 @@ bool MediaPlayerPrivate::hasAudio() const
}
bool MediaPlayerPrivate::supportsFullscreen() const
-{
+{
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
return true;
+#else
+ // See <rdar://problem/7389945>
+ return false;
+#endif
}
void MediaPlayerPrivate::setVolume(float volume)
@@ -746,6 +751,27 @@ void MediaPlayerPrivate::setVolume(float volume)
[m_qtMovie.get() setVolume:volume];
}
+bool MediaPlayerPrivate::hasClosedCaptions() const
+{
+ if (!metaDataAvailable())
+ return false;
+ return wkQTMovieHasClosedCaptions(m_qtMovie.get());
+}
+
+void MediaPlayerPrivate::setClosedCaptionsVisible(bool closedCaptionsVisible)
+{
+ if (metaDataAvailable()) {
+ wkQTMovieSetShowClosedCaptions(m_qtMovie.get(), closedCaptionsVisible);
+
+#if USE(ACCELERATED_COMPOSITING) && (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+ if (closedCaptionsVisible && m_qtVideoLayer) {
+ // Captions will be rendered upsided down unless we flag the movie as flipped (again). See <rdar://7408440>.
+ [m_qtVideoLayer.get() setGeometryFlipped:YES];
+ }
+#endif
+ }
+}
+
void MediaPlayerPrivate::setRate(float rate)
{
if (m_qtMovie)
@@ -1158,10 +1184,10 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
TextRun textRun(text.characters(), text.length());
const Color color(255, 0, 0);
context->scale(FloatSize(1.0f, -1.0f));
- context->setStrokeColor(color);
+ context->setStrokeColor(color, styleToUse->colorSpace());
context->setStrokeStyle(SolidStroke);
context->setStrokeThickness(1.0f);
- context->setFillColor(color);
+ context->setFillColor(color, styleToUse->colorSpace());
context->drawText(styleToUse->font(), textRun, IntPoint(2, -3));
}
}
diff --git a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp
new file mode 100644
index 0000000..b4cdb09
--- /dev/null
+++ b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#if ENABLE(OPENTYPE_SANITIZER)
+#include "OpenTypeSanitizer.h"
+
+#include "SharedBuffer.h"
+#include "opentype-sanitiser.h"
+#include "ots-memory-stream.h"
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize()
+{
+ if (!m_buffer)
+ return 0;
+
+ // This is the largest web font size which we'll try to transcode.
+ static const size_t maxWebFontSize = 30 * 1024 * 1024; // 30 MB
+ if (m_buffer->size() > maxWebFontSize)
+ return 0;
+
+ // A transcoded font is usually smaller than an original font.
+ // However, it can be slightly bigger than the original one due to
+ // name table replacement and/or padding for glyf table.
+ static const size_t padLen = 20 * 1024; // 20 kB
+
+ OwnArrayPtr<unsigned char> transcodeRawBuffer(new unsigned char[m_buffer->size() + padLen]);
+ ots::MemoryStream output(transcodeRawBuffer.get(), m_buffer->size() + padLen);
+ if (!ots::Process(&output, reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size()))
+ return 0;
+
+ const size_t transcodeLen = output.Tell();
+ return SharedBuffer::create(transcodeRawBuffer.get(), transcodeLen);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(OPENTYPE_SANITIZER)
diff --git a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.h b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.h
new file mode 100644
index 0000000..3f93448
--- /dev/null
+++ b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OpenTypeSanitizer_h
+#define OpenTypeSanitizer_h
+
+#if ENABLE(OPENTYPE_SANITIZER)
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+
+class OpenTypeSanitizer {
+public:
+ explicit OpenTypeSanitizer(SharedBuffer* buffer)
+ : m_buffer(buffer)
+ {
+ }
+
+ PassRefPtr<SharedBuffer> sanitize();
+
+private:
+ SharedBuffer* const m_buffer;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(OPENTYPE_SANITIZER)
+#endif // OpenTypeSanitizer_h
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
index b2e3d92..3a60160 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
@@ -435,7 +435,7 @@ HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
DWORD numFonts = 0;
HANDLE fontHandle = AddFontMemResourceEx(rewrittenFontData.data(), fontData->size() + nameTableSize, 0, &numFonts);
- if (fontHandle && numFonts != 1) {
+ if (fontHandle && numFonts < 1) {
RemoveFontMemResourceEx(fontHandle);
return 0;
}
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
index 1113eae..82fb709 100644
--- a/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -34,260 +34,39 @@
#include <wtf/ListHashSet.h>
#include <wtf/StdLibExtras.h>
+#include <QFont>
+
using namespace WTF;
namespace WebCore {
-FontCache* fontCache()
+void FontCache::platformInit()
{
- DEFINE_STATIC_LOCAL(FontCache, globalFontCache, ());
- return &globalFontCache;
}
-FontCache::FontCache()
-{
-}
-
-void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
-{
-}
-
-// This type must be consistent with FontPlatformData's ctor - the one which
-// gets FontDescription as it's parameter.
-class FontPlatformDataCacheKey {
-public:
- FontPlatformDataCacheKey(const FontDescription& description)
- : m_familyName()
- , m_size(description.computedPixelSize())
- , m_bold(false)
- , m_italic(description.italic())
- , m_smallCaps(description.smallCaps())
- , m_hash(0)
- {
- // FIXME: Map all FontWeight values to QFont weights in FontPlatformData's ctor and follow it here
- if (FontPlatformData::toQFontWeight(description.weight()) > QFont::Normal)
- m_bold = true;
-
- const FontFamily* family = &description.family();
- while (family) {
- m_familyName.append(family->family());
- family = family->next();
- if (family)
- m_familyName.append(',');
- }
-
- computeHash();
- }
-
- FontPlatformDataCacheKey(const FontPlatformData& fontData)
- : m_familyName(static_cast<String>(fontData.family()))
- , m_size(fontData.pixelSize())
- , m_bold(fontData.bold())
- , m_italic(fontData.italic())
- , m_smallCaps(fontData.smallCaps())
- , m_hash(0)
- {
- computeHash();
- }
-
- FontPlatformDataCacheKey(HashTableDeletedValueType) : m_size(hashTableDeletedSize()) { }
- bool isHashTableDeletedValue() const { return m_size == hashTableDeletedSize(); }
-
- enum HashTableEmptyValueType { HashTableEmptyValue };
-
- FontPlatformDataCacheKey(HashTableEmptyValueType)
- : m_familyName()
- , m_size(0)
- , m_bold(false)
- , m_italic(false)
- , m_smallCaps(false)
- , m_hash(0)
- {
- }
-
- bool operator==(const FontPlatformDataCacheKey& other) const
- {
- if (m_hash != other.m_hash)
- return false;
-
- return equalIgnoringCase(m_familyName, other.m_familyName) && m_size == other.m_size &&
- m_bold == other.m_bold && m_italic == other.m_italic && m_smallCaps == other.m_smallCaps;
- }
-
- unsigned hash() const
- {
- return m_hash;
- }
-
- void computeHash()
- {
- unsigned hashCodes[] = {
- CaseFoldingHash::hash(m_familyName),
- m_size | static_cast<unsigned>(m_bold << sizeof(unsigned) * 8 - 1)
- | static_cast<unsigned>(m_italic) << sizeof(unsigned) *8 - 2
- | static_cast<unsigned>(m_smallCaps) << sizeof(unsigned) * 8 - 3
- };
- m_hash = StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
- }
-
-private:
- String m_familyName;
- int m_size;
- bool m_bold;
- bool m_italic;
- bool m_smallCaps;
- unsigned m_hash;
-
- static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
-};
-
-struct FontPlatformDataCacheKeyHash {
- static unsigned hash(const FontPlatformDataCacheKey& key)
- {
- return key.hash();
- }
-
- static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataCacheKey& b)
- {
- return a == b;
- }
-
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
-
-struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
- static const bool needsDestruction = true;
- static const FontPlatformDataCacheKey& emptyValue()
- {
- DEFINE_STATIC_LOCAL(FontPlatformDataCacheKey, key, (FontPlatformDataCacheKey::HashTableEmptyValue));
- return key;
- }
- static void constructDeletedValue(FontPlatformDataCacheKey& slot)
- {
- new (&slot) FontPlatformDataCacheKey(HashTableDeletedValue);
- }
- static bool isDeletedValue(const FontPlatformDataCacheKey& value)
- {
- return value.isHashTableDeletedValue();
- }
-};
-
-typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
-
-// using Q_GLOBAL_STATIC leads to crash. TODO investigate the way to fix this.
-static FontPlatformDataCache* gFontPlatformDataCache = 0;
-
-FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& description, const AtomicString&, bool)
-{
- if (!gFontPlatformDataCache)
- gFontPlatformDataCache = new FontPlatformDataCache;
-
- FontPlatformDataCacheKey key(description);
- FontPlatformData* platformData = gFontPlatformDataCache->get(key);
- if (!platformData) {
- platformData = new FontPlatformData(description);
- gFontPlatformDataCache->add(key, platformData);
- }
- return platformData;
-}
-
-typedef HashMap<FontPlatformDataCacheKey, std::pair<SimpleFontData*, unsigned>, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontDataCache;
-
-static FontDataCache* gFontDataCache = 0;
-
-static const int cMaxInactiveFontData = 40;
-static const int cTargetInactiveFontData = 32;
-
-static ListHashSet<const SimpleFontData*>* gInactiveFontDataSet = 0;
-
-SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* fontPlatformData)
-{
- if (!gFontDataCache) {
- gFontDataCache = new FontDataCache;
- gInactiveFontDataSet = new ListHashSet<const SimpleFontData*>;
- }
-
- FontPlatformDataCacheKey key(*fontPlatformData);
- FontDataCache::iterator it = gFontDataCache->find(key);
- if (it == gFontDataCache->end()) {
- SimpleFontData* fontData = new SimpleFontData(*fontPlatformData);
- gFontDataCache->add(key, std::pair<SimpleFontData*, unsigned>(fontData, 1));
- return fontData;
- }
- if (!it->second.second++) {
- ASSERT(gInactiveFontDataSet->contains(it->second.first));
- gInactiveFontDataSet->remove(it->second.first);
- }
- return it->second.first;
-}
-
-FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription&)
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font&, const UChar*, int)
{
return 0;
}
-void FontCache::releaseFontData(const WebCore::SimpleFontData* fontData)
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
{
- ASSERT(gFontDataCache);
- ASSERT(!fontData->isCustomFont());
-
- FontPlatformDataCacheKey key(fontData->platformData());
- FontDataCache::iterator it = gFontDataCache->find(key);
- ASSERT(it != gFontDataCache->end());
- if (!--it->second.second) {
- gInactiveFontDataSet->add(it->second.first);
- if (gInactiveFontDataSet->size() > cMaxInactiveFontData)
- purgeInactiveFontData(gInactiveFontDataSet->size() - cTargetInactiveFontData);
- }
-}
-
-void FontCache::purgeInactiveFontData(int count)
-{
- static bool isPurging; // Guard against reentry when e.g. a deleted FontData releases its small caps FontData.
- if (isPurging)
- return;
-
- isPurging = true;
-
- ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontDataSet->begin();
- ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontDataSet->end();
- for (int i = 0; i < count && it != end; ++i, ++it) {
- FontPlatformDataCacheKey key = (*it)->platformData();
- pair<SimpleFontData*, unsigned> fontDataPair = gFontDataCache->take(key);
- ASSERT(fontDataPair.first != 0);
- ASSERT(!fontDataPair.second);
- delete fontDataPair.first;
-
- FontPlatformData* platformData = gFontPlatformDataCache->take(key);
- if (platformData)
- delete platformData;
- }
-
- if (it == end) {
- // Removed everything
- gInactiveFontDataSet->clear();
- } else {
- for (int i = 0; i < count; ++i)
- gInactiveFontDataSet->remove(gInactiveFontDataSet->begin());
- }
-
- isPurging = false;
+ return 0;
}
-void FontCache::addClient(FontSelector*)
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
{
+ const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFont();
+ return new FontPlatformData(fontDescription, fallbackFamily);
}
-void FontCache::removeClient(FontSelector*)
+void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
{
}
-void FontCache::invalidate()
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
{
- if (!gFontPlatformDataCache || !gFontDataCache)
- return;
-
- purgeInactiveFontData();
+ return new FontPlatformData(fontDescription, familyName);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
index a19464e..6e9d053 100644
--- a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
@@ -43,7 +43,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
font.setWeight(QFont::Bold);
font.setItalic(italic);
- return FontPlatformData(font, bold);
+ return FontPlatformData(font);
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
deleted file mode 100644
index 8e1e4f6..0000000
--- a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- Copyright (C) 2008 Holger Hans Peter Freyther
-
- 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.
-
- Replacement of the stock FontFallbackList as Qt is going to find us a
- replacement font, will do caching and the other stuff we implement in
- WebKit.
-*/
-
-#include "config.h"
-#include "FontFallbackList.h"
-
-#include "Font.h"
-#include "FontCache.h"
-#include "SegmentedFontData.h"
-
-#include <QDebug>
-
-namespace WebCore {
-
-FontFallbackList::FontFallbackList()
- : m_pageZero(0)
- , m_cachedPrimarySimpleFontData(0)
- , m_fontSelector(0)
- , m_familyIndex(0)
- , m_pitch(UnknownPitch)
- , m_loadingCustomFonts(false)
- , m_generation(0)
-{
-}
-
-void FontFallbackList::invalidate(WTF::PassRefPtr<WebCore::FontSelector> fontSelector)
-{
- releaseFontData();
- m_fontList.clear();
- m_pageZero = 0;
- m_pages.clear();
- m_cachedPrimarySimpleFontData = 0;
- m_familyIndex = 0;
- m_pitch = UnknownPitch;
- m_loadingCustomFonts = false;
- m_fontSelector = fontSelector;
- m_generation = 0;
-}
-
-void FontFallbackList::releaseFontData()
-{
- unsigned numFonts = m_fontList.size();
- for (unsigned i = 0; i < numFonts; ++i) {
- if (m_fontList[i].second)
- delete m_fontList[i].first;
- else {
- ASSERT(!m_fontList[i].first->isSegmented());
- fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first));
- }
- }
-}
-
-void FontFallbackList::determinePitch(const WebCore::Font* font) const
-{
- const FontData* fontData = primaryFontData(font);
- if (!fontData->isSegmented())
- m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch();
- else {
- const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
- unsigned numRanges = segmentedFontData->numRanges();
- if (numRanges == 1)
- m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch();
- else
- m_pitch = VariablePitch;
- }
-}
-
-const FontData* FontFallbackList::fontDataAt(const WebCore::Font* _font, unsigned index) const
-{
- if (index != 0)
- return 0;
-
- // Search for the WebCore font that is already in the list
- for (int i = m_fontList.size() - 1; i >= 0; --i) {
- pair<const FontData*, bool> item = m_fontList[i];
- // item.second means that the item was created locally or not
- if (!item.second)
- return item.first;
- }
-
- // Use the FontSelector to get a WebCore font and then fallback to Qt
- const FontDescription& description = _font->fontDescription();
- const FontFamily* family = &description.family();
- while (family) {
- if (m_fontSelector) {
- FontData* data = m_fontSelector->getFontData(description, family->family());
- if (data) {
- if (data->isLoading())
- m_loadingCustomFonts = true;
- if (!data->isCustomFont()) {
- // Custom fonts can be freed anytime so we must not hold them
- m_fontList.append(pair<const FontData*, bool>(data, false));
- }
- return data;
- }
- }
- family = family->next();
- }
-
- if (m_fontList.size())
- return m_fontList[0].first;
-
- const FontData* result = new SimpleFontData(FontPlatformData(description, _font->wordSpacing(), _font->letterSpacing()), true);
- m_fontList.append(pair<const FontData*, bool>(result, true));
- return result;
-}
-
-const FontData* FontFallbackList::fontDataForCharacters(const WebCore::Font* font, const UChar*, int) const
-{
- return primaryFontData(font);
-}
-
-void FontFallbackList::setPlatformFont(const WebCore::FontPlatformData&)
-{
- m_familyIndex = cAllFamiliesScanned;
-}
-
-}
diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h
index 92219fd..4a3f8bc 100644
--- a/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -26,20 +26,62 @@
#include "FontDescription.h"
#include <QFont>
+#include <QHash>
namespace WebCore {
class String;
+class FontPlatformDataPrivate {
+public:
+ FontPlatformDataPrivate()
+ : refCount(1)
+ , size(font.pointSizeF())
+ , bold(font.bold())
+ , oblique(false)
+ {}
+ FontPlatformDataPrivate(const float size, const bool bold, const bool oblique)
+ : refCount(1)
+ , size(size)
+ , bold(bold)
+ , oblique(oblique)
+ {}
+ FontPlatformDataPrivate(const QFont& font)
+ : refCount(1)
+ , font(font)
+ , size(font.pointSizeF())
+ , bold(font.bold())
+ , oblique(false)
+ {}
+ unsigned refCount;
+ QFont font;
+ float size;
+ bool bold : 1;
+ bool oblique : 1;
+};
+
+
-class FontPlatformData
-{
+class FontPlatformData : public FastAllocBase {
public:
-#if ENABLE(SVG_FONTS)
FontPlatformData(float size, bool bold, bool oblique);
-#endif
- FontPlatformData();
- FontPlatformData(const FontDescription&, int wordSpacing = 0, int letterSpacing = 0);
- FontPlatformData(const QFont&, bool bold);
+ FontPlatformData(const FontPlatformData &);
+ FontPlatformData(const FontDescription&, const AtomicString& familyName, int wordSpacing = 0, int letterSpacing = 0);
+ FontPlatformData(const QFont& font)
+ : m_data(new FontPlatformDataPrivate(font))
+ {}
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_data(reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ {}
+
+ ~FontPlatformData();
+
+ FontPlatformData& operator=(const FontPlatformData&);
+ bool operator==(const FontPlatformData&) const;
+
+ bool isHashTableDeletedValue() const
+ {
+ return m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1);
+ }
static inline QFont::Weight toQFontWeight(FontWeight fontWeight)
{
@@ -62,22 +104,62 @@ public:
}
}
- QFont font() const { return m_font; }
- float size() const { return m_size; }
- QString family() const { return m_font.family(); }
- bool bold() const { return m_bold; }
- bool italic() const { return m_font.italic(); }
- bool smallCaps() const { return m_font.capitalization() == QFont::SmallCaps; }
- int pixelSize() const { return m_font.pixelSize(); }
+ QFont font() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font;
+ return QFont();
+ }
+ float size() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->size;
+ return 0.0f;
+ }
+ QString family() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.family();
+ return QString();
+ }
+ bool bold() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->bold;
+ return false;
+ }
+ bool italic() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.italic();
+ return false;
+ }
+ bool smallCaps() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.capitalization() == QFont::SmallCaps;
+ return false;
+ }
+ int pixelSize() const
+ {
+ Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
+ if (m_data)
+ return m_data->font.pixelSize();
+ return 0;
+ }
+ unsigned hash() const;
#ifndef NDEBUG
String description() const;
#endif
-
- float m_size;
- bool m_bold;
- bool m_oblique;
- QFont m_font;
+private:
+ FontPlatformDataPrivate* m_data;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index 7709be6..2cc2fc6 100644
--- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -26,56 +26,104 @@
namespace WebCore {
-FontPlatformData::FontPlatformData(const FontDescription& description, int wordSpacing, int letterSpacing)
- : m_size(0.0f)
- , m_bold(false)
- , m_oblique(false)
+static inline bool isEmtpyValue(const float size, const bool bold, const bool oblique)
{
- QString familyName;
+ // this is the empty value by definition of the trait FontDataCacheKeyTraits
+ return !bold && !oblique && size == 0.f;
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+{
+ if (isEmtpyValue(size, bold, oblique))
+ m_data = 0;
+ else
+ m_data = new FontPlatformDataPrivate(size, bold, oblique);
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData &other) : m_data(other.m_data)
+{
+ if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ ++m_data->refCount;
+}
+
+FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, int wordSpacing, int letterSpacing)
+ : m_data(new FontPlatformDataPrivate())
+{
+ QString familyNames(familyName);
+ if (!familyName.isEmpty())
+ familyNames += QLatin1Char(',');
+
const FontFamily* family = &description.family();
while (family) {
- familyName += family->family();
+ familyNames += family->family();
family = family->next();
if (family)
- familyName += QLatin1Char(',');
+ familyNames += QLatin1Char(',');
}
+ QFont& font = m_data->font;
+ font.setFamily(familyName);
+ font.setPixelSize(qRound(description.computedSize()));
+ font.setItalic(description.italic());
+ font.setWeight(toQFontWeight(description.weight()));
+ font.setWordSpacing(wordSpacing);
+ font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
+ const bool smallCaps = description.smallCaps();
+ font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+
+ m_data->bold = font.bold();
+ m_data->size = font.pointSizeF();
+}
- m_font.setFamily(familyName);
- m_font.setPixelSize(qRound(description.computedSize()));
- m_font.setItalic(description.italic());
-
- m_font.setWeight(toQFontWeight(description.weight()));
- m_bold = m_font.bold();
-
- bool smallCaps = description.smallCaps();
- m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
- m_font.setWordSpacing(wordSpacing);
- m_font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
- m_size = m_font.pointSize();
+FontPlatformData::~FontPlatformData()
+{
+ if (!m_data || m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ return;
+ --m_data->refCount;
+ if (!m_data->refCount)
+ delete m_data;
}
-FontPlatformData::FontPlatformData(const QFont& font, bool bold)
- : m_size(font.pointSize())
- , m_bold(bold)
- , m_oblique(false)
- , m_font(font)
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
{
+ if (m_data == other.m_data)
+ return *this;
+ if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1)) {
+ --m_data->refCount;
+ if (!m_data->refCount)
+ delete m_data;
+ }
+ m_data = other.m_data;
+ if (m_data && m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ ++m_data->refCount;
+ return *this;
}
-#if ENABLE(SVG_FONTS)
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : m_size(size)
- , m_bold(bold)
- , m_oblique(oblique)
+bool FontPlatformData::operator==(const FontPlatformData& other) const
{
+ if (m_data == other.m_data)
+ return true;
+
+ if (!m_data || !other.m_data
+ || m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1) || other.m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ return false;
+
+ const bool equals = (m_data->size == other.m_data->size
+ && m_data->bold == other.m_data->bold
+ && m_data->oblique == other.m_data->oblique
+ && m_data->font == other.m_data->font);
+ return equals;
}
-#endif
-FontPlatformData::FontPlatformData()
- : m_size(0.0f)
- , m_bold(false)
- , m_oblique(false)
+unsigned FontPlatformData::hash() const
{
+ if (!m_data)
+ return 0;
+ if (m_data == reinterpret_cast<FontPlatformDataPrivate*>(-1))
+ return 1;
+ return qHash(m_data->font.toString())
+ ^ qHash(*reinterpret_cast<quint32*>(&m_data->size))
+ ^ qHash(m_data->bold)
+ ^ qHash(m_data->oblique);
}
#ifndef NDEBUG
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index c5960ac..1e44626 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -42,7 +42,6 @@
#include <limits.h>
-#if QT_VERSION >= 0x040400
namespace WebCore {
static const QString qstring(const TextRun& run)
@@ -229,5 +228,3 @@ QFont Font::font() const
}
-#endif
-
diff --git a/WebCore/platform/graphics/qt/FontQt43.cpp b/WebCore/platform/graphics/qt/FontQt43.cpp
deleted file mode 100644
index 45bf05d..0000000
--- a/WebCore/platform/graphics/qt/FontQt43.cpp
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- Copyright (C) 2008 Holger Hans Peter Freyther
-
- 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.
-*/
-
-#include "config.h"
-#include "Font.h"
-#include "FontDescription.h"
-#include "FontFallbackList.h"
-#include "FontSelector.h"
-
-#include "GraphicsContext.h"
-#include <QTextLayout>
-#include <QPainter>
-#include <QFontMetrics>
-#include <QFontInfo>
-#include <qalgorithms.h>
-#include <qdebug.h>
-
-#include <limits.h>
-
-#if QT_VERSION < 0x040400
-
-namespace WebCore {
-
-struct TextRunComponent {
- TextRunComponent() : font(0) {}
- TextRunComponent(const UChar *start, int length, bool rtl, const QFont *font, int offset, bool sc = false);
- TextRunComponent(int spaces, bool rtl, const QFont *font, int offset);
-
- inline bool isSpace() const { return spaces != 0; }
-
- QString string;
- const QFont *font;
- int width;
- int offset;
- int spaces;
-};
-
-TextRunComponent::TextRunComponent(const UChar *start, int length, bool rtl, const QFont *f, int o, bool sc)
- : string(reinterpret_cast<const QChar*>(start), length)
- , font(f)
- , offset(o)
- , spaces(0)
-{
- if (sc)
- string = string.toUpper();
- string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
- width = QFontMetrics(*font).width(string);
-}
-
-TextRunComponent::TextRunComponent(int s, bool rtl, const QFont *f, int o)
- : string(s, QLatin1Char(' '))
- , font(f)
- , offset(o)
- , spaces(s)
-{
- string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
- width = spaces * QFontMetrics(*font).width(QLatin1Char(' '));
-}
-
-
-static int generateComponents(Vector<TextRunComponent, 1024>* components, const Font &font, const TextRun &run)
-{
-// qDebug() << "generateComponents" << QString((const QChar *)run.characters(), run.length());
- int letterSpacing = font.letterSpacing();
- int wordSpacing = font.wordSpacing();
- bool smallCaps = font.fontDescription().smallCaps();
- int padding = run.padding();
- int numSpaces = 0;
- if (padding) {
- for (int i = 0; i < run.length(); i++)
- if (Font::treatAsSpace(run[i]))
- ++numSpaces;
- }
-
- int offset = 0;
- const QFont *f = &font.font();
- if (letterSpacing || smallCaps) {
- // need to draw every letter on it's own
- int start = 0;
- if (Font::treatAsSpace(run[0])) {
- int add = 0;
- if (numSpaces) {
- add = padding/numSpaces;
- padding -= add;
- --numSpaces;
- }
- components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
- offset += add + letterSpacing + components->last().width;
- start = 1;
-// qDebug() << "space at 0" << offset;
- } else if (smallCaps)
- f = (QChar::category(run[0]) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
-
- for (int i = 1; i < run.length(); ++i) {
- uint ch = run[i];
- if (QChar(ch).isHighSurrogate() && QChar(run[i-1]).isLowSurrogate())
- ch = QChar::surrogateToUcs4(ch, run[i-1]);
- if (QChar(ch).isLowSurrogate() || QChar::category(ch) == QChar::Mark_NonSpacing)
- continue;
- if (Font::treatAsSpace(run[i])) {
- int add = 0;
-// qDebug() << " treatAsSpace:" << i << start;
- if (i - start > 0) {
- components->append(TextRunComponent(run.characters() + start, i - start,
- run.rtl(),
- f, offset, f == &font.scFont()));
- offset += components->last().width + letterSpacing;
-// qDebug() << " appending(1) " << components->last().string << components->last().width;
- }
- if (numSpaces) {
- add = padding/numSpaces;
- padding -= add;
- --numSpaces;
- }
- components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
- offset += wordSpacing + add + components->last().width + letterSpacing;
- start = i + 1;
- continue;
- } else if (!letterSpacing) {
-// qDebug() << i << char(run[i]) << (QChar::category(ch) == QChar::Letter_Lowercase) <<
-// QFontInfo(*f).pointSizeF();
- if (QChar::category(ch) == QChar::Letter_Lowercase) {
- if (f == &font.scFont())
- continue;
- } else {
- if (f == &font.font())
- continue;
- }
- }
- if (i - start > 0) {
- components->append(TextRunComponent(run.characters() + start, i - start,
- run.rtl(),
- f, offset, f == &font.scFont()));
- offset += components->last().width + letterSpacing;
-// qDebug() << " appending(2) " << components->last().string << components->last().width;
- }
- if (smallCaps)
- f = (QChar::category(ch) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
- start = i;
- }
- if (run.length() - start > 0) {
- components->append(TextRunComponent(run.characters() + start, run.length() - start,
- run.rtl(),
- f, offset, f == &font.scFont()));
- offset += components->last().width;
-// qDebug() << " appending(3) " << components->last().string << components->last().width;
- }
- offset += letterSpacing;
- } else {
- int start = 0;
- for (int i = 0; i < run.length(); ++i) {
- if (Font::treatAsSpace(run[i])) {
- if (i - start > 0) {
- components->append(TextRunComponent(run.characters() + start, i - start,
- run.rtl(),
- f, offset));
- offset += components->last().width;
- }
- int add = 0;
- if (numSpaces) {
- add = padding/numSpaces;
- padding -= add;
- --numSpaces;
- }
- components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
- offset += add + components->last().width;
- if (i)
- offset += wordSpacing;
- start = i + 1;
- }
- }
- if (run.length() - start > 0) {
- components->append(TextRunComponent(run.characters() + start, run.length() - start,
- run.rtl(),
- f, offset));
- offset += components->last().width;
- }
- }
- return offset;
-}
-
-void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- if (to < 0)
- to = run.length();
-
- QPainter *p = ctx->platformContext();
- Color color = ctx->fillColor();
- p->setPen(QColor(color));
-
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- if (from > 0 || to < run.length()) {
- FloatRect clip = selectionRectForComplexText(run,
- IntPoint(qRound(point.x()), qRound(point.y())),
- QFontMetrics(font()).height(), from, to);
- QRectF rect(clip.x(), clip.y() - ascent(), clip.width(), clip.height());
- p->save();
- p->setClipRect(rect.toRect());
- }
-
- if (run.rtl()) {
- for (int i = 0; i < components.size(); ++i) {
- if (!components.at(i).isSpace()) {
- p->setFont(*components.at(i).font);
- QPointF pt(point.x() + w - components.at(i).offset - components.at(i).width, point.y());
- p->drawText(pt, components.at(i).string);
- }
- }
- } else {
- for (int i = 0; i < components.size(); ++i) {
- if (!components.at(i).isSpace()) {
- p->setFont(*components.at(i).font);
- QPointF pt(point.x() + components.at(i).offset, point.y());
- p->drawText(pt, components.at(i).string);
- }
- }
- }
- if (from > 0 || to < run.length())
- p->restore();
-}
-
-float Font::floatWidthForComplexText(const TextRun& run) const
-{
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- return w;
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
-{
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- int offset = 0;
- if (run.rtl()) {
- for (int i = 0; i < components.size(); ++i) {
- int xe = w - components.at(i).offset;
- int xs = xe - components.at(i).width;
- if (position >= xs) {
- QTextLayout layout(components.at(i).string, *components.at(i).font);
- layout.beginLayout();
- QTextLine l = layout.createLine();
- if (!l.isValid())
- return offset;
-
- l.setLineWidth(INT_MAX / 256);
- layout.endLayout();
-
- if (position - xs >= l.width())
- return offset;
- int cursor = l.xToCursor(position - xs);
- if (cursor > 1)
- --cursor;
- return offset + cursor;
- } else
- offset += components.at(i).string.length() - 1;
- }
- } else {
- for (int i = 0; i < components.size(); ++i) {
- int xs = components.at(i).offset;
- int xe = xs + components.at(i).width;
- if (position <= xe) {
- QTextLayout layout(components.at(i).string, *components.at(i).font);
- layout.beginLayout();
- QTextLine l = layout.createLine();
- if (!l.isValid())
- return offset;
-
- l.setLineWidth(INT_MAX / 256);
- layout.endLayout();
-
- if (position - xs >= l.width())
- return offset + components.at(i).string.length() - 1;
- int cursor = l.xToCursor(position - xs);
- if (cursor > 1)
- --cursor;
- return offset + cursor;
- } else
- offset += components.at(i).string.length() - 1;
- }
- }
- return run.length();
-}
-
-static float cursorToX(const Vector<TextRunComponent, 1024>& components, int width, bool rtl, int cursor)
-{
- int start = 0;
- for (int i = 0; i < components.size(); ++i) {
- if (start + components.at(i).string.length() - 1 < cursor) {
- start += components.at(i).string.length() - 1;
- continue;
- }
- int xs = components.at(i).offset;
- if (rtl)
- xs = width - xs - components.at(i).width;
- QTextLayout layout(components.at(i).string, *components.at(i).font);
- layout.beginLayout();
- QTextLine l = layout.createLine();
- if (!l.isValid())
- return 0;
-
- l.setLineWidth(INT_MAX / 256);
- layout.endLayout();
-
- return xs + l.cursorToX(cursor - start + 1);
- }
- return width;
-}
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt,
- int h, int from, int to) const
-{
- Vector<TextRunComponent, 1024> components;
- int w = generateComponents(&components, *this, run);
-
- if (from == 0 && to == run.length())
- return FloatRect(pt.x(), pt.y(), w, h);
-
- float x1 = cursorToX(components, w, run.rtl(), from);
- float x2 = cursorToX(components, w, run.rtl(), to);
- if (x2 < x1)
- qSwap(x1, x2);
-
- return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
-}
-
-int Font::lineGap() const
-{
- return QFontMetrics(m_font).leading();
-}
-
-}
-
-#endif
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 57a481a..a095476 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -256,8 +256,8 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
setPaintingDisabled(!context);
if (context) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), DeviceColorSpace);
+ setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
}
}
@@ -639,24 +639,18 @@ void GraphicsContext::fillPath()
QPainterPath path = m_data->currentPath;
path.setFillRule(toQtFillRule(fillRule()));
- if ((m_common->state.fillColorSpace != SolidColorSpace)
- || (fillColor().alpha())) {
+ if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) {
drawFilledShadowPath(this, p, &path);
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- if (fillColor().alpha())
- p->fillPath(path, p->brush());
- break;
- case PatternColorSpace: {
+ if (m_common->state.fillPattern) {
TransformationMatrix affine;
p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- break;
- }
- case GradientColorSpace:
+ } else if (m_common->state.fillGradient) {
QBrush brush(*m_common->state.fillGradient->platformGradient());
brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
p->fillPath(path, brush);
- break;
+ } else {
+ if (fillColor().alpha())
+ p->fillPath(path, p->brush());
}
}
m_data->currentPath = QPainterPath();
@@ -672,8 +666,7 @@ void GraphicsContext::strokePath()
QPainterPath path = m_data->currentPath;
path.setFillRule(toQtFillRule(fillRule()));
- if ((m_common->state.strokeColorSpace != SolidColorSpace)
- || (strokeColor().alpha())) {
+ if (m_common->state.strokePattern || m_common->state.strokeGradient || strokeColor().alpha()) {
IntSize shadowSize;
int shadowBlur;
Color shadowColor;
@@ -685,26 +678,20 @@ void GraphicsContext::strokePath()
p->strokePath(path, shadowPen);
p->setWorldTransform(t);
}
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- if (strokeColor().alpha())
- p->strokePath(path, pen);
- break;
- case PatternColorSpace: {
+ if (m_common->state.strokePattern) {
TransformationMatrix affine;
pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
p->setPen(pen);
p->strokePath(path, pen);
- break;
- }
- case GradientColorSpace: {
+ } else if (m_common->state.strokeGradient) {
QBrush brush(*m_common->state.strokeGradient->platformGradient());
brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform());
pen.setBrush(brush);
p->setPen(pen);
p->strokePath(path, pen);
- break;
- }
+ } else {
+ if (strokeColor().alpha())
+ p->strokePath(path, pen);
}
}
m_data->currentPath = QPainterPath();
@@ -729,29 +716,23 @@ void GraphicsContext::fillRect(const FloatRect& rect)
QPainter* p = m_data->p();
- if ((m_common->state.fillColorSpace != SolidColorSpace)
- || (fillColor().alpha())) {
+ if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) {
drawBorderlessRectShadow(this, p, rect);
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- if (fillColor().alpha())
- p->fillRect(rect, p->brush());
- break;
- case PatternColorSpace: {
+ if (m_common->state.fillPattern) {
TransformationMatrix affine;
p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- break;
- }
- case GradientColorSpace:
+ } else if (m_common->state.fillGradient) {
QBrush brush(*m_common->state.fillGradient->platformGradient());
brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
p->fillRect(rect, brush);
- break;
+ } else {
+ if (fillColor().alpha())
+ p->fillRect(rect, p->brush());
}
}
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -762,7 +743,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
p->fillRect(rect, m_data->solidColor);
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled() || !color.alpha())
return;
@@ -886,7 +867,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
return FloatRect(QRectF(result));
}
-void GraphicsContext::setPlatformShadow(const IntSize& size, int, const Color&)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int, const Color&, ColorSpace)
{
// Qt doesn't support shadows natively, they are drawn manually in the draw*
// functions
@@ -1225,7 +1206,7 @@ void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
notImplemented();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1255,7 +1236,7 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
p->setPen(newPen);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp
index 98f4606..a9870fc 100644
--- a/WebCore/platform/graphics/qt/IconQt.cpp
+++ b/WebCore/platform/graphics/qt/IconQt.cpp
@@ -40,15 +40,17 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- RefPtr<Icon> i = adoptRef(new Icon);
- i->m_icon = QIcon(filename);
- return i.release();
-}
+ if (filenames.isEmpty())
+ return 0;
+
+ if (filenames.size() == 1) {
+ RefPtr<Icon> i = adoptRef(new Icon);
+ i->m_icon = QIcon(filenames[0]);
+ return i.release();
+ }
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
-{
//FIXME: Implement this
return 0;
}
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index f8403b7..b6823dd 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -145,16 +145,8 @@ RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
return &frame;
}
-void ImageDecoderQt::clearFrameBufferCache(size_t index)
+void ImageDecoderQt::clearFrameBufferCache(size_t /*index*/)
{
- // Currently QImageReader will be asked to read everything. This
- // might change when we read gif images on demand. For now we
- // can have a rather simple implementation.
- if (index > m_frameBufferCache.size())
- return;
-
- for (size_t i = 0; i < index; ++index)
- m_frameBufferCache[index].clear();
}
void ImageDecoderQt::internalDecodeSize()
diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp
index da6ddac..9a82911 100644
--- a/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -44,9 +44,7 @@
#include <QPainter>
#include <QImage>
#include <QImageReader>
-#if QT_VERSION >= 0x040300
#include <QTransform>
-#endif
#include <QDebug>
@@ -64,6 +62,8 @@ static QPixmap loadResourcePixmap(const char *name)
pixmap = QWebSettings::webGraphic(QWebSettings::DefaultFrameIconGraphic);
else if (qstrcmp(name, "textAreaResizeCorner") == 0)
pixmap = QWebSettings::webGraphic(QWebSettings::TextAreaSizeGripCornerGraphic);
+ else if (qstrcmp(name, "deleteButton") == 0)
+ pixmap = QWebSettings::webGraphic(QWebSettings::DeleteButtonGraphic);
return pixmap;
}
@@ -94,7 +94,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
}
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform,
- const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+ const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
{
QPixmap* framePixmap = nativeImageForCurrentFrame();
if (!framePixmap) // If it's too early we won't have an image yet.
@@ -120,6 +120,38 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
imageObserver()->didDraw(this);
}
+BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer)
+ : Image(observer)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(cAnimationNone)
+ , m_repetitionCountStatus(Unknown)
+ , m_repetitionsComplete(0)
+ , m_isSolidColor(false)
+ , m_checkedForSolidColor(false)
+ , m_animationFinished(true)
+ , m_allDataReceived(true)
+ , m_haveSize(true)
+ , m_sizeAvailable(true)
+ , m_decodedSize(0)
+ , m_haveFrameCount(true)
+ , m_frameCount(1)
+{
+ initPlatformData();
+
+ int width = pixmap->width();
+ int height = pixmap->height();
+ m_decodedSize = width * height * 4;
+ m_size = IntSize(width, height);
+
+ m_frames.grow(1);
+ m_frames[0].m_frame = pixmap;
+ m_frames[0].m_hasAlpha = pixmap->hasAlpha();
+ m_frames[0].m_haveMetadata = true;
+ checkForSolidColor();
+}
+
void BitmapImage::initPlatformData()
{
}
@@ -130,7 +162,7 @@ void BitmapImage::invalidatePlatformData()
// Drawing Routines
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
- const FloatRect& src, CompositeOperator op)
+ const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
startAnimation();
@@ -139,7 +171,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dst, solidColor(), op);
+ fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
return;
}
@@ -181,6 +213,13 @@ void BitmapImage::checkForSolidColor()
m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0));
}
+#if PLATFORM(WIN_OS)
+PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+ return BitmapImage::create(new QPixmap(QPixmap::fromWinHBITMAP(hBitmap)));
+}
+#endif
+
}
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index 7078d16..f446755 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -101,15 +101,15 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
foreach (QWidget* widget, qFindChildren<QWidget*>(m_videoWidget))
widget->installEventFilter(this);
- connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
- this, SLOT(stateChanged(Phonon::State, Phonon::State)));
+ connect(m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
+ this, SLOT(stateChanged(Phonon::State,Phonon::State)));
connect(m_mediaObject, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
connect(m_mediaObject, SIGNAL(seekableChanged(bool)), this, SLOT(seekableChanged(bool)));
connect(m_mediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasVideoChanged(bool)));
connect(m_mediaObject, SIGNAL(bufferStatus(int)), this, SLOT(bufferStatus(int)));
connect(m_mediaObject, SIGNAL(finished()), this, SLOT(finished()));
- connect(m_mediaObject, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)),
- this, SLOT(currentSourceChanged(const Phonon::MediaSource&)));
+ connect(m_mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
+ this, SLOT(currentSourceChanged(Phonon::MediaSource)));
connect(m_mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
connect(m_mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
}
diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp
index 95b3bc8..1db04a7 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.cpp
+++ b/WebCore/platform/graphics/qt/StillImageQt.cpp
@@ -50,7 +50,7 @@ NativeImagePtr StillImage::nativeImageForCurrentFrame()
}
void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
- const FloatRect& src, CompositeOperator op)
+ const FloatRect& src, ColorSpace, CompositeOperator op)
{
if (m_pixmap.isNull())
return;
diff --git a/WebCore/platform/graphics/qt/StillImageQt.h b/WebCore/platform/graphics/qt/StillImageQt.h
index 6c417b1..7be9136 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.h
+++ b/WebCore/platform/graphics/qt/StillImageQt.h
@@ -46,7 +46,7 @@ namespace WebCore {
virtual IntSize size() const;
virtual NativeImagePtr nativeImageForCurrentFrame();
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
private:
StillImage(const QPixmap& pixmap);
diff --git a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
index 5d85652..9fb6a8b 100644
--- a/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
+++ b/WebCore/platform/graphics/skia/BitmapImageSingleFrameSkia.h
@@ -72,7 +72,7 @@ public:
}
protected:
- virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator);
private:
NativeImageSkia m_nativeImage;
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 889c41b..f1536a6 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -293,7 +293,10 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
path.addOval(r, SkPath::kCW_Direction);
// only perform the inset if we won't invert r
if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
- r.inset(SkIntToScalar(thickness), SkIntToScalar(thickness));
+ // Adding one to the thickness doesn't make the border too thick as
+ // it's painted over afterwards. But without this adjustment the
+ // border appears a little anemic after anti-aliasing.
+ r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
path.addOval(r, SkPath::kCCW_Direction);
}
platformContext()->clipPathAntiAliased(path);
@@ -704,8 +707,6 @@ void GraphicsContext::fillPath()
return;
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.fillColorSpace;
-
path.setFillType(state.fillRule == RULE_EVENODD ?
SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
@@ -727,14 +728,13 @@ void GraphicsContext::fillRect(const FloatRect& rect)
}
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.fillColorSpace;
SkPaint paint;
platformContext()->setupPaintForFilling(&paint);
platformContext()->canvas()->drawRect(r, paint);
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -765,7 +765,8 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
const IntSize& topRight,
const IntSize& bottomLeft,
const IntSize& bottomRight,
- const Color& color)
+ const Color& color,
+ ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -782,7 +783,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect,
// Not all the radii fit, return a rect. This matches the behavior of
// Path::createRoundedRectangle. Without this we attempt to draw a round
// shadow for a square box.
- fillRect(rect, color);
+ fillRect(rect, color, colorSpace);
return;
}
@@ -950,7 +951,7 @@ void GraphicsContext::setMiterLimit(float limit)
platformContext()->setMiterLimit(limit);
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -977,7 +978,8 @@ void GraphicsContext::setPlatformFillPattern(Pattern* pattern)
void GraphicsContext::setPlatformShadow(const IntSize& size,
int blurInt,
- const Color& color)
+ const Color& color,
+ ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1019,7 +1021,7 @@ void GraphicsContext::setPlatformShadow(const IntSize& size,
dl->unref();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor)
+void GraphicsContext::setPlatformStrokeColor(const Color& strokecolor, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -1118,7 +1120,6 @@ void GraphicsContext::strokePath()
return;
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.strokeColorSpace;
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
@@ -1135,7 +1136,6 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
return;
const GraphicsContextState& state = m_common->state;
- ColorSpace colorSpace = state.strokeColorSpace;
SkPaint paint;
platformContext()->setupPaintForStroking(&paint, 0, 0);
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index a5c8926..c36f1ce 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -105,13 +105,16 @@ Image* ImageBuffer::image() const
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
{
const SkBitmap& bitmap = *context()->platformContext()->bitmap();
+ if (bitmap.isNull())
+ return;
+
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
SkAutoLockPixels bitmapLock(bitmap);
for (int y = 0; y < m_size.height(); ++y) {
uint32_t* srcRow = bitmap.getAddr32(0, y);
for (int x = 0; x < m_size.width(); ++x) {
SkColor color = SkPMColorToColor(srcRow[x]);
- srcRow[x] = SkPreMultiplyARGB(lookUpTable[SkColorGetA(color)],
+ srcRow[x] = SkPreMultiplyARGB(SkColorGetA(color),
lookUpTable[SkColorGetR(color)],
lookUpTable[SkColorGetG(color)],
lookUpTable[SkColorGetB(color)]);
@@ -164,11 +167,12 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const SkBitmap& bitmap,
for (int x = 0; x < numColumns; ++x) {
unsigned char* destPixel = &destRow[x * 4];
if (multiplied == Unmultiplied) {
- SkColor color = SkPMColorToColor(srcRow[x]);
- destPixel[0] = SkColorGetR(color);
- destPixel[1] = SkColorGetG(color);
- destPixel[2] = SkColorGetB(color);
- destPixel[3] = SkColorGetA(color);
+ SkColor color = srcRow[x];
+ unsigned a = SkColorGetA(color);
+ destPixel[0] = a ? SkColorGetR(color) * 255 / a : 0;
+ destPixel[1] = a ? SkColorGetG(color) * 255 / a : 0;
+ destPixel[2] = a ? SkColorGetB(color) * 255 / a : 0;
+ destPixel[3] = a;
} else {
// Input and output are both pre-multiplied, we just need to re-arrange the
// bytes from the bitmap format to RGBA.
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index ecab364..6d8ed22 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -302,6 +302,7 @@ void Image::drawPattern(GraphicsContext* context,
const FloatRect& floatSrcRect,
const TransformationMatrix& patternTransform,
const FloatPoint& phase,
+ ColorSpace styleColorSpace,
CompositeOperator compositeOp,
const FloatRect& destRect)
{
@@ -405,7 +406,7 @@ void BitmapImage::checkForSolidColor()
}
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
- const FloatRect& srcRect, CompositeOperator compositeOp)
+ const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp)
{
if (!m_source.initialized())
return;
@@ -437,6 +438,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt,
const FloatRect& dstRect,
const FloatRect& srcRect,
+ ColorSpace styleColorSpace,
CompositeOperator compositeOp)
{
FloatRect normDstRect = normalizeRect(dstRect);
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index a079da0..dfffa0d 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -343,6 +343,15 @@ void PlatformContextSkia::setupPaintForFilling(SkPaint* paint) const
paint->setShader(m_state->m_fillShader);
}
+static SkScalar scalarBound(SkScalar v, SkScalar min, SkScalar max)
+{
+ if (v < min)
+ return min;
+ if (v > max)
+ return max;
+ return v;
+}
+
float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, int length) const
{
setupPaintCommon(paint);
@@ -351,10 +360,13 @@ float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, i
paint->setColor(m_state->applyAlpha(m_state->m_strokeColor));
paint->setShader(m_state->m_strokeShader);
paint->setStyle(SkPaint::kStroke_Style);
- paint->setStrokeWidth(SkFloatToScalar(width));
+ // The limits here (512 and 256) were made up but are hopefully large
+ // enough to be reasonable. They are, empirically, small enough not to
+ // cause overflows in Skia.
+ paint->setStrokeWidth(scalarBound(SkFloatToScalar(width), 0, 512));
paint->setStrokeCap(m_state->m_lineCap);
paint->setStrokeJoin(m_state->m_lineJoin);
- paint->setStrokeMiter(SkFloatToScalar(m_state->m_miterLimit));
+ paint->setStrokeMiter(scalarBound(SkFloatToScalar(m_state->m_miterLimit), 0, 256));
if (m_state->m_dash)
paint->setPathEffect(m_state->m_dash);
diff --git a/WebCore/platform/graphics/transforms/TransformOperations.h b/WebCore/platform/graphics/transforms/TransformOperations.h
index dd56408..08efd23 100644
--- a/WebCore/platform/graphics/transforms/TransformOperations.h
+++ b/WebCore/platform/graphics/transforms/TransformOperations.h
@@ -31,7 +31,7 @@
namespace WebCore {
-class TransformOperations {
+class TransformOperations : public FastAllocBase {
public:
TransformOperations(bool makeIdentity = false);
diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h
index a7fbb3d..33f9afe 100644
--- a/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -29,6 +29,7 @@
#include "FloatPoint.h"
#include "IntPoint.h"
#include <string.h> //for memcpy
+#include <wtf/FastAllocBase.h>
#if PLATFORM(CG)
#include <CoreGraphics/CGAffineTransform.h>
@@ -49,7 +50,7 @@ class FloatPoint3D;
class FloatRect;
class FloatQuad;
-class TransformationMatrix {
+class TransformationMatrix : public FastAllocBase {
public:
typedef double Matrix4[4][4];
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index e2ed130..e901669 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -362,14 +362,14 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
graphicsContext->clearShadow();
Color fillColor = graphicsContext->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- graphicsContext->setFillColor(shadowFillColor);
+ graphicsContext->setFillColor(shadowFillColor, DeviceColorSpace);
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width(), point.y() + translation.height() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
- graphicsContext->setFillColor(fillColor);
+ graphicsContext->setFillColor(fillColor, DeviceColorSpace);
}
CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height());
@@ -380,7 +380,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
}
if (hasSimpleShadow)
- graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
+ graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace);
wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle);
}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 1923ecc..137b914 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -70,8 +70,8 @@ GraphicsContext::GraphicsContext(HDC hdc, bool hasAlpha)
setPaintingDisabled(!m_data->m_cgContext);
if (m_data->m_cgContext) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), DeviceColorSpace);
+ setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
}
}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index 2489e02..61ae76c 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -74,8 +74,8 @@ GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
if (m_data->cr) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), fillColorSpace());
+ setPlatformStrokeColor(strokeColor(), strokeColorSpace());
}
}
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
new file mode 100644
index 0000000..22faeb8
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayerCACF.h"
+
+#include "CString.h"
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "Image.h"
+#include "PlatformString.h"
+#include "SystemTime.h"
+#include "WKCACFLayer.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/StringExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t)
+{
+ toT3D.m11 = narrowPrecisionToFloat(t.m11());
+ toT3D.m12 = narrowPrecisionToFloat(t.m12());
+ toT3D.m13 = narrowPrecisionToFloat(t.m13());
+ toT3D.m14 = narrowPrecisionToFloat(t.m14());
+ toT3D.m21 = narrowPrecisionToFloat(t.m21());
+ toT3D.m22 = narrowPrecisionToFloat(t.m22());
+ toT3D.m23 = narrowPrecisionToFloat(t.m23());
+ toT3D.m24 = narrowPrecisionToFloat(t.m24());
+ toT3D.m31 = narrowPrecisionToFloat(t.m31());
+ toT3D.m32 = narrowPrecisionToFloat(t.m32());
+ toT3D.m33 = narrowPrecisionToFloat(t.m33());
+ toT3D.m34 = narrowPrecisionToFloat(t.m34());
+ toT3D.m41 = narrowPrecisionToFloat(t.m41());
+ toT3D.m42 = narrowPrecisionToFloat(t.m42());
+ toT3D.m43 = narrowPrecisionToFloat(t.m43());
+ toT3D.m44 = narrowPrecisionToFloat(t.m44());
+}
+
+TransformationMatrix CAToTransform3D(const CATransform3D& fromT3D)
+{
+ return TransformationMatrix(
+ fromT3D.m11,
+ fromT3D.m12,
+ fromT3D.m13,
+ fromT3D.m14,
+ fromT3D.m21,
+ fromT3D.m22,
+ fromT3D.m23,
+ fromT3D.m24,
+ fromT3D.m31,
+ fromT3D.m32,
+ fromT3D.m33,
+ fromT3D.m34,
+ fromT3D.m41,
+ fromT3D.m42,
+ fromT3D.m43,
+ fromT3D.m44);
+}
+
+static void setLayerBorderColor(WKCACFLayer* layer, const Color& color)
+{
+ CGColorRef borderColor = createCGColor(color);
+ layer->setBorderColor(borderColor);
+ CGColorRelease(borderColor);
+}
+
+static void clearBorderColor(WKCACFLayer* layer)
+{
+ layer->setBorderColor(0);
+}
+
+static void setLayerBackgroundColor(WKCACFLayer* layer, const Color& color)
+{
+ CGColorRef bgColor = createCGColor(color);
+ layer->setBackgroundColor(bgColor);
+ CGColorRelease(bgColor);
+}
+
+static void clearLayerBackgroundColor(WKCACFLayer* layer)
+{
+ layer->setBackgroundColor(0);
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
+{
+ return CompositingCoordinatesBottomUp;
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerCACF(client);
+}
+
+GraphicsLayerCACF::GraphicsLayerCACF(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+{
+ m_layer = WKCACFLayer::create(kCACFLayer, this);
+
+ updateDebugIndicators();
+}
+
+GraphicsLayerCACF::~GraphicsLayerCACF()
+{
+ // clean up the WK layer
+ if (m_layer)
+ m_layer->removeFromSuperlayer();
+
+ if (m_transformLayer)
+ m_transformLayer->removeFromSuperlayer();
+}
+
+void GraphicsLayerCACF::setName(const String& inName)
+{
+ String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
+ GraphicsLayer::setName(name);
+
+ m_layer->setName(inName);
+}
+
+NativeLayer GraphicsLayerCACF::nativeLayer() const
+{
+ return m_layer.get();
+}
+
+bool GraphicsLayerCACF::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which
+ // will end up calling updateSublayerList() N times.
+ if (childrenChanged)
+ updateSublayerList();
+
+ return childrenChanged;
+}
+
+void GraphicsLayerCACF::addChild(GraphicsLayer* childLayer)
+{
+ GraphicsLayer::addChild(childLayer);
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
+{
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ updateSublayerList();
+}
+
+bool GraphicsLayerCACF::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ updateSublayerList();
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerCACF::removeFromParent()
+{
+ GraphicsLayer::removeFromParent();
+ layerForSuperlayer()->removeFromSuperlayer();
+}
+
+void GraphicsLayerCACF::setPosition(const FloatPoint& point)
+{
+ GraphicsLayer::setPosition(point);
+ updateLayerPosition();
+}
+
+void GraphicsLayerCACF::setAnchorPoint(const FloatPoint3D& point)
+{
+ if (point == m_anchorPoint)
+ return;
+
+ GraphicsLayer::setAnchorPoint(point);
+ updateAnchorPoint();
+}
+
+void GraphicsLayerCACF::setSize(const FloatSize& size)
+{
+ if (size == m_size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ updateLayerSize();
+}
+
+void GraphicsLayerCACF::setTransform(const TransformationMatrix& t)
+{
+ if (t == m_transform)
+ return;
+
+ GraphicsLayer::setTransform(t);
+ updateTransform();
+}
+
+void GraphicsLayerCACF::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (t == m_childrenTransform)
+ return;
+
+ GraphicsLayer::setChildrenTransform(t);
+ updateChildrenTransform();
+}
+
+void GraphicsLayerCACF::setPreserves3D(bool preserves3D)
+{
+ if (preserves3D == m_preserves3D)
+ return;
+
+ GraphicsLayer::setPreserves3D(preserves3D);
+ updateLayerPreserves3D();
+}
+
+void GraphicsLayerCACF::setMasksToBounds(bool masksToBounds)
+{
+ if (masksToBounds == m_masksToBounds)
+ return;
+
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ updateMasksToBounds();
+}
+
+void GraphicsLayerCACF::setDrawsContent(bool drawsContent)
+{
+ if (drawsContent == m_drawsContent)
+ return;
+
+ GraphicsLayer::setDrawsContent(drawsContent);
+ updateLayerDrawsContent();
+}
+
+void GraphicsLayerCACF::setBackgroundColor(const Color& color)
+{
+ if (m_backgroundColorSet && m_backgroundColor == color)
+ return;
+
+ GraphicsLayer::setBackgroundColor(color);
+
+ m_contentsLayerHasBackgroundColor = true;
+ updateLayerBackgroundColor();
+}
+
+void GraphicsLayerCACF::clearBackgroundColor()
+{
+ if (!m_backgroundColorSet)
+ return;
+
+ GraphicsLayer::clearBackgroundColor();
+ clearLayerBackgroundColor(m_contentsLayer.get());
+}
+
+void GraphicsLayerCACF::setContentsOpaque(bool opaque)
+{
+ if (m_contentsOpaque == opaque)
+ return;
+
+ GraphicsLayer::setContentsOpaque(opaque);
+ updateContentsOpaque();
+}
+
+void GraphicsLayerCACF::setBackfaceVisibility(bool visible)
+{
+ if (m_backfaceVisibility == visible)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(visible);
+ updateBackfaceVisibility();
+}
+
+void GraphicsLayerCACF::setOpacity(float opacity)
+{
+ float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
+
+ if (m_opacity == clampedOpacity)
+ return;
+
+ GraphicsLayer::setOpacity(clampedOpacity);
+ primaryLayer()->setOpacity(opacity);
+}
+
+void GraphicsLayerCACF::setNeedsDisplay()
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay();
+}
+
+void GraphicsLayerCACF::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay(rect);
+}
+
+void GraphicsLayerCACF::setContentsRect(const IntRect& rect)
+{
+ if (rect == m_contentsRect)
+ return;
+
+ GraphicsLayer::setContentsRect(rect);
+ updateContentsRect();
+}
+
+void GraphicsLayerCACF::setContentsToImage(Image* image)
+{
+ bool childrenChanged = false;
+
+ if (image) {
+ m_pendingContentsImage = image->nativeImageForCurrentFrame();
+ m_contentsLayerPurpose = ContentsLayerForImage;
+ if (!m_contentsLayer)
+ childrenChanged = true;
+ } else {
+ m_pendingContentsImage = 0;
+ m_contentsLayerPurpose = NoContentsLayer;
+ if (m_contentsLayer)
+ childrenChanged = true;
+ }
+
+ updateContentsImage();
+
+ // This has to happen after updateContentsImage
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::setContentsToVideo(PlatformLayer* videoLayer)
+{
+ bool childrenChanged = false;
+
+ if (videoLayer != m_contentsLayer.get())
+ childrenChanged = true;
+
+ m_contentsLayer = videoLayer;
+ m_contentsLayerPurpose = videoLayer ? ContentsLayerForVideo : NoContentsLayer;
+
+ updateContentsVideo();
+
+ // This has to happen after updateContentsVideo
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+void GraphicsLayerCACF::setGeometryOrientation(CompositingCoordinatesOrientation orientation)
+{
+ if (orientation == m_geometryOrientation)
+ return;
+
+ GraphicsLayer::setGeometryOrientation(orientation);
+ updateGeometryOrientation();
+}
+
+PlatformLayer* GraphicsLayerCACF::hostLayerForSublayers() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerCACF::layerForSuperlayer() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerCACF::platformLayer() const
+{
+ return primaryLayer();
+}
+
+void GraphicsLayerCACF::setDebugBackgroundColor(const Color& color)
+{
+ if (color.isValid())
+ setLayerBackgroundColor(m_layer.get(), color);
+ else
+ clearLayerBackgroundColor(m_layer.get());
+}
+
+void GraphicsLayerCACF::setDebugBorder(const Color& color, float borderWidth)
+{
+ if (color.isValid()) {
+ setLayerBorderColor(m_layer.get(), color);
+ m_layer->setBorderWidth(borderWidth);
+ } else {
+ clearBorderColor(m_layer.get());
+ m_layer->setBorderWidth(0);
+ }
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCACF::defaultContentsOrientation() const
+{
+ return CompositingCoordinatesTopDown;
+}
+
+void GraphicsLayerCACF::updateSublayerList()
+{
+ Vector<RefPtr<WKCACFLayer> > newSublayers;
+
+ if (m_transformLayer) {
+ // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
+ newSublayers.append(m_layer.get());
+ } else if (m_contentsLayer) {
+ // FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
+ newSublayers.append(m_contentsLayer.get());
+ }
+
+ const Vector<GraphicsLayer*>& childLayers = children();
+ size_t numChildren = childLayers.size();
+ for (size_t i = 0; i < numChildren; ++i) {
+ GraphicsLayerCACF* curChild = static_cast<GraphicsLayerCACF*>(childLayers[i]);
+
+ WKCACFLayer* childLayer = curChild->layerForSuperlayer();
+ newSublayers.append(childLayer);
+ }
+
+ for (int i = 0; i < newSublayers.size(); ++i)
+ newSublayers[i]->removeFromSuperlayer();
+
+ if (m_transformLayer) {
+ m_transformLayer->setSublayers(newSublayers);
+
+ if (m_contentsLayer) {
+ // If we have a transform layer, then the contents layer is parented in the
+ // primary layer (which is itself a child of the transform layer).
+ m_layer->removeAllSublayers();
+ m_layer->addSublayer(m_contentsLayer);
+ }
+ } else
+ m_layer->setSublayers(newSublayers);
+}
+
+void GraphicsLayerCACF::updateLayerPosition()
+{
+ // Position is offset on the layer by the layer anchor point.
+ CGPoint posPoint = CGPointMake(m_position.x() + m_anchorPoint.x() * m_size.width(),
+ m_position.y() + m_anchorPoint.y() * m_size.height());
+
+ primaryLayer()->setPosition(posPoint);
+}
+
+void GraphicsLayerCACF::updateLayerSize()
+{
+ CGRect rect = CGRectMake(0, 0, m_size.width(), m_size.height());
+ if (m_transformLayer) {
+ m_transformLayer->setBounds(rect);
+ // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
+ CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
+ m_layer->setPosition(centerPoint);
+ }
+
+ m_layer->setBounds(rect);
+
+ // Note that we don't resize m_contentsLayer. It's up the caller to do that.
+
+ // if we've changed the bounds, we need to recalculate the position
+ // of the layer, taking anchor point into account.
+ updateLayerPosition();
+}
+
+void GraphicsLayerCACF::updateAnchorPoint()
+{
+ primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
+ primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
+ updateLayerPosition();
+}
+
+void GraphicsLayerCACF::updateTransform()
+{
+ CATransform3D transform;
+ copyTransform(transform, m_transform);
+ primaryLayer()->setTransform(transform);
+}
+
+void GraphicsLayerCACF::updateChildrenTransform()
+{
+ CATransform3D transform;
+ copyTransform(transform, m_childrenTransform);
+ primaryLayer()->setSublayerTransform(transform);
+}
+
+void GraphicsLayerCACF::updateMasksToBounds()
+{
+ m_layer->setMasksToBounds(m_masksToBounds);
+ updateDebugIndicators();
+}
+
+void GraphicsLayerCACF::updateContentsOpaque()
+{
+ m_layer->setOpaque(m_contentsOpaque);
+}
+
+void GraphicsLayerCACF::updateBackfaceVisibility()
+{
+ m_layer->setDoubleSided(m_backfaceVisibility);
+}
+
+void GraphicsLayerCACF::updateLayerPreserves3D()
+{
+ if (m_preserves3D && !m_transformLayer) {
+ // Create the transform layer.
+ m_transformLayer = WKCACFLayer::create(kCACFTransformLayer, this);
+
+#ifndef NDEBUG
+ m_transformLayer->setName(String().format("Transform Layer CATransformLayer(%p) GraphicsLayer(%p)", m_transformLayer.get(), this));
+#endif
+ // Copy the position from this layer.
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
+ m_layer->setPosition(point);
+
+ m_layer->setAnchorPoint(CGPointMake(0.5f, 0.5f));
+ m_layer->setTransform(CATransform3DIdentity);
+
+ // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
+ m_layer->setOpacity(1);
+
+ // Move this layer to be a child of the transform layer.
+ if (m_layer->superlayer())
+ m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get());
+ m_transformLayer->addSublayer(m_layer.get());
+
+ updateSublayerList();
+ } else if (!m_preserves3D && m_transformLayer) {
+ // Relace the transformLayer in the parent with this layer.
+ m_layer->removeFromSuperlayer();
+ m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get());
+
+ // Release the transform layer.
+ m_transformLayer = 0;
+
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ updateSublayerList();
+ }
+
+ updateOpacityOnLayer();
+}
+
+void GraphicsLayerCACF::updateLayerDrawsContent()
+{
+ if (m_drawsContent)
+ m_layer->setNeedsDisplay();
+ else
+ m_layer->setContents(nil);
+
+ updateDebugIndicators();
+}
+
+void GraphicsLayerCACF::updateLayerBackgroundColor()
+{
+ if (!m_contentsLayer)
+ return;
+
+ // We never create the contents layer just for background color yet.
+ if (m_backgroundColorSet)
+ setLayerBackgroundColor(m_contentsLayer.get(), m_backgroundColor);
+ else
+ clearLayerBackgroundColor(m_contentsLayer.get());
+}
+
+void GraphicsLayerCACF::updateContentsImage()
+{
+ if (m_pendingContentsImage) {
+ if (!m_contentsLayer.get()) {
+ RefPtr<WKCACFLayer> imageLayer = WKCACFLayer::create(kCACFLayer, this);
+#ifndef NDEBUG
+ imageLayer->setName("Image Layer");
+#endif
+ setupContentsLayer(imageLayer.get());
+ m_contentsLayer = imageLayer;
+ // m_contentsLayer will be parented by updateSublayerList
+ }
+
+ // FIXME: maybe only do trilinear if the image is being scaled down,
+ // but then what if the layer size changes?
+ m_contentsLayer->setMinificationFilter(kCACFFilterTrilinear);
+ m_contentsLayer->setContents(m_pendingContentsImage.get());
+ m_pendingContentsImage = 0;
+
+ updateContentsRect();
+ } else {
+ // No image.
+ // m_contentsLayer will be removed via updateSublayerList.
+ m_contentsLayer = 0;
+ }
+}
+
+void GraphicsLayerCACF::updateContentsVideo()
+{
+ // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ updateContentsRect();
+ }
+}
+
+void GraphicsLayerCACF::updateContentsRect()
+{
+ if (!m_contentsLayer)
+ return;
+
+ CGPoint point = CGPointMake(m_contentsRect.x(),
+ m_contentsRect.y());
+ CGRect rect = CGRectMake(0.0f,
+ 0.0f,
+ m_contentsRect.width(),
+ m_contentsRect.height());
+
+ m_contentsLayer->setPosition(point);
+ m_contentsLayer->setBounds(rect);
+}
+
+void GraphicsLayerCACF::updateGeometryOrientation()
+{
+ switch (geometryOrientation()) {
+ case CompositingCoordinatesTopDown:
+ m_layer->setGeometryFlipped(false);
+ break;
+
+ case CompositingCoordinatesBottomUp:
+ m_layer->setGeometryFlipped(true);
+ break;
+ }
+ // Geometry orientation is mapped onto children transform in older QuartzCores,
+ // so is handled via setGeometryOrientation().
+}
+
+void GraphicsLayerCACF::setupContentsLayer(WKCACFLayer* contentsLayer)
+{
+ if (contentsLayer == m_contentsLayer)
+ return;
+
+ if (m_contentsLayer) {
+ m_contentsLayer->removeFromSuperlayer();
+ m_contentsLayer = 0;
+ }
+
+ if (contentsLayer) {
+ m_contentsLayer = contentsLayer;
+
+ if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
+ CATransform3D flipper = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ m_contentsLayer->setTransform(flipper);
+ m_contentsLayer->setAnchorPoint(CGPointMake(0.0f, 1.0f));
+ } else
+ m_contentsLayer->setAnchorPoint(CGPointMake(0.0f, 0.0f));
+
+ // Insert the content layer first. Video elements require this, because they have
+ // shadow content that must display in front of the video.
+ m_layer->insertSublayer(m_contentsLayer.get(), 0);
+
+ updateContentsRect();
+
+ if (showDebugBorders()) {
+ setLayerBorderColor(m_contentsLayer.get(), Color(0, 0, 128, 180));
+ m_contentsLayer->setBorderWidth(1.0f);
+ }
+ }
+ updateDebugIndicators();
+}
+
+// This function simply mimics the operation of GraphicsLayerCA
+void GraphicsLayerCACF::updateOpacityOnLayer()
+{
+ primaryLayer()->setOpacity(m_opacity);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
new file mode 100644
index 0000000..93ddf25
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GraphicsLayerCACF_h_
+#define GraphicsLayerCACF_h_
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayer.h"
+#include "GraphicsContext.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+class WKCACFLayer;
+
+class GraphicsLayerCACF : public GraphicsLayer {
+public:
+
+ GraphicsLayerCACF(GraphicsLayerClient*);
+ virtual ~GraphicsLayerCACF();
+
+ virtual void setName(const String& inName);
+
+ // for hosting this GraphicsLayer in a native layer hierarchy
+ virtual NativeLayer nativeLayer() const;
+
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer *layer);
+ virtual void addChildAtIndex(GraphicsLayer *layer, int index);
+ virtual void addChildAbove(GraphicsLayer *layer, GraphicsLayer *sibling);
+ virtual void addChildBelow(GraphicsLayer *layer, GraphicsLayer *sibling);
+ virtual bool replaceChild(GraphicsLayer *oldChild, GraphicsLayer *newChild);
+
+ virtual void removeFromParent();
+
+ virtual void setPosition(const FloatPoint& inPoint);
+ virtual void setAnchorPoint(const FloatPoint3D& inPoint);
+ virtual void setSize(const FloatSize& inSize);
+
+ virtual void setTransform(const TransformationMatrix&);
+
+ virtual void setChildrenTransform(const TransformationMatrix&);
+
+ virtual void setPreserves3D(bool);
+ virtual void setMasksToBounds(bool);
+ virtual void setDrawsContent(bool);
+
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+
+ virtual void setContentsOpaque(bool);
+ virtual void setBackfaceVisibility(bool);
+
+ virtual void setOpacity(float opacity);
+
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+
+ virtual void setContentsRect(const IntRect&);
+
+ virtual void setContentsToImage(Image*);
+ virtual void setContentsToVideo(PlatformLayer*);
+
+ virtual PlatformLayer* platformLayer() const;
+
+ virtual void setDebugBackgroundColor(const Color&);
+ virtual void setDebugBorder(const Color&, float borderWidth);
+
+ virtual void setGeometryOrientation(CompositingCoordinatesOrientation);
+
+ void notifySyncRequired() { if (m_client) m_client->notifySyncRequired(this); }
+
+private:
+ void updateOpacityOnLayer();
+
+ WKCACFLayer* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); }
+ WKCACFLayer* hostLayerForSublayers() const;
+ WKCACFLayer* layerForSuperlayer() const;
+
+ CompositingCoordinatesOrientation defaultContentsOrientation() const;
+ void updateSublayerList();
+ void updateLayerPosition();
+ void updateLayerSize();
+ void updateAnchorPoint();
+ void updateTransform();
+ void updateChildrenTransform();
+ void updateMasksToBounds();
+ void updateContentsOpaque();
+ void updateBackfaceVisibility();
+ void updateLayerPreserves3D();
+ void updateLayerDrawsContent();
+ void updateLayerBackgroundColor();
+
+ void updateContentsImage();
+ void updateContentsVideo();
+ void updateContentsRect();
+ void updateGeometryOrientation();
+
+ void setupContentsLayer(WKCACFLayer*);
+ WKCACFLayer* contentsLayer() const { return m_contentsLayer.get(); }
+
+ RefPtr<WKCACFLayer> m_layer;
+ RefPtr<WKCACFLayer> m_transformLayer;
+ RefPtr<WKCACFLayer> m_contentsLayer;
+
+ enum ContentsLayerPurpose {
+ NoContentsLayer = 0,
+ ContentsLayerForImage,
+ ContentsLayerForVideo
+ };
+
+ ContentsLayerPurpose m_contentsLayerPurpose;
+ bool m_contentsLayerHasBackgroundColor : 1;
+ RetainPtr<CGImageRef> m_pendingContentsImage;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // GraphicsLayerCACF_h_
diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp
index 61f1fd3..d71ca00 100644
--- a/WebCore/platform/graphics/win/IconWin.cpp
+++ b/WebCore/platform/graphics/win/IconWin.cpp
@@ -47,20 +47,22 @@ Icon::~Icon()
DestroyIcon(m_hIcon);
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
- SHFILEINFO sfi;
- memset(&sfi, 0, sizeof(sfi));
-
- String tmpFilename = filename;
- if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON))
+ if (filenames.isEmpty())
return 0;
- return adoptRef(new Icon(sfi.hIcon));
-}
+ if (filenames.size() == 1) {
+ SHFILEINFO sfi;
+ memset(&sfi, 0, sizeof(sfi));
+
+ String tmpFilename = filenames[0];
+ if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON))
+ return 0;
+
+ return adoptRef(new Icon(sfi.hIcon));
+ }
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
-{
#if PLATFORM(WINCE)
return 0;
#else
diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp
index 285fb71..2c6d41d 100644
--- a/WebCore/platform/graphics/win/ImageCGWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCGWin.cpp
@@ -77,9 +77,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
else
- draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
// Do cleanup
CGContextRelease(cgContext);
@@ -88,7 +88,7 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
return true;
}
-void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
size_t frames = frameCount();
for (size_t i = 0; i < frames; ++i) {
@@ -96,7 +96,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
if (CGImageGetHeight(image) == static_cast<size_t>(srcSize.height()) && CGImageGetWidth(image) == static_cast<size_t>(srcSize.width())) {
size_t currentFrame = m_currentFrame;
m_currentFrame = i;
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), styleColorSpace, compositeOp);
m_currentFrame = currentFrame;
return;
}
@@ -104,7 +104,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
// No image of the correct size was found, fallback to drawing the current frame
IntSize imageSize = BitmapImage::size();
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), styleColorSpace, compositeOp);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/ImageCairoWin.cpp b/WebCore/platform/graphics/win/ImageCairoWin.cpp
index 0b27438..e3c5ea0 100644
--- a/WebCore/platform/graphics/win/ImageCairoWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCairoWin.cpp
@@ -82,9 +82,9 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
IntSize imageSize = BitmapImage::size();
if (size)
- drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), CompositeCopy);
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), DeviceColorSpace, CompositeCopy);
else
- draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, CompositeCopy);
// Do cleanup
cairo_destroy(targetRef);
@@ -92,7 +92,7 @@ bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
return true;
}
-void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
size_t frames = frameCount();
for (size_t i = 0; i < frames; ++i) {
@@ -100,7 +100,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
if (cairo_image_surface_get_height(image) == static_cast<size_t>(srcSize.height()) && cairo_image_surface_get_width(image) == static_cast<size_t>(srcSize.width())) {
size_t currentFrame = m_currentFrame;
m_currentFrame = i;
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), DeviceColorSpace, compositeOp);
m_currentFrame = currentFrame;
return;
}
@@ -108,7 +108,7 @@ void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const Float
// No image of the correct size was found, fallback to drawing the current frame
IntSize imageSize = BitmapImage::size();
- draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp);
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), DeviceColorSpace, compositeOp);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/IntPointWin.cpp b/WebCore/platform/graphics/win/IntPointWin.cpp
index a6ce0bb..73db199 100644
--- a/WebCore/platform/graphics/win/IntPointWin.cpp
+++ b/WebCore/platform/graphics/win/IntPointWin.cpp
@@ -23,6 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "IntPoint.h"
#include <windows.h>
diff --git a/WebCore/platform/graphics/win/IntRectWin.cpp b/WebCore/platform/graphics/win/IntRectWin.cpp
index 6228be8..fe25a7f 100644
--- a/WebCore/platform/graphics/win/IntRectWin.cpp
+++ b/WebCore/platform/graphics/win/IntRectWin.cpp
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
@@ -23,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "IntRect.h"
#include <windows.h>
diff --git a/WebCore/platform/graphics/win/IntSizeWin.cpp b/WebCore/platform/graphics/win/IntSizeWin.cpp
index 8a27cdb..26e68da 100644
--- a/WebCore/platform/graphics/win/IntSizeWin.cpp
+++ b/WebCore/platform/graphics/win/IntSizeWin.cpp
@@ -23,6 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
#include "IntSize.h"
#include <windows.h>
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index 15e1001..a5beea1 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -318,6 +318,20 @@ void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch)
m_qtMovie->setPreservesPitch(preservesPitch);
}
+bool MediaPlayerPrivate::hasClosedCaptions() const
+{
+ if (!m_qtMovie)
+ return false;
+ return m_qtMovie->hasClosedCaptions();
+}
+
+void MediaPlayerPrivate::setClosedCaptionsVisible(bool visible)
+{
+ if (!m_qtMovie)
+ return;
+ m_qtMovie->setClosedCaptionsVisible(visible);
+}
+
int MediaPlayerPrivate::dataRate() const
{
// This is not used at the moment
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
index 4a3a28e..2bccbbf 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -49,7 +49,10 @@ public:
static void registerMediaEngine(MediaEngineRegistrar);
~MediaPlayerPrivate();
-
+
+private:
+ MediaPlayerPrivate(MediaPlayer*);
+
IntSize naturalSize() const;
bool hasVideo() const;
bool hasAudio() const;
@@ -93,8 +96,8 @@ public:
bool hasSingleSecurityOrigin() const;
-private:
- MediaPlayerPrivate(MediaPlayer*);
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool);
void updateStates();
void doSeek();
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
index 56f3d0b..2d4c2ea 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.cpp
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -45,6 +45,12 @@ using namespace std;
static const long minimumQuickTimeVersion = 0x07300000; // 7.3
+static const long closedCaptionTrackType = 'clcp';
+static const long subTitleTrackType = 'sbtl';
+static const long mpeg4ObjectDescriptionTrackType = 'odsm';
+static const long mpeg4SceneDescriptionTrackType = 'sdsm';
+static const long closedCaptionDisplayPropertyID = 'disp';
+
// Resizing GWorlds is slow, give them a minimum size so size of small
// videos can be animated smoothly
static const int cGWorldMinWidth = 640;
@@ -757,10 +763,10 @@ void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount, unsigned&
allowedTrackTypes->add(SoundMediaType);
allowedTrackTypes->add(TextMediaType);
allowedTrackTypes->add(BaseMediaType);
- allowedTrackTypes->add('clcp'); // Closed caption
- allowedTrackTypes->add('sbtl'); // Subtitle
- allowedTrackTypes->add('odsm'); // MPEG-4 object descriptor stream
- allowedTrackTypes->add('sdsm'); // MPEG-4 scene description stream
+ allowedTrackTypes->add(closedCaptionTrackType);
+ allowedTrackTypes->add(subTitleTrackType);
+ allowedTrackTypes->add(mpeg4ObjectDescriptionTrackType);
+ allowedTrackTypes->add(mpeg4SceneDescriptionTrackType);
allowedTrackTypes->add(TimeCodeMediaType);
allowedTrackTypes->add(TimeCode64MediaType);
}
@@ -877,6 +883,27 @@ bool QTMovieWin::hasAudio() const
return (GetMovieIndTrackType(m_private->m_movie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
}
+
+bool QTMovieWin::hasClosedCaptions() const
+{
+ if (!m_private->m_movie)
+ return false;
+ return GetMovieIndTrackType(m_private->m_movie, 1, closedCaptionTrackType, movieTrackMediaType);
+}
+
+void QTMovieWin::setClosedCaptionsVisible(bool visible)
+{
+ if (!m_private->m_movie)
+ return;
+
+ Track ccTrack = GetMovieIndTrackType(m_private->m_movie, 1, closedCaptionTrackType, movieTrackMediaType);
+ if (!ccTrack)
+ return;
+
+ Boolean doDisplay = visible;
+ QTSetTrackProperty(ccTrack, closedCaptionTrackType, closedCaptionDisplayPropertyID, sizeof(doDisplay), &doDisplay);
+}
+
pascal OSErr movieDrawingCompleteProc(Movie movie, long data)
{
UppParam param;
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
index d178eb8..778f9aa 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.h
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -98,6 +98,9 @@ public:
bool hasVideo() const;
bool hasAudio() const;
+ bool hasClosedCaptions() const;
+ void setClosedCaptionsVisible(bool);
+
static unsigned countSupportedTypes();
static void getSupportedType(unsigned index, const UChar*& str, unsigned& len);
diff --git a/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
new file mode 100644
index 0000000..e97b530
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFContextFlusher.h"
+
+#include <wtf/StdLibExtras.h>
+#include <QuartzCore/CACFContext.h>
+
+namespace WebCore {
+
+WKCACFContextFlusher& WKCACFContextFlusher::shared()
+{
+ DEFINE_STATIC_LOCAL(WKCACFContextFlusher, flusher, ());
+ return flusher;
+}
+
+WKCACFContextFlusher::WKCACFContextFlusher()
+{
+}
+
+WKCACFContextFlusher::~WKCACFContextFlusher()
+{
+}
+
+void WKCACFContextFlusher::addContext(CACFContextRef context)
+{
+ ASSERT(context);
+
+ m_contexts.add(context);
+ CFRetain(context);
+}
+
+void WKCACFContextFlusher::removeContext(CACFContextRef context)
+{
+ ASSERT(context);
+
+ ContextSet::iterator found = m_contexts.find(context);
+ if (found == m_contexts.end())
+ return;
+
+ CFRelease(*found);
+ m_contexts.remove(found);
+}
+
+void WKCACFContextFlusher::flushAllContexts()
+{
+ // addContext might get called beneath CACFContextFlush, and we don't want m_contexts to change while
+ // we're iterating over it, so we move the contexts into a local ContextSet and iterate over that instead.
+ ContextSet contextsToFlush;
+ contextsToFlush.swap(m_contexts);
+
+ ContextSet::const_iterator end = contextsToFlush.end();
+ for (ContextSet::const_iterator it = contextsToFlush.begin(); it != end; ++it) {
+ CACFContextRef context = *it;
+ CACFContextFlush(context);
+ CFRelease(context);
+ }
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WKCACFContextFlusher.h b/WebCore/platform/graphics/win/WKCACFContextFlusher.h
new file mode 100644
index 0000000..9ce76aa
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WKCACFContextFlusher_h
+#define WKCACFContextFlusher_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <wtf/Noncopyable.h>
+
+#include <wtf/HashSet.h>
+
+typedef struct _CACFContext* CACFContextRef;
+
+namespace WebCore {
+
+class WKCACFContextFlusher : public Noncopyable {
+public:
+ static WKCACFContextFlusher& shared();
+
+ void addContext(CACFContextRef);
+ void removeContext(CACFContextRef);
+
+ void flushAllContexts();
+
+private:
+ WKCACFContextFlusher();
+ ~WKCACFContextFlusher();
+
+ typedef HashSet<CACFContextRef> ContextSet;
+ ContextSet m_contexts;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFContextFlusher_h
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp
new file mode 100644
index 0000000..21e010d
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFLayer.h"
+
+#include "WKCACFContextFlusher.h"
+
+#include <stdio.h>
+#include <QuartzCore/CACFContext.h>
+#include <QuartzCore/CARender.h>
+
+#pragma comment(lib, "QuartzCore")
+
+namespace WebCore {
+
+using namespace std;
+
+static void displayInContext(CACFLayerRef layer, CGContextRef context)
+{
+ ASSERT_ARG(layer, WKCACFLayer::layer(layer));
+ WKCACFLayer::layer(layer)->display(context);
+}
+
+// FIXME: It might be good to have a way of ensuring that all WKCACFLayers eventually
+// get destroyed in debug builds. A static counter could accomplish this pretty easily.
+
+WKCACFLayer::WKCACFLayer(CFStringRef className, GraphicsLayerCACF* owner)
+ : m_layer(AdoptCF, CACFLayerCreate(className))
+ , m_needsDisplayOnBoundsChange(false)
+ , m_owner(owner)
+{
+ CACFLayerSetUserData(layer(), this);
+ CACFLayerSetDisplayCallback(layer(), displayInContext);
+}
+
+WKCACFLayer::~WKCACFLayer()
+{
+ // Our superlayer should be holding a reference to us, so there should be no way for us to be destroyed while we still have a superlayer.
+ ASSERT(!superlayer());
+
+ CACFLayerSetUserData(layer(), 0);
+ CACFLayerSetDisplayCallback(layer(), 0);
+}
+
+void WKCACFLayer::display(PlatformGraphicsContext* context)
+{
+ if (!m_owner)
+ return;
+
+ CGContextSaveGState(context);
+
+ CGRect layerBounds = bounds();
+ if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
+ CGContextScaleCTM(context, 1, -1);
+ CGContextTranslateCTM(context, 0, -layerBounds.size.height);
+ }
+
+ if (m_owner->client()) {
+ GraphicsContext graphicsContext(context);
+
+ // It's important to get the clip from the context, because it may be significantly
+ // smaller than the layer bounds (e.g. tiled layers)
+ CGRect clipBounds = CGContextGetClipBoundingBox(context);
+ IntRect clip(enclosingIntRect(clipBounds));
+ m_owner->paintGraphicsLayerContents(graphicsContext, clip);
+ }
+#ifndef NDEBUG
+ else {
+ ASSERT_NOT_REACHED();
+
+ // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color,
+ // so CA never makes backing store for it (which is what -setNeedsDisplay will do above).
+ CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f);
+ CGContextFillRect(context, layerBounds);
+ }
+#endif
+
+ if (m_owner->showRepaintCounter()) {
+ char text[16]; // that's a lot of repaints
+ _snprintf(text, sizeof(text), "%d", m_owner->incrementRepaintCount());
+
+ CGContextSaveGState(context);
+ CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
+
+ CGRect aBounds = layerBounds;
+
+ aBounds.size.width = 10 + 12 * strlen(text);
+ aBounds.size.height = 25;
+ CGContextFillRect(context, aBounds);
+
+ CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f);
+
+ CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f));
+ CGContextSelectFont(context, "Helvetica", 25, kCGEncodingMacRoman);
+ CGContextShowTextAtPoint(context, aBounds.origin.x + 3.0f, aBounds.origin.y + 20.0f, text, strlen(text));
+
+ CGContextRestoreGState(context);
+ }
+
+ CGContextRestoreGState(context);
+}
+
+void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context)
+{
+ CACFContextSetLayer(context, layer());
+ setNeedsCommit();
+}
+
+void WKCACFLayer::setNeedsCommit()
+{
+ CACFContextRef context = CACFLayerGetContext(rootLayer()->layer());
+
+ // The context might now be set yet. This happens if a property gets set
+ // before placing the layer in the tree. In this case we don't need to
+ // worry about remembering the context because we will when the layer is
+ // added to the tree.
+ if (context)
+ WKCACFContextFlusher::shared().addContext(context);
+
+ // Call notifySyncRequired(), which in this implementation plumbs through to
+ // call setRootLayerNeedsDisplay() on the WebView, which causes the CACFRenderer
+ // to render a frame.
+ if (m_owner)
+ m_owner->notifySyncRequired();
+}
+
+void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
+{
+ insertSublayer(sublayer, numSublayers());
+}
+
+void WKCACFLayer::insertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
+{
+ index = min(index, numSublayers());
+ CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
+ setNeedsCommit();
+}
+
+void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
+{
+ if (!reference) {
+ insertSublayer(sublayer, 0);
+ return;
+ }
+
+ int referenceIndex = indexOfSublayer(reference);
+ if (referenceIndex == -1) {
+ addSublayer(sublayer);
+ return;
+ }
+
+ insertSublayer(sublayer, referenceIndex + 1);
+}
+
+void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
+{
+ if (!reference) {
+ insertSublayer(sublayer, 0);
+ return;
+ }
+
+ int referenceIndex = indexOfSublayer(reference);
+ if (referenceIndex == -1) {
+ addSublayer(sublayer);
+ return;
+ }
+
+ insertSublayer(sublayer, referenceIndex);
+}
+
+void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer> newLayer)
+{
+ ASSERT_ARG(reference, reference);
+ ASSERT_ARG(reference, reference->superlayer() == this);
+
+ if (reference == newLayer)
+ return;
+
+ if (!newLayer) {
+ removeSublayer(reference);
+ return;
+ }
+
+ newLayer->removeFromSuperlayer();
+
+ int referenceIndex = indexOfSublayer(reference);
+ ASSERT(referenceIndex != -1);
+ if (referenceIndex == -1)
+ return;
+
+ // FIXME: Can we make this more efficient? The current CACF API doesn't seem to give us a way to do so.
+ reference->removeFromSuperlayer();
+ insertSublayer(newLayer, referenceIndex);
+}
+
+void WKCACFLayer::removeFromSuperlayer()
+{
+ WKCACFLayer* superlayer = this->superlayer();
+ if (!superlayer)
+ return;
+
+ superlayer->removeSublayer(this);
+ CACFLayerRemoveFromSuperlayer(layer());
+ superlayer->setNeedsCommit();
+}
+
+void WKCACFLayer::removeSublayer(const WKCACFLayer* sublayer)
+{
+ int foundIndex = indexOfSublayer(sublayer);
+ if (foundIndex == -1)
+ return;
+
+ CACFLayerRemoveFromSuperlayer(sublayer->layer());
+ setNeedsCommit();
+}
+
+int WKCACFLayer::indexOfSublayer(const WKCACFLayer* reference)
+{
+ CACFLayerRef ref = reference->layer();
+ if (!ref)
+ return -1;
+
+ CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+ size_t n = CFArrayGetCount(sublayers);
+
+ for (size_t i = 0; i < n; ++i)
+ if (CFArrayGetValueAtIndex(sublayers, i) == ref)
+ return i;
+
+ return -1;
+}
+
+WKCACFLayer* WKCACFLayer::ancestorOrSelfWithSuperlayer(WKCACFLayer* superlayer) const
+{
+ WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
+ for (WKCACFLayer* ancestor = this->superlayer(); ancestor; layer = ancestor, ancestor = ancestor->superlayer()) {
+ if (ancestor == superlayer)
+ return layer;
+ }
+ return 0;
+}
+
+void WKCACFLayer::setBounds(const CGRect& rect)
+{
+ if (CGRectEqualToRect(rect, bounds()))
+ return;
+
+ CACFLayerSetBounds(layer(), rect);
+ setNeedsCommit();
+
+ if (m_needsDisplayOnBoundsChange)
+ setNeedsDisplay();
+}
+
+void WKCACFLayer::setFrame(const CGRect& rect)
+{
+ CGRect oldFrame = frame();
+ if (CGRectEqualToRect(rect, oldFrame))
+ return;
+
+ CACFLayerSetFrame(layer(), rect);
+ setNeedsCommit();
+
+ if (m_needsDisplayOnBoundsChange)
+ setNeedsDisplay();
+}
+
+WKCACFLayer* WKCACFLayer::rootLayer() const
+{
+ WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
+ for (WKCACFLayer* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
+ return layer;
+}
+
+void WKCACFLayer::removeAllSublayers()
+{
+ CACFLayerSetSublayers(layer(), 0);
+ setNeedsCommit();
+}
+
+void WKCACFLayer::setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
+{
+ if (sublayers.isEmpty())
+ CACFLayerSetSublayers(layer(), 0);
+ else {
+ // Create a vector of CACFLayers.
+ Vector<const void*> layers;
+ for (size_t i = 0; i < sublayers.size(); i++)
+ layers.append(sublayers[i]->layer());
+
+ RetainPtr<CFArrayRef> layersArray(AdoptCF, CFArrayCreate(0, layers.data(), layers.size(), 0));
+ CACFLayerSetSublayers(layer(), layersArray.get());
+ }
+
+ setNeedsCommit();
+}
+
+void WKCACFLayer::moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer)
+{
+ if (!fromLayer || !toLayer)
+ return;
+
+ CACFLayerSetSublayers(toLayer->layer(), CACFLayerGetSublayers(fromLayer->layer()));
+ fromLayer->setNeedsCommit();
+ toLayer->setNeedsCommit();
+}
+
+WKCACFLayer* WKCACFLayer::superlayer() const
+{
+ CACFLayerRef super = CACFLayerGetSuperlayer(layer());
+ if (!super)
+ return 0;
+ return WKCACFLayer::layer(super);
+}
+
+void WKCACFLayer::setNeedsDisplay(const CGRect& dirtyRect)
+{
+ if (m_owner)
+ CACFLayerSetNeedsDisplay(layer(), &dirtyRect);
+ setNeedsCommit();
+}
+
+void WKCACFLayer::setNeedsDisplay()
+{
+ if (m_owner)
+ CACFLayerSetNeedsDisplay(layer(), 0);
+ setNeedsCommit();
+}
+
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h
new file mode 100644
index 0000000..6655f7a
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayer.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WKCACFLayer_h
+#define WKCACFLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "StringHash.h"
+
+#include <wtf/RefCounted.h>
+
+#include <QuartzCore/CACFLayer.h>
+#include <QuartzCore/CACFVector.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+#include "GraphicsContext.h"
+#include "GraphicsLayerCACF.h"
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+
+namespace WebCore {
+
+class WKCACFAnimation;
+class WKCACFTimingFunction;
+
+class WKCACFLayer : public RefCounted<WKCACFLayer> {
+public:
+ static PassRefPtr<WKCACFLayer> create(CFStringRef className, GraphicsLayerCACF* owner = 0) { return adoptRef(new WKCACFLayer(className, owner)); }
+ static WKCACFLayer* layer(CACFLayerRef layer) { return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer)); }
+
+ ~WKCACFLayer();
+
+ // Makes this layer the root when the passed context is rendered
+ void becomeRootLayerForContext(CACFContextRef);
+
+ static RetainPtr<CFTypeRef> cfValue(float value) { return RetainPtr<CFTypeRef>(AdoptCF, CFNumberCreate(0, kCFNumberFloat32Type, &value)); }
+ static RetainPtr<CFTypeRef> cfValue(const TransformationMatrix& value)
+ {
+ CATransform3D t;
+ t.m11 = value.m11();
+ t.m12 = value.m12();
+ t.m13 = value.m13();
+ t.m14 = value.m14();
+ t.m21 = value.m21();
+ t.m22 = value.m22();
+ t.m23 = value.m23();
+ t.m24 = value.m24();
+ t.m31 = value.m31();
+ t.m32 = value.m32();
+ t.m33 = value.m33();
+ t.m34 = value.m34();
+ t.m41 = value.m41();
+ t.m42 = value.m42();
+ t.m43 = value.m43();
+ t.m44 = value.m44();
+ return RetainPtr<CFTypeRef>(AdoptCF, CACFVectorCreateTransform(t));
+ }
+ static RetainPtr<CFTypeRef> cfValue(const FloatPoint& value)
+ {
+ CGPoint p;
+ p.x = value.x(); p.y = value.y();
+ return RetainPtr<CFTypeRef>(AdoptCF, CACFVectorCreatePoint(p));
+ }
+ static RetainPtr<CFTypeRef> cfValue(const FloatRect& rect)
+ {
+ CGRect r;
+ r.origin.x = rect.x();
+ r.origin.y = rect.y();
+ r.size.width = rect.width();
+ r.size.height = rect.height();
+ CGFloat v[4] = { CGRectGetMinX(r), CGRectGetMinY(r), CGRectGetMaxX(r), CGRectGetMaxY(r) };
+ return RetainPtr<CFTypeRef>(AdoptCF, CACFVectorCreate(4, v));
+ }
+ static RetainPtr<CFTypeRef> cfValue(const Color& color)
+ {
+ return RetainPtr<CFTypeRef>(AdoptCF, CGColorCreateGenericRGB(color.red(), color.green(), color.blue(), color.alpha()));
+ }
+
+ void display(PlatformGraphicsContext*);
+
+ bool isTransformLayer() const { return CACFLayerGetClass(layer()) == kCACFTransformLayer; }
+
+ void addSublayer(PassRefPtr<WKCACFLayer> sublayer);
+ void insertSublayer(PassRefPtr<WKCACFLayer>, size_t index);
+ void insertSublayerAboveLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference);
+ void insertSublayerBelowLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference);
+ void replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer>);
+ void removeFromSuperlayer();
+ static void moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer);
+
+ WKCACFLayer* ancestorOrSelfWithSuperlayer(WKCACFLayer*) const;
+
+ void setAnchorPoint(const CGPoint& p) { CACFLayerSetAnchorPoint(layer(), p); setNeedsCommit(); }
+ CGPoint anchorPoint() const { return CACFLayerGetAnchorPoint(layer()); }
+
+ void setAnchorPointZ(CGFloat z) { CACFLayerSetAnchorPointZ(layer(), z); setNeedsCommit(); }
+ CGFloat anchorPointZ() const { return CACFLayerGetAnchorPointZ(layer()); }
+
+ void setBackgroundColor(CGColorRef color) { CACFLayerSetBackgroundColor(layer(), color); setNeedsCommit(); }
+ CGColorRef backgroundColor() const { return CACFLayerGetBackgroundColor(layer()); }
+
+ void setBorderColor(CGColorRef color) { CACFLayerSetBorderColor(layer(), color); setNeedsCommit(); }
+ CGColorRef borderColor() const { return CACFLayerGetBorderColor(layer()); }
+
+ void setBorderWidth(CGFloat width) { CACFLayerSetBorderWidth(layer(), width); setNeedsCommit(); }
+ CGFloat borderWidth() const { return CACFLayerGetBorderWidth(layer()); }
+
+ void setBounds(const CGRect&);
+ CGRect bounds() const { return CACFLayerGetBounds(layer()); }
+
+ void setClearsContext(bool clears) { CACFLayerSetClearsContext(layer(), clears); setNeedsCommit(); }
+ bool clearsContext() const { return CACFLayerGetClearsContext(layer()); }
+
+ void setContents(CGImageRef contents) { CACFLayerSetContents(layer(), contents); setNeedsCommit(); }
+ CGImageRef contents() const { return static_cast<CGImageRef>(const_cast<void*>(CACFLayerGetContents(layer()))); }
+
+ void setContentsRect(const CGRect& contentsRect) { CACFLayerSetContentsRect(layer(), contentsRect); setNeedsCommit(); }
+ CGRect contentsRect() const { return CACFLayerGetContentsRect(layer()); }
+
+ void setContentsGravity(CFStringRef str) { CACFLayerSetContentsGravity(layer(), str); setNeedsCommit(); }
+ CFStringRef contentsGravity() const { return CACFLayerGetContentsGravity(layer()); }
+
+ void setDoubleSided(bool b) { CACFLayerSetDoubleSided(layer(), b); setNeedsCommit(); }
+ bool doubleSided() const { return CACFLayerIsDoubleSided(layer()); }
+
+ void setEdgeAntialiasingMask(uint32_t mask) { CACFLayerSetEdgeAntialiasingMask(layer(), mask); setNeedsCommit(); }
+ uint32_t edgeAntialiasingMask() const { return CACFLayerGetEdgeAntialiasingMask(layer()); }
+
+ void setFilters(CFArrayRef filters) { CACFLayerSetFilters(layer(), filters); setNeedsCommit(); }
+ CFArrayRef filters() const { return CACFLayerGetFilters(layer()); }
+
+ void setFrame(const CGRect&);
+ CGRect frame() const { return CACFLayerGetFrame(layer()); }
+
+ void setHidden(bool hidden) { CACFLayerSetHidden(layer(), hidden); setNeedsCommit(); }
+ bool isHidden() const { return CACFLayerIsHidden(layer()); }
+
+ void setMasksToBounds(bool b) { CACFLayerSetMasksToBounds(layer(), b); }
+ bool masksToBounds() const { return CACFLayerGetMasksToBounds(layer()); }
+
+ void setMagnificationFilter(const String& string) { CACFLayerSetMagnificationFilter(layer(), RetainPtr<CFStringRef>(AdoptCF, string.createCFString()).get()); }
+ String magnificationFilter() const { return CACFLayerGetMagnificationFilter(layer()); }
+
+ void setMinificationFilter(const String& string) { CACFLayerSetMinificationFilter(layer(), RetainPtr<CFStringRef>(AdoptCF, string.createCFString()).get()); }
+ String minificationFilter() const { return CACFLayerGetMinificationFilter(layer()); }
+
+ void setMinificationFilterBias(float bias) { CACFLayerSetMinificationFilterBias(layer(), bias); }
+ float minificationFilterBias() const { return CACFLayerGetMinificationFilterBias(layer()); }
+
+ void setName(const String& name) { CACFLayerSetName(layer(), RetainPtr<CFStringRef>(AdoptCF, name.createCFString()).get()); }
+ String name() const { return CACFLayerGetName(layer()); }
+
+ void setNeedsDisplay(const CGRect& dirtyRect);
+ void setNeedsDisplay();
+
+ void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; }
+
+ void setOpacity(float opacity) { CACFLayerSetOpacity(layer(), opacity); setNeedsCommit(); }
+ float opacity() const { return CACFLayerGetOpacity(layer()); }
+
+ void setOpaque(bool b) { CACFLayerSetOpaque(layer(), b); setNeedsCommit(); }
+ bool opaque() const { return CACFLayerIsOpaque(layer()); }
+
+ void setPosition(const CGPoint& position) { CACFLayerSetPosition(layer(), position); setNeedsCommit(); }
+ CGPoint position() const { return CACFLayerGetPosition(layer()); }
+
+ void setZPosition(CGFloat position) { CACFLayerSetZPosition(layer(), position); setNeedsCommit(); }
+ CGFloat zPosition() const { return CACFLayerGetZPosition(layer()); }
+
+ void setSpeed(float speed) { CACFLayerSetSpeed(layer(), speed); }
+ CFTimeInterval speed() const { CACFLayerGetSpeed(layer()); }
+
+ void setTimeOffset(CFTimeInterval t) { CACFLayerSetTimeOffset(layer(), t); }
+ CFTimeInterval timeOffset() const { CACFLayerGetTimeOffset(layer()); }
+
+ WKCACFLayer* rootLayer() const;
+
+ void setSortsSublayers(bool sorts) { CACFLayerSetSortsSublayers(layer(), sorts); setNeedsCommit(); }
+ bool sortsSublayers() const { return CACFLayerGetSortsSublayers(layer()); }
+
+ void removeAllSublayers();
+
+ void setSublayers(const Vector<RefPtr<WKCACFLayer> >&);
+
+ void setSublayerTransform(const CATransform3D& transform) { CACFLayerSetSublayerTransform(layer(), transform); setNeedsCommit(); }
+ CATransform3D sublayerTransform() const { return CACFLayerGetSublayerTransform(layer()); }
+
+ WKCACFLayer* superlayer() const;
+
+ void setTransform(const CATransform3D& transform) { CACFLayerSetTransform(layer(), transform); setNeedsCommit(); }
+ CATransform3D transform() const { return CACFLayerGetTransform(layer()); }
+
+ void setGeometryFlipped(bool flipped) { CACFLayerSetGeometryFlipped(layer(), flipped); setNeedsCommit(); }
+ bool geometryFlipped() const { return CACFLayerIsGeometryFlipped(layer()); }
+
+ WKCACFLayer(CFStringRef className, GraphicsLayerCACF* owner);
+
+private:
+ void setNeedsCommit();
+ CACFLayerRef layer() const { return m_layer.get(); }
+ size_t numSublayers() const
+ {
+ CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+ return sublayers ? CFArrayGetCount(sublayers) : 0;
+ }
+
+ // Returns the index of the passed layer in this layer's sublayers list
+ // or -1 if not found
+ int indexOfSublayer(const WKCACFLayer*);
+
+ // This should only be called from removeFromSuperlayer.
+ void removeSublayer(const WKCACFLayer*);
+
+ RetainPtr<CACFLayerRef> m_layer;
+ bool m_needsDisplayOnBoundsChange;
+ GraphicsLayerCACF* m_owner;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFLayer_h
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
new file mode 100644
index 0000000..9fbd0fc
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFLayerRenderer.h"
+
+#include "WKCACFContextFlusher.h"
+#include "WKCACFLayer.h"
+#include <CoreGraphics/CGSRegion.h>
+#include <QuartzCore/CACFContext.h>
+#include <QuartzCore/CARenderOGL.h>
+#include <wtf/HashMap.h>
+#include <wtf/OwnArrayPtr.h>
+#include <d3d9.h>
+#include <d3dx9.h>
+#include <dxerr9.h>
+
+#pragma comment(lib, "d3d9")
+#pragma comment(lib, "d3dx9")
+#pragma comment(lib, "QuartzCore")
+
+static IDirect3D9* s_d3d = 0;
+static IDirect3D9* d3d()
+{
+ if (s_d3d)
+ return s_d3d;
+
+ if (!LoadLibrary(TEXT("d3d9.dll")))
+ return 0;
+
+ s_d3d = Direct3DCreate9(D3D_SDK_VERSION);
+
+ return s_d3d;
+}
+
+inline static CGRect winRectToCGRect(RECT rc)
+{
+ return CGRectMake(rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top));
+}
+
+inline static CGRect winRectToCGRect(RECT rc, RECT relativeToRect)
+{
+ return CGRectMake(rc.left, (relativeToRect.bottom-rc.bottom), (rc.right - rc.left), (rc.bottom - rc.top));
+}
+
+namespace WebCore {
+
+typedef HashMap<CACFContextRef, WKCACFLayerRenderer*> ContextToWindowMap;
+
+static ContextToWindowMap& windowsForContexts()
+{
+ DEFINE_STATIC_LOCAL(ContextToWindowMap, map, ());
+ return map;
+}
+
+static D3DPRESENT_PARAMETERS initialPresentationParameters()
+{
+ D3DPRESENT_PARAMETERS parameters = {0};
+ parameters.Windowed = TRUE;
+ parameters.SwapEffect = D3DSWAPEFFECT_COPY;
+ parameters.BackBufferCount = 1;
+ parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+ parameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+
+ return parameters;
+}
+
+bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
+{
+ static bool available;
+ static bool tested;
+
+ if (tested)
+ return available;
+
+ tested = true;
+ HMODULE library = LoadLibrary(TEXT("d3d9.dll"));
+ if (!library)
+ return false;
+
+ FreeLibrary(library);
+ library = LoadLibrary(TEXT("QuartzCore.dll"));
+ if (!library)
+ return false;
+
+ FreeLibrary(library);
+ available = true;
+ return available;
+}
+
+void WKCACFLayerRenderer::didFlushContext(CACFContextRef context)
+{
+ WKCACFLayerRenderer* window = windowsForContexts().get(context);
+ if (!window)
+ return;
+
+ window->renderSoon();
+}
+
+PassOwnPtr<WKCACFLayerRenderer> WKCACFLayerRenderer::create()
+{
+ if (!acceleratedCompositingAvailable())
+ return 0;
+ return new WKCACFLayerRenderer;
+}
+
+WKCACFLayerRenderer::WKCACFLayerRenderer()
+ : m_triedToCreateD3DRenderer(false)
+ , m_renderContext(0)
+ , m_renderer(0)
+ , m_hostWindow(0)
+ , m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired)
+ , m_scrollFrameWidth(1) // Default to 1 to avoid 0 size frames
+ , m_scrollFrameHeight(1) // Default to 1 to avoid 0 size frames
+{
+}
+
+WKCACFLayerRenderer::~WKCACFLayerRenderer()
+{
+ destroyRenderer();
+}
+
+void WKCACFLayerRenderer::setScrollFrame(int width, int height, int scrollX, int scrollY)
+{
+ m_scrollFrameWidth = width;
+ m_scrollFrameHeight = height;
+
+ CGRect contentsRect = CGRectMake(scrollX, scrollY, width, height);
+ m_scrollLayer->setFrame(contentsRect);
+
+ if (m_rootChildLayer) {
+ contentsRect.origin.x = 0;
+ contentsRect.origin.y = 0;
+ m_rootChildLayer->setFrame(contentsRect);
+ }
+}
+
+void WKCACFLayerRenderer::setRootContents(CGImageRef image)
+{
+ ASSERT(m_rootLayer);
+ m_rootLayer->setContents(image);
+ renderSoon();
+}
+
+void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer)
+{
+ if (!m_scrollLayer)
+ return;
+
+ m_scrollLayer->removeAllSublayers();
+ if (layer) {
+ m_scrollLayer->addSublayer(layer);
+
+ // Set the frame
+ layer->setFrame(CGRectMake(0, 0, m_scrollFrameWidth, m_scrollFrameHeight));
+ }
+
+ m_rootChildLayer = layer;
+
+}
+
+void WKCACFLayerRenderer::setNeedsDisplay()
+{
+ ASSERT(m_rootLayer);
+ m_rootLayer->setNeedsDisplay();
+ renderSoon();
+}
+
+void WKCACFLayerRenderer::createRenderer()
+{
+ if (m_triedToCreateD3DRenderer)
+ return;
+
+ m_triedToCreateD3DRenderer = true;
+ D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
+
+ if (!d3d() || !::IsWindow(m_hostWindow))
+ return;
+
+ // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the
+ // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero
+ // size eventually, and then the backbuffer size will get reset.
+ RECT rect;
+ GetClientRect(m_hostWindow, &rect);
+
+ if (rect.left-rect.right == 0 || rect.bottom-rect.top == 0) {
+ parameters.BackBufferWidth = 1;
+ parameters.BackBufferHeight = 1;
+ }
+
+ if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &parameters, &m_d3dDevice)))
+ return;
+
+ D3DXMATRIXA16 projection;
+ D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f);
+
+ m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+
+ m_context.adoptCF(CACFContextCreate(0));
+ windowsForContexts().set(m_context.get(), this);
+
+ m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()));
+ m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);
+
+ // Create the root hierarchy
+ m_rootLayer = WKCACFLayer::create(kCACFLayer);
+ m_scrollLayer = WKCACFLayer::create(kCACFLayer);
+
+ m_rootLayer->addSublayer(m_scrollLayer);
+ m_scrollLayer->setMasksToBounds(true);
+
+#ifndef NDEBUG
+ CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204));
+ m_rootLayer->setBackgroundColor(debugColor);
+ CGColorRelease(debugColor);
+#endif
+
+ if (IsWindow(m_hostWindow)) {
+ m_rootLayer->setFrame(bounds());
+
+ // For now this will include the scroll bars. Later in the setScrollFrame
+ // we will fix it
+ m_scrollLayer->setFrame(bounds());
+ }
+
+ if (m_context)
+ m_rootLayer->becomeRootLayerForContext(m_context.get());
+}
+
+void WKCACFLayerRenderer::destroyRenderer()
+{
+ if (m_context) {
+ windowsForContexts().remove(m_context.get());
+ WKCACFContextFlusher::shared().removeContext(m_context.get());
+ }
+
+ if (m_renderer)
+ CARenderOGLDestroy(m_renderer);
+ m_renderer = 0;
+ m_d3dDevice = 0;
+ if (s_d3d)
+ s_d3d->Release();
+
+ s_d3d = 0;
+ m_rootLayer = 0;
+ m_scrollLayer = 0;
+ m_rootChildLayer = 0;
+
+ m_triedToCreateD3DRenderer = false;
+}
+
+void WKCACFLayerRenderer::resize()
+{
+ if (!m_d3dDevice)
+ return;
+
+ resetDevice();
+
+ if (m_rootLayer) {
+ m_rootLayer->setFrame(bounds());
+ WKCACFContextFlusher::shared().flushAllContexts();
+ }
+}
+
+static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
+{
+ ASSERT_ARG(outRects, outRects.isEmpty());
+
+ RECT clientRect;
+ if (!GetClientRect(window, &clientRect))
+ return;
+
+ HRGN region = CreateRectRgn(0, 0, 0, 0);
+ int regionType = GetUpdateRgn(window, region, false);
+ if (regionType != COMPLEXREGION) {
+ RECT dirtyRect;
+ if (GetUpdateRect(window, &dirtyRect, false))
+ outRects.append(winRectToCGRect(dirtyRect, clientRect));
+ return;
+ }
+
+ DWORD dataSize = GetRegionData(region, 0, 0);
+ OwnArrayPtr<unsigned char> regionDataBuffer(new unsigned char[dataSize]);
+ RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get());
+ if (!GetRegionData(region, dataSize, regionData))
+ return;
+
+ outRects.resize(regionData->rdh.nCount);
+
+ RECT* rect = reinterpret_cast<RECT*>(regionData->Buffer);
+ for (size_t i = 0; i < outRects.size(); ++i, ++rect)
+ outRects[i] = winRectToCGRect(*rect, clientRect);
+
+ DeleteObject(region);
+}
+
+void WKCACFLayerRenderer::renderTimerFired(Timer<WKCACFLayerRenderer>*)
+{
+ paint();
+}
+
+void WKCACFLayerRenderer::paint()
+{
+ if (!m_d3dDevice)
+ return;
+
+ Vector<CGRect> dirtyRects;
+ getDirtyRects(m_hostWindow, dirtyRects);
+ render(dirtyRects);
+}
+
+void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
+{
+ ASSERT(m_d3dDevice);
+
+ // Flush the root layer to the render tree.
+ WKCACFContextFlusher::shared().flushAllContexts();
+
+ CGRect bounds = this->bounds();
+
+ CFTimeInterval t = CACurrentMediaTime();
+
+ // Give the renderer some space to use. This needs to be valid until the
+ // CARenderUpdateFinish() call below.
+ char space[4096];
+ CARenderUpdate* u = CARenderUpdateBegin(space, sizeof(space), t, 0, 0, &bounds);
+ if (!u)
+ return;
+
+ CARenderContextLock(m_renderContext);
+ CARenderUpdateAddContext(u, m_renderContext);
+ CARenderContextUnlock(m_renderContext);
+
+ for (size_t i = 0; i < dirtyRects.size(); ++i)
+ CARenderUpdateAddRect(u, &dirtyRects[i]);
+
+ HRESULT err = S_OK;
+ do {
+ CGSRegionObj rgn = CARenderUpdateCopyRegion(u);
+
+ if (!rgn)
+ break;
+
+ // FIXME: don't need to clear dirty region if layer tree is opaque.
+
+ Vector<D3DRECT, 64> rects;
+ CGSRegionEnumeratorObj e = CGSRegionEnumerator(rgn);
+ for (const CGRect* r = CGSNextRect(e); r; r = CGSNextRect(e)) {
+ D3DRECT rect;
+ rect.x1 = r->origin.x;
+ rect.x2 = rect.x1 + r->size.width;
+ rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height);
+ rect.y2 = rect.y1 + r->size.height;
+
+ rects.append(rect);
+ }
+ CGSReleaseRegionEnumerator(e);
+ CGSReleaseRegion(rgn);
+
+ if (rects.isEmpty())
+ break;
+
+ m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0);
+
+ m_d3dDevice->BeginScene();
+ CARenderOGLRender(m_renderer, u);
+ m_d3dDevice->EndScene();
+
+ err = m_d3dDevice->Present(0, 0, 0, 0);
+
+ if (err == D3DERR_DEVICELOST) {
+ // Lost device situation.
+ CARenderOGLPurge(m_renderer);
+ resetDevice();
+ CARenderUpdateAddRect(u, &bounds);
+ }
+ } while (err == D3DERR_DEVICELOST);
+
+ CARenderUpdateFinish(u);
+}
+
+void WKCACFLayerRenderer::renderSoon()
+{
+ if (!m_renderTimer.isActive())
+ m_renderTimer.startOneShot(0);
+}
+
+CGRect WKCACFLayerRenderer::bounds() const
+{
+ RECT clientRect;
+ GetClientRect(m_hostWindow, &clientRect);
+
+ return winRectToCGRect(clientRect);
+}
+
+void WKCACFLayerRenderer::initD3DGeometry()
+{
+ ASSERT(m_d3dDevice);
+
+ CGRect bounds = this->bounds();
+
+ float x0 = bounds.origin.x;
+ float y0 = bounds.origin.y;
+ float x1 = x0 + bounds.size.width;
+ float y1 = y0 + bounds.size.height;
+
+ D3DXMATRIXA16 projection;
+ D3DXMatrixOrthoOffCenterRH(&projection, x0, x1, y0, y1, -1.0f, 1.0f);
+
+ m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
+}
+
+void WKCACFLayerRenderer::resetDevice()
+{
+ ASSERT(m_d3dDevice);
+
+ D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
+ m_d3dDevice->Reset(&parameters);
+ initD3DGeometry();
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
new file mode 100644
index 0000000..12cde48
--- /dev/null
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WKCACFLayerRenderer_h
+#define WKCACFLayerRenderer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "COMPtr.h"
+#include "Timer.h"
+#include "WKCACFLayer.h"
+
+#include <wtf/Noncopyable.h>
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/RetainPtr.h>
+
+#include <CoreGraphics/CGGeometry.h>
+
+interface IDirect3DDevice9;
+typedef struct _CACFContext* CACFContextRef;
+typedef struct _CARenderContext CARenderContext;
+typedef struct _CARenderOGLContext CARenderOGLContext;
+
+namespace WebCore {
+
+// FIXME: Currently there is a WKCACFLayerRenderer for each WebView and each
+// has its own CARenderOGLContext and Direct3DDevice9, which is inefficient.
+// (https://bugs.webkit.org/show_bug.cgi?id=31855)
+class WKCACFLayerRenderer : public Noncopyable {
+public:
+ static PassOwnPtr<WKCACFLayerRenderer> create();
+ ~WKCACFLayerRenderer();
+
+ static bool acceleratedCompositingAvailable();
+ static void didFlushContext(CACFContextRef);
+
+ void setScrollFrame(int width, int height, int scrollX, int scrollY);
+ void setRootContents(CGImageRef);
+ void setRootChildLayer(WebCore::PlatformLayer* layer);
+ void setNeedsDisplay();
+ void setHostWindow(HWND window) { m_hostWindow = window; createRenderer(); }
+
+ void createRenderer();
+ void destroyRenderer();
+ void resize();
+ void renderSoon();
+
+protected:
+ WKCACFLayer* rootLayer() const { return m_rootLayer.get(); }
+
+private:
+ WKCACFLayerRenderer();
+
+ void renderTimerFired(Timer<WKCACFLayerRenderer>*);
+
+ CGRect bounds() const;
+
+ void initD3DGeometry();
+ void resetDevice();
+
+ void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
+ void paint();
+
+ bool m_triedToCreateD3DRenderer;
+ COMPtr<IDirect3DDevice9> m_d3dDevice;
+ RefPtr<WKCACFLayer> m_rootLayer;
+ RefPtr<WKCACFLayer> m_viewLayer;
+ RefPtr<WKCACFLayer> m_scrollLayer;
+ RefPtr<WKCACFLayer> m_rootChildLayer;
+ RetainPtr<CACFContextRef> m_context;
+ CARenderContext* m_renderContext;
+ CARenderOGLContext* m_renderer;
+ HWND m_hostWindow;
+ Timer<WKCACFLayerRenderer> m_renderTimer;
+ int m_scrollFrameWidth, m_scrollFrameHeight;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WKCACFLayerRenderer_h
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
index f308840..f22e6c9 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp
@@ -947,7 +947,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
}
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled() || !m_data->m_opacity)
return;
@@ -1051,12 +1051,12 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int wi
notImplemented();
}
-void GraphicsContext::setPlatformFillColor(const Color& col)
+void GraphicsContext::setPlatformFillColor(const Color& col, ColorSpace colorSpace)
{
notImplemented();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& col)
+void GraphicsContext::setPlatformStrokeColor(const Color& col, ColorSpace colorSpace)
{
notImplemented();
}
@@ -1088,7 +1088,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
return;
}
- fillRect(rect, Color(Color::white));
+ fillRect(rect, Color(Color::white), DeviceColorSpace);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float width)
@@ -1238,7 +1238,7 @@ static inline IntPoint rectCenterPoint(const RECT& rect)
{
return IntPoint(rect.left + (rect.right - rect.left) / 2, rect.top + (rect.bottom - rect.top) / 2);
}
-void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& c)
+void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& c, ColorSpace colorSpace)
{
ScopeDCProvider dcProvider(m_data);
if (!m_data->m_dc)
@@ -1355,7 +1355,7 @@ Color gradientAverageColor(const Gradient* gradient)
void GraphicsContext::fillPath()
{
- Color c = m_common->state.fillColorSpace == GradientColorSpace && m_common->state.fillGradient
+ Color c = m_common->state.fillGradient
? gradientAverageColor(m_common->state.fillGradient.get())
: fillColor();
@@ -1449,7 +1449,7 @@ void GraphicsContext::fillRect(const FloatRect& r, const Gradient* gradient)
if (numStops == 1) {
const Gradient::ColorStop& stop = stops.first();
Color color(stop.red, stop.green, stop.blue, stop.alpha);
- fillRect(r, color);
+ fillRect(r, color, DeviceColorSpace);
return;
}
@@ -1539,13 +1539,13 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
void GraphicsContext::fillRect(const FloatRect& rect)
{
- if (m_common->state.fillColorSpace == GradientColorSpace && m_common->state.fillGradient)
+ if (m_common->state.fillGradient)
fillRect(rect, m_common->state.fillGradient.get());
else
- fillRect(rect, fillColor());
+ fillRect(rect, fillColor(), DeviceColorSpace);
}
-void GraphicsContext::setPlatformShadow(const IntSize&, int, const Color&)
+void GraphicsContext::setPlatformShadow(const IntSize&, int, const Color&, ColorSpace)
{
notImplemented();
}
diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
index de92fcd..fd3322f 100644
--- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
+++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -111,7 +111,7 @@ unsigned FontPlatformData::computeHash() const {
// a font whose properties are equal should generate the same hash
uintptr_t hashCodes[6] = { thisFont->GetPointSize(), thisFont->GetFamily(), thisFont->GetStyle(),
thisFont->GetWeight(), thisFont->GetUnderlined(),
- StringImpl::computeHash(thisFont->GetFaceName().mb_str(wxConvUTF8)) };
+ StringImpl::computeHash(thisFont->GetFaceName().utf8_str()) };
return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
}
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 39f14f4..9c05ce5 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -119,8 +119,8 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
setPaintingDisabled(!context);
if (context) {
// Make sure the context starts in sync with our state.
- setPlatformFillColor(fillColor());
- setPlatformStrokeColor(strokeColor());
+ setPlatformFillColor(fillColor(), DeviceColorSpace);
+ setPlatformStrokeColor(strokeColor(), DeviceColorSpace);
}
#if USE(WXGC)
m_data->context = (wxGCDC*)context;
@@ -252,7 +252,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
delete [] polygon;
}
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -262,7 +262,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
}
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -438,7 +438,7 @@ void GraphicsContext::addPath(const Path& path)
notImplemented();
}
-void GraphicsContext::setPlatformStrokeColor(const Color& color)
+void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -457,7 +457,7 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
}
-void GraphicsContext::setPlatformFillColor(const Color& color)
+void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
return;
@@ -511,7 +511,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
}
-void GraphicsContext::setPlatformShadow(IntSize const&,int,Color const&)
+void GraphicsContext::setPlatformShadow(IntSize const&,int,Color const&, ColorSpace)
{
notImplemented();
}
@@ -566,4 +566,72 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
notImplemented();
}
+#if PLATFORM(WIN_OS)
+HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
+{
+ if (dstRect.isEmpty())
+ return 0;
+
+ // Create a bitmap DC in which to draw.
+ BITMAPINFO bitmapInfo;
+ bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.bmiHeader.biWidth = dstRect.width();
+ bitmapInfo.bmiHeader.biHeight = dstRect.height();
+ bitmapInfo.bmiHeader.biPlanes = 1;
+ bitmapInfo.bmiHeader.biBitCount = 32;
+ bitmapInfo.bmiHeader.biCompression = BI_RGB;
+ bitmapInfo.bmiHeader.biSizeImage = 0;
+ bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biClrUsed = 0;
+ bitmapInfo.bmiHeader.biClrImportant = 0;
+
+ void* pixels = 0;
+ HBITMAP bitmap = ::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
+ if (!bitmap)
+ return 0;
+
+ HDC displayDC = ::GetDC(0);
+ HDC bitmapDC = ::CreateCompatibleDC(displayDC);
+ ::ReleaseDC(0, displayDC);
+
+ ::SelectObject(bitmapDC, bitmap);
+
+ // Fill our buffer with clear if we're going to alpha blend.
+ if (supportAlphaBlend) {
+ BITMAP bmpInfo;
+ GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ memset(bmpInfo.bmBits, 0, bufferSize);
+ }
+ return bitmapDC;
+}
+
+void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
+{
+ if (hdc) {
+
+ if (!dstRect.isEmpty()) {
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ wxBitmap bmp;
+ bmp.SetHBITMAP(bitmap);
+#if !wxCHECK_VERSION(2,9,0)
+ if (supportAlphaBlend)
+ bmp.UseAlpha();
+#endif
+ m_data->context->DrawBitmap(bmp, dstRect.x(), dstRect.y(), supportAlphaBlend);
+
+ ::DeleteObject(bitmap);
+ }
+
+ ::DeleteDC(hdc);
+ }
+}
+#endif
+
}
diff --git a/WebCore/platform/graphics/wx/IconWx.cpp b/WebCore/platform/graphics/wx/IconWx.cpp
index e82091e..d3cc961 100644
--- a/WebCore/platform/graphics/wx/IconWx.cpp
+++ b/WebCore/platform/graphics/wx/IconWx.cpp
@@ -32,12 +32,6 @@ Icon::~Icon()
{
}
-PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
-{
- notImplemented();
- return 0;
-}
-
PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
{
notImplemented();
diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp
index bd129cf..ff60d6f 100644
--- a/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -86,13 +86,13 @@ void BitmapImage::initPlatformData()
// Drawing Routines
-void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
{
if (!m_source.initialized())
return;
if (mayFillWithSolidColor()) {
- fillWithSolidColor(ctxt, dst, solidColor(), op);
+ fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
return;
}
@@ -176,7 +176,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR
observer->didDraw(this);
}
-void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& dstRect)
+void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& dstRect)
{
if (!m_source.initialized())
return;
@@ -261,7 +261,7 @@ void BitmapImage::invalidatePlatformData()
}
-void Image::drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& destRect)
+void Image::drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& destRect)
{
notImplemented();
}