summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/BitmapImage.h15
-rw-r--r--WebCore/platform/graphics/Color.h9
-rw-r--r--WebCore/platform/graphics/FloatPoint.h18
-rw-r--r--WebCore/platform/graphics/FloatRect.h22
-rw-r--r--WebCore/platform/graphics/FloatSize.h5
-rw-r--r--WebCore/platform/graphics/FontCache.h11
-rw-r--r--WebCore/platform/graphics/FontDescription.h17
-rw-r--r--WebCore/platform/graphics/FontFastPath.cpp4
-rw-r--r--WebCore/platform/graphics/FontSmoothingMode.h35
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.cpp6
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp49
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h42
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h335
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.cpp3
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h19
-rw-r--r--WebCore/platform/graphics/GraphicsLayerClient.h7
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h12
-rw-r--r--WebCore/platform/graphics/ImageSource.cpp (renamed from WebCore/platform/graphics/cairo/ImageSourceCairo.cpp)152
-rw-r--r--WebCore/platform/graphics/ImageSource.h31
-rw-r--r--WebCore/platform/graphics/IntPoint.h5
-rw-r--r--WebCore/platform/graphics/IntRect.h13
-rw-r--r--WebCore/platform/graphics/IntSize.h15
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp36
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h26
-rw-r--r--WebCore/platform/graphics/MediaPlayerPrivate.h8
-rw-r--r--WebCore/platform/graphics/Path.h3
-rw-r--r--WebCore/platform/graphics/Pattern.h3
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp4
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h21
-rw-r--r--WebCore/platform/graphics/TextRenderingMode.h35
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp2
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp172
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp69
-rw-r--r--WebCore/platform/graphics/cg/ColorCG.cpp12
-rw-r--r--WebCore/platform/graphics/cg/GradientCG.cpp11
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp402
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h4
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp79
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp77
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp48
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.cpp10
-rw-r--r--WebCore/platform/graphics/cg/PathCG.cpp10
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp8
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp63
-rw-r--r--WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/UniscribeHelper.cpp14
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp78
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.h2
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp4
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp92
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp72
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp7
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h1
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp23
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.h2
-rw-r--r--WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp243
-rw-r--r--WebCore/platform/graphics/gtk/DataSourceGStreamer.h54
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformData.h2
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp11
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp7
-rw-r--r--WebCore/platform/graphics/gtk/ImageGtk.cpp73
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp395
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h13
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp14
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp14
-rw-r--r--WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp66
-rw-r--r--WebCore/platform/graphics/haiku/ColorHaiku.cpp54
-rw-r--r--WebCore/platform/graphics/haiku/FloatPointHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/FloatRectHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/FontCacheHaiku.cpp79
-rw-r--r--WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp45
-rw-r--r--WebCore/platform/graphics/haiku/FontCustomPlatformData.h44
-rw-r--r--WebCore/platform/graphics/haiku/FontHaiku.cpp116
-rw-r--r--WebCore/platform/graphics/haiku/FontPlatformData.h81
-rw-r--r--WebCore/platform/graphics/haiku/GradientHaiku.cpp53
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp536
-rw-r--r--WebCore/platform/graphics/haiku/IconHaiku.cpp57
-rw-r--r--WebCore/platform/graphics/haiku/ImageBufferData.h43
-rw-r--r--WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp97
-rw-r--r--WebCore/platform/graphics/haiku/ImageHaiku.cpp152
-rw-r--r--WebCore/platform/graphics/haiku/IntPointHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/IntRectHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/IntSizeHaiku.cpp48
-rw-r--r--WebCore/platform/graphics/haiku/PathHaiku.cpp161
-rw-r--r--WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp108
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.h50
-rw-r--r--WebCore/platform/graphics/mac/Canvas3DLayer.mm123
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.cpp2
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp12
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm27
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm47
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp1698
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm15
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h29
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm127
-rw-r--r--WebCore/platform/graphics/mac/ImageMac.mm9
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h6
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm42
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm31
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp45
-rw-r--r--WebCore/platform/graphics/opentype/OpenTypeUtilities.h5
-rw-r--r--WebCore/platform/graphics/qt/ColorQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp6
-rw-r--r--WebCore/platform/graphics/qt/FontFallbackListQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp466
-rw-r--r--WebCore/platform/graphics/qt/IconQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp73
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp376
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h54
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp1
-rw-r--r--WebCore/platform/graphics/qt/ImageSourceQt.cpp173
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp23
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h3
-rw-r--r--WebCore/platform/graphics/qt/SimpleFontDataQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.h2
-rw-r--r--WebCore/platform/graphics/skia/GradientSkia.cpp28
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp105
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp81
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp19
-rw-r--r--WebCore/platform/graphics/skia/ImageSourceSkia.cpp238
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp8
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp24
-rw-r--r--WebCore/platform/graphics/win/FontCacheWin.cpp15
-rw-r--r--WebCore/platform/graphics/win/FontDatabase.cpp92
-rw-r--r--WebCore/platform/graphics/win/FontPlatformData.h1
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp6
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp8
-rw-r--r--WebCore/platform/graphics/win/ImageCGWin.cpp25
-rw-r--r--WebCore/platform/graphics/win/ImageCairoWin.cpp21
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp65
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h5
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.cpp24
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.h6
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp6
-rw-r--r--WebCore/platform/graphics/wince/ColorWince.cpp38
-rw-r--r--WebCore/platform/graphics/wince/FontCustomPlatformData.cpp12
-rw-r--r--WebCore/platform/graphics/wince/FontCustomPlatformData.h6
-rw-r--r--WebCore/platform/graphics/wince/GradientWince.cpp52
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferData.h34
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferWince.cpp246
-rw-r--r--WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h129
-rw-r--r--WebCore/platform/graphics/wince/MediaPlayerProxy.cpp145
-rw-r--r--WebCore/platform/graphics/wince/MediaPlayerProxy.h70
-rw-r--r--WebCore/platform/graphics/wince/PathWince.cpp163
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWince.cpp810
-rw-r--r--WebCore/platform/graphics/wince/PlatformPathWince.h178
-rw-r--r--WebCore/platform/graphics/wince/WinceGraphicsExtras.h39
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp55
-rw-r--r--WebCore/platform/graphics/wx/IconWx.cpp53
-rw-r--r--WebCore/platform/graphics/wx/ImageBufferWx.cpp15
-rw-r--r--WebCore/platform/graphics/wx/ImageSourceWx.cpp226
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp13
-rw-r--r--WebCore/platform/graphics/wx/IntSizeWx.cpp45
155 files changed, 9320 insertions, 2237 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
index 807c11b..13641d2 100644
--- a/WebCore/platform/graphics/BitmapImage.h
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -45,6 +45,10 @@ class NSImage;
typedef struct HBITMAP__ *HBITMAP;
#endif
+#if PLATFORM(HAIKU)
+class BBitmap;
+#endif
+
namespace WebCore {
struct FrameData;
}
@@ -137,6 +141,7 @@ public:
#endif
#if PLATFORM(WIN)
+ static PassRefPtr<BitmapImage> create(HBITMAP);
virtual bool getHBITMAP(HBITMAP);
virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE);
#endif
@@ -165,10 +170,16 @@ protected:
virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator);
#endif
virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
-#if PLATFORM(WX) || PLATFORM(WINCE)
+
+#if PLATFORM(WX) || (PLATFORM(WINCE) && !PLATFORM(QT))
virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
-#endif
+#endif
+
+#if PLATFORM(HAIKU)
+ virtual BBitmap* getBBitmap() const;
+#endif
+
size_t currentFrame() const { return m_currentFrame; }
size_t frameCount();
NativeImagePtr frameAtIndex(size_t);
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
index 5baa56e..8e51b95 100644
--- a/WebCore/platform/graphics/Color.h
+++ b/WebCore/platform/graphics/Color.h
@@ -47,6 +47,10 @@ typedef struct _GdkColor GdkColor;
class wxColour;
#endif
+#if PLATFORM(HAIKU)
+struct rgb_color;
+#endif
+
namespace WebCore {
class String;
@@ -121,6 +125,11 @@ public:
Color(CGColorRef);
#endif
+#if PLATFORM(HAIKU)
+ Color(const rgb_color&);
+ operator rgb_color() const;
+#endif
+
static bool parseHexColor(const String& name, RGBA32& rgb);
static const RGBA32 black = 0xFF000000;
diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h
index 0c97c49..06b280b 100644
--- a/WebCore/platform/graphics/FloatPoint.h
+++ b/WebCore/platform/graphics/FloatPoint.h
@@ -36,7 +36,7 @@
typedef struct CGPoint CGPoint;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGPoint NSPoint;
#else
@@ -51,6 +51,10 @@ class QPointF;
QT_END_NAMESPACE
#endif
+#if PLATFORM(HAIKU)
+class BPoint;
+#endif
+
#if PLATFORM(SKIA)
struct SkPoint;
#endif
@@ -80,7 +84,8 @@ public:
operator CGPoint() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
FloatPoint(const NSPoint&);
operator NSPoint() const;
#endif
@@ -90,7 +95,16 @@ public:
operator QPointF() const;
#endif
+<<<<<<< HEAD:WebCore/platform/graphics/FloatPoint.h
#if (PLATFORM(SKIA) || PLATFORM(SGL))
+=======
+#if PLATFORM(HAIKU)
+ FloatPoint(const BPoint&);
+ operator BPoint() const;
+#endif
+
+#if PLATFORM(SKIA)
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/FloatPoint.h
operator SkPoint() const;
FloatPoint(const SkPoint&);
#endif
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
index e906812..704241a 100644
--- a/WebCore/platform/graphics/FloatRect.h
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -33,7 +33,7 @@
typedef struct CGRect CGRect;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGRect NSRect;
#else
@@ -51,7 +51,15 @@ QT_END_NAMESPACE
class wxRect2DDouble;
#endif
+<<<<<<< HEAD:WebCore/platform/graphics/FloatRect.h
#if (PLATFORM(SKIA) || PLATFORM(SGL))
+=======
+#if PLATFORM(HAIKU)
+class BRect;
+#endif
+
+#if PLATFORM(SKIA)
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/FloatRect.h
struct SkRect;
#endif
@@ -123,7 +131,8 @@ public:
operator CGRect() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
FloatRect(const NSRect&);
operator NSRect() const;
#endif
@@ -138,7 +147,16 @@ public:
operator wxRect2DDouble() const;
#endif
+<<<<<<< HEAD:WebCore/platform/graphics/FloatRect.h
#if (PLATFORM(SKIA) || PLATFORM(SGL))
+=======
+#if PLATFORM(HAIKU)
+ FloatRect(const BRect&);
+ operator BRect() const;
+#endif
+
+#if PLATFORM(SKIA)
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/FloatRect.h
FloatRect(const SkRect&);
operator SkRect() const;
#endif
diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h
index 6e792b6..5a84fd1 100644
--- a/WebCore/platform/graphics/FloatSize.h
+++ b/WebCore/platform/graphics/FloatSize.h
@@ -34,7 +34,7 @@
typedef struct CGSize CGSize;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGSize NSSize;
#else
@@ -79,7 +79,8 @@ public:
operator CGSize() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
explicit FloatSize(const NSSize &); // don't do this implicitly since it's lossy
operator NSSize() const;
#endif
diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h
index 3c0f2d9..b88305f 100644
--- a/WebCore/platform/graphics/FontCache.h
+++ b/WebCore/platform/graphics/FontCache.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007-2008 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -63,7 +64,15 @@ public:
// Also implemented by the platform.
void platformInit();
-#if PLATFORM(WIN)
+#if PLATFORM(WINCE) && !PLATFORM(QT)
+#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
+ IMLangFontLink2* getFontLinkInterface();
+#else
+ IMLangFontLink* getFontLinkInterface();
+#endif
+ static void comInitialize();
+ static void comUninitialize();
+#elif PLATFORM(WIN)
IMLangFontLink2* getFontLinkInterface();
#endif
diff --git a/WebCore/platform/graphics/FontDescription.h b/WebCore/platform/graphics/FontDescription.h
index c893b8a..fc63db9 100644
--- a/WebCore/platform/graphics/FontDescription.h
+++ b/WebCore/platform/graphics/FontDescription.h
@@ -27,7 +27,9 @@
#include "FontFamily.h"
#include "FontRenderingMode.h"
+#include "FontSmoothingMode.h"
#include "FontTraitsMask.h"
+#include "TextRenderingMode.h"
namespace WebCore {
@@ -61,6 +63,8 @@ public:
, m_usePrinterFont(false)
, m_renderingMode(NormalRenderingMode)
, m_keywordSize(0)
+ , m_fontSmoothing(AutoSmoothing)
+ , m_textRendering(AutoTextRendering)
{
}
@@ -80,8 +84,12 @@ public:
FontWeight bolderWeight() const;
GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); }
bool usePrinterFont() const { return m_usePrinterFont; }
+ // only use fixed default size when there is only one font family, and that family is "monospace"
+ bool useFixedDefaultSize() const { return genericFamily() == MonospaceFamily && !family().next() && family().family() == "-webkit-monospace"; }
FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); }
unsigned keywordSize() const { return m_keywordSize; }
+ FontSmoothingMode fontSmoothing() const { return static_cast<FontSmoothingMode>(m_fontSmoothing); }
+ TextRenderingMode textRenderingMode() const { return static_cast<TextRenderingMode>(m_textRendering); }
FontTraitsMask traitsMask() const;
@@ -96,6 +104,8 @@ public:
void setUsePrinterFont(bool p) { m_usePrinterFont = p; }
void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; }
void setKeywordSize(unsigned s) { m_keywordSize = s; }
+ void setFontSmoothing(FontSmoothingMode smoothing) { m_fontSmoothing = smoothing; }
+ void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
private:
FontFamily m_familyList; // The list of font families to be used.
@@ -117,6 +127,9 @@ private:
unsigned m_keywordSize : 4; // We cache whether or not a font is currently represented by a CSS keyword (e.g., medium). If so,
// then we can accurately translate across different generic families to adjust for different preference settings
// (e.g., 13px monospace vs. 16px everything else). Sizes are 1-8 (like the HTML size values for <font>).
+
+ unsigned m_fontSmoothing : 2; // FontSmoothingMode
+ unsigned m_textRendering : 2; // TextRenderingMode
};
inline bool FontDescription::operator==(const FontDescription& other) const
@@ -131,7 +144,9 @@ inline bool FontDescription::operator==(const FontDescription& other) const
&& m_genericFamily == other.m_genericFamily
&& m_usePrinterFont == other.m_usePrinterFont
&& m_renderingMode == other.m_renderingMode
- && m_keywordSize == other.m_keywordSize;
+ && m_keywordSize == other.m_keywordSize
+ && m_fontSmoothing == other.m_fontSmoothing
+ && m_textRendering == other.m_textRendering;
}
}
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
index b0e39db..5246593 100644
--- a/WebCore/platform/graphics/FontFastPath.cpp
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -251,6 +251,10 @@ bool Font::canUseGlyphCache(const TextRun& run) const
return false;
}
+ TextRenderingMode textMode = m_fontDescription.textRenderingMode();
+ if (textMode == OptimizeLegibility || textMode == GeometricPrecision)
+ return false;
+
return true;
}
diff --git a/WebCore/platform/graphics/FontSmoothingMode.h b/WebCore/platform/graphics/FontSmoothingMode.h
new file mode 100644
index 0000000..7c23394
--- /dev/null
+++ b/WebCore/platform/graphics/FontSmoothingMode.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 FontSmoothingMode_h
+#define FontSmoothingMode_h
+
+namespace WebCore {
+
+ enum FontSmoothingMode { AutoSmoothing, NoSmoothing, Antialiased, SubpixelAntialiased };
+
+} // namespace WebCore
+
+#endif // FontSmoothingMode_h
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index 6419e0c..9f53f0b 100644
--- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -202,8 +202,10 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu
GlyphPage* pageToFill = m_page.get();
for (unsigned i = 0; i < numRanges; i++) {
const FontDataRange& range = segmentedFontData->rangeAt(i);
- int from = max(0, range.from() - static_cast<int>(start));
- int to = 1 + min(range.to() - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1);
+ // all this casting is to ensure all the parameters to min and max have the same type,
+ // to avoid ambiguous template parameter errors on Windows
+ int from = max(0, static_cast<int>(range.from()) - static_cast<int>(start));
+ int to = 1 + min(static_cast<int>(range.to()) - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1);
if (from < static_cast<int>(GlyphPage::size) && to > 0) {
if (haveGlyphs && !scratchPage) {
scratchPage = GlyphPage::create(this);
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index a4e8408..ccdce08 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -27,9 +27,9 @@
#include "GraphicsContext.h"
#include "BidiResolver.h"
+#include "Font.h"
#include "Generator.h"
#include "GraphicsContextPrivate.h"
-#include "Font.h"
using namespace std;
@@ -89,7 +89,7 @@ void GraphicsContext::save()
return;
m_common->stack.append(m_common->state);
-
+
savePlatformState();
}
@@ -104,7 +104,7 @@ void GraphicsContext::restore()
}
m_common->state = m_common->stack.last();
m_common->stack.removeLast();
-
+
restorePlatformState();
}
@@ -305,7 +305,7 @@ bool GraphicsContext::paintingDisabled() const
}
void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op)
-{
+{
drawImage(image, p, IntRect(0, 0, -1, -1), op);
}
@@ -329,7 +329,7 @@ void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPo
{
if (paintingDisabled())
return;
-
+
font.drawText(this, run, point, from, to);
}
#endif
@@ -383,7 +383,7 @@ void GraphicsContext::initFocusRing(int width, int offset)
if (paintingDisabled())
return;
clearFocusRing();
-
+
m_common->m_focusRingWidth = width;
m_common->m_focusRingOffset = offset;
}
@@ -396,12 +396,12 @@ void GraphicsContext::clearFocusRing()
IntRect GraphicsContext::focusRingBoundingRect()
{
IntRect result = IntRect(0, 0, 0, 0);
-
+
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
for (unsigned i = 0; i < rectCount; i++)
result.unite(rects[i]);
-
+
return result;
}
@@ -436,7 +436,7 @@ void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
float tsh = src.height();
float tw = dest.width();
float th = dest.height();
-
+
if (tsw == -1)
tsw = image->width();
if (tsh == -1)
@@ -540,10 +540,39 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
}
#endif
-#if !PLATFORM(QT) && !PLATFORM(CAIRO) && !PLATFORM(SKIA)
+#if !PLATFORM(QT) && !PLATFORM(CAIRO) && !PLATFORM(SKIA) && !PLATFORM(HAIKU)
void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&)
{
}
#endif
+void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle& penStyle)
+{
+ // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
+ // works out. For example, with a border width of 3, WebKit will pass us (y1+y2)/2, e.g.,
+ // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
+ // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
+ if (penStyle == DottedStroke || penStyle == DashedStroke) {
+ if (p1.x() == p2.x()) {
+ p1.setY(p1.y() + strokeWidth);
+ p2.setY(p2.y() - strokeWidth);
+ } else {
+ p1.setX(p1.x() + strokeWidth);
+ p2.setX(p2.x() - strokeWidth);
+ }
+ }
+
+ if (static_cast<int>(strokeWidth) % 2) { //odd
+ if (p1.x() == p2.x()) {
+ // We're a vertical line. Adjust our x.
+ p1.setX(p1.x() + 0.5f);
+ p2.setX(p2.x() + 0.5f);
+ } else {
+ // We're a horizontal line. Adjust our y.
+ p1.setY(p1.y() + 0.5f);
+ p2.setY(p2.y() + 0.5f);
+ }
+ }
+}
+
}
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 233c14c..b1d1ef9 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -55,8 +55,8 @@ struct SkPoint;
class wxGCDC;
class wxWindowDC;
-// wxGraphicsContext allows us to support Path, etc.
-// but on some platforms, e.g. Linux, it requires fairly
+// wxGraphicsContext allows us to support Path, etc.
+// but on some platforms, e.g. Linux, it requires fairly
// new software.
#if USE(WXGC)
// On OS X, wxGCDC is just a typedef for wxDC, so use wxDC explicitly to make
@@ -72,6 +72,10 @@ class wxWindowDC;
#endif
#elif PLATFORM(SKIA)
typedef class PlatformContextSkia PlatformGraphicsContext;
+#elif PLATFORM(HAIKU)
+class BView;
+typedef BView PlatformGraphicsContext;
+struct pattern;
#elif PLATFORM(WINCE)
typedef struct HDC__ PlatformGraphicsContext;
#else
@@ -124,7 +128,7 @@ namespace WebCore {
const int cTextFill = 1;
const int cTextStroke = 2;
const int cTextClip = 4;
-
+
enum StrokeStyle {
NoStroke,
SolidStroke,
@@ -132,12 +136,12 @@ 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
+ // 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,
@@ -156,11 +160,11 @@ namespace WebCore {
public:
GraphicsContext(PlatformGraphicsContext*);
~GraphicsContext();
-
+
#if !PLATFORM(WINCE) || PLATFORM(QT)
PlatformGraphicsContext* platformContext() const;
#endif
-
+
float strokeThickness() const;
void setStrokeThickness(float);
StrokeStyle strokeStyle() const;
@@ -267,7 +271,7 @@ namespace WebCore {
CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
CompositeOperator = CompositeSourceOver);
- void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
+ void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
CompositeOperator = CompositeSourceOver);
@@ -291,13 +295,13 @@ namespace WebCore {
void drawHighlightForText(const Font&, const TextRun&, const IntPoint&, int h, const Color& backgroundColor, int from = 0, int to = -1);
FloatRect roundToDevicePixels(const FloatRect&);
-
+
void drawLineForText(const IntPoint&, int width, bool printing);
void drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar);
-
+
bool paintingDisabled() const;
void setPaintingDisabled(bool);
-
+
bool updatingControlTints() const;
void setUpdatingControlTints(bool);
@@ -336,7 +340,7 @@ namespace WebCore {
void rotate(float angleInRadians);
void translate(float x, float y);
IntPoint origin();
-
+
void setURLForRect(const KURL&, const IntRect&);
void concatCTM(const TransformationMatrix&);
@@ -418,6 +422,10 @@ namespace WebCore {
GdkEventExpose* gdkExposeEvent() const;
#endif
+#if PLATFORM(HAIKU)
+ pattern getHaikuStrokeStyle();
+#endif
+
private:
void savePlatformState();
void restorePlatformState();
@@ -440,6 +448,8 @@ namespace WebCore {
void setPlatformShadow(const IntSize&, int blur, const Color&);
void clearPlatformShadow();
+ static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&);
+
int focusRingWidth() const;
int focusRingOffset() const;
const Vector<IntRect>& focusRingRects() const;
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
new file mode 100644
index 0000000..5223e05
--- /dev/null
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -0,0 +1,335 @@
+/*
+ * 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 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.
+ */
+
+#ifndef GraphicsContext3D_h
+#define GraphicsContext3D_h
+
+#include "PlatformString.h"
+
+#include <wtf/Noncopyable.h>
+
+#if PLATFORM(MAC)
+#include <OpenGL/OpenGL.h>
+
+typedef void* PlatformGraphicsContext3D;
+const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
+typedef GLuint Platform3DObject;
+const Platform3DObject NullPlatform3DObject = 0;
+#else
+typedef void* PlatformGraphicsContext3D;
+const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0;
+typedef int Platform3DObject;
+const Platform3DObject NullPlatform3DObject = 0;
+#endif
+
+namespace WebCore {
+ 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 HTMLVideoElement;
+ class ImageData;
+ class WebKitCSSMatrix;
+
+ // FIXME: ideally this would be used on all platforms.
+#if PLATFORM(CHROMIUM)
+ class GraphicsContext3DInternal;
+#endif
+
+ class GraphicsContext3D : Noncopyable {
+ public:
+ enum ShaderType { FRAGMENT_SHADER, VERTEX_SHADER };
+
+ GraphicsContext3D();
+ virtual ~GraphicsContext3D();
+
+#if PLATFORM(MAC)
+ PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; }
+ Platform3DObject platformTexture() const { return m_texture; }
+#elif PLATFORM(CHROMIUM)
+ PlatformGraphicsContext3D platformGraphicsContext3D() const;
+ Platform3DObject platformTexture() const;
+#else
+ 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
+ // like GL_FLOAT, GL_INT, etc.
+ 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 blendColor(double red, double green, double blue, double alpha);
+ void blendEquation(unsigned long mode);
+ void blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha);
+ void blendFunc(unsigned long sfactor, unsigned long dfactor);
+ 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);
+
+ unsigned long checkFramebufferStatus(unsigned long target);
+ void clear(unsigned long mask);
+ void clearColor(double red, double green, double blue, double alpha);
+ void clearDepth(double depth);
+ void clearStencil(long s);
+ void colorMask(bool red, bool green, bool blue, bool alpha);
+ void compileShader(CanvasShader*);
+
+ //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);
+
+ void copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border);
+ void copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height);
+ void cullFace(unsigned long mode);
+ void depthFunc(unsigned long func);
+ void depthMask(bool flag);
+ void depthRange(double zNear, double zFar);
+ void detachShader(CanvasProgram*, CanvasShader*);
+ void disable(unsigned long cap);
+ void disableVertexAttribArray(unsigned long index);
+ void drawArrays(unsigned long mode, long first, long count);
+ void drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset);
+
+ void enable(unsigned long cap);
+ 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 frontFace(unsigned long mode);
+ void generateMipmap(unsigned long target);
+
+ int getAttribLocation(CanvasProgram*, 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);
+
+ 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*);
+
+ // TBD
+ // void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+
+ String getShaderSource(CanvasShader*);
+ 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);
+
+ long getVertexAttribOffset(unsigned long index, unsigned long pname);
+
+ void hint(unsigned long target, unsigned long mode);
+ bool isBuffer(CanvasBuffer*);
+ bool isEnabled(unsigned long cap);
+ bool isFramebuffer(CanvasFramebuffer*);
+ bool isProgram(CanvasProgram*);
+ bool isRenderbuffer(CanvasRenderbuffer*);
+ bool isShader(CanvasShader*);
+ bool isTexture(CanvasTexture*);
+ void lineWidth(double);
+ void linkProgram(CanvasProgram*);
+ void pixelStorei(unsigned long pname, long param);
+ void polygonOffset(double factor, double units);
+
+ // TBD
+ //void readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* pixels);
+
+ 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 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);
+ void stencilMaskSeparate(unsigned long face, unsigned long mask);
+ void stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass);
+ void stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass);
+
+ // These next several functions return an error code (0 if no errors) rather than using an ExceptionCode.
+ // 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);
+ 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,
+ bool flipY, bool premultiplyAlpha);
+ int texImage2D(unsigned target, unsigned level, HTMLVideoElement* video,
+ bool flipY, bool premultiplyAlpha);
+
+ void texParameterf(unsigned target, unsigned pname, float param);
+ void texParameteri(unsigned target, unsigned pname, int param);
+
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned width, unsigned height,
+ unsigned format, unsigned type, CanvasArray* 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,
+ bool flipY, bool premultiplyAlpha);
+ int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset,
+ unsigned width, unsigned height, HTMLVideoElement* video,
+ bool flipY, bool premultiplyAlpha);
+
+ void uniform1f(long location, float x);
+ void uniform1fv(long location, float* v, int size);
+ void uniform1i(long location, int x);
+ void uniform1iv(long location, int* v, int size);
+ void uniform2f(long location, float x, float y);
+ void uniform2fv(long location, float* v, int size);
+ void uniform2i(long location, int x, int y);
+ void uniform2iv(long location, int* v, int size);
+ void uniform3f(long location, float x, float y, float z);
+ void uniform3fv(long location, float* v, int size);
+ void uniform3i(long location, int x, int y, int z);
+ void uniform3iv(long location, int* v, int size);
+ void uniform4f(long location, float x, float y, float z, float w);
+ void uniform4fv(long location, float* v, int size);
+ void uniform4i(long location, int x, int y, int z, int w);
+ void uniform4iv(long location, int* v, int size);
+ void uniformMatrix2fv(long location, bool transpose, float* value, int size);
+ 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 vertexAttrib1f(unsigned long indx, float x);
+ void vertexAttrib1fv(unsigned long indx, float* values);
+ void vertexAttrib2f(unsigned long indx, float x, float y);
+ void vertexAttrib2fv(unsigned long indx, float* values);
+ void vertexAttrib3f(unsigned long indx, float x, float y, float z);
+ void vertexAttrib3fv(unsigned long indx, float* values);
+ void vertexAttrib4f(unsigned long indx, float x, float y, float z, float w);
+ void vertexAttrib4fv(unsigned long indx, float* values);
+ void vertexAttribPointer(unsigned long indx, int size, int type, bool normalized,
+ unsigned long stride, unsigned long offset);
+
+ void viewport(long x, long y, unsigned long width, unsigned long height);
+
+ void reshape(int width, int height);
+
+ // Helpers for notification about paint events
+ void beginPaint(CanvasRenderingContext3D* context);
+ void endPaint();
+
+ // Support for buffer creation and deletion
+ unsigned createBuffer();
+ unsigned createFramebuffer();
+ unsigned createProgram();
+ unsigned createRenderbuffer();
+ unsigned createShader(ShaderType);
+ unsigned createTexture();
+
+ void deleteBuffer(unsigned);
+ void deleteFramebuffer(unsigned);
+ void deleteProgram(unsigned);
+ void deleteRenderbuffer(unsigned);
+ void deleteShader(unsigned);
+ void deleteTexture(unsigned);
+
+ private:
+ int m_currentWidth, m_currentHeight;
+
+#if PLATFORM(MAC)
+ Vector<Vector<float> > m_vertexArray;
+
+ CGLContextObj m_contextObj;
+ GLuint m_texture;
+ GLuint m_fbo;
+ GLuint m_depthBuffer;
+#endif
+
+ // FIXME: ideally this would be used on all platforms.
+#if PLATFORM(CHROMIUM)
+ friend class GraphicsContext3DInternal;
+ OwnPtr<GraphicsContext3DInternal> m_internal;
+#endif
+ };
+
+} // namespace WebCore
+
+#endif // GraphicsContext3D_h
+
diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp
index 7d43832..b375bd3 100644
--- a/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -69,10 +69,11 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
, m_usingTiledLayer(false)
, m_masksToBounds(false)
, m_drawsContent(false)
- , m_paintingPhase(GraphicsLayerPaintAllMask)
+ , m_paintingPhase(GraphicsLayerPaintAll)
, m_geometryOrientation(CompositingCoordinatesTopDown)
, m_contentsOrientation(CompositingCoordinatesTopDown)
, m_parent(0)
+ , m_maskLayer(0)
#ifndef NDEBUG
, m_repaintCount(0)
#endif
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 4d7668a..2924073 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -33,11 +33,15 @@
#include "FloatPoint.h"
#include "FloatPoint3D.h"
#include "FloatSize.h"
+#if ENABLE(3D_CANVAS)
+#include "GraphicsContext3D.h"
+#endif
#include "GraphicsLayerClient.h"
#include "IntRect.h"
#include "TransformationMatrix.h"
#include "TransformOperations.h"
#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
#if PLATFORM(MAC)
#ifdef __OBJC__
@@ -152,7 +156,7 @@ protected:
class GraphicsLayer {
public:
- static GraphicsLayer* createGraphicsLayer(GraphicsLayerClient*);
+ static PassOwnPtr<GraphicsLayer> create(GraphicsLayerClient*);
virtual ~GraphicsLayer();
@@ -180,6 +184,9 @@ public:
void removeAllChildren();
virtual void removeFromParent();
+ GraphicsLayer* maskLayer() const { return m_maskLayer; }
+ virtual void setMaskLayer(GraphicsLayer* layer) { m_maskLayer = layer; }
+
// Offset is origin of the renderer minus origin of the graphics layer (so either zero or negative).
IntSize offsetFromRenderer() const { return m_offsetFromRenderer; }
void setOffsetFromRenderer(const IntSize& offset) { m_offsetFromRenderer = offset; }
@@ -229,8 +236,8 @@ public:
virtual void setOpacity(float opacity) { m_opacity = opacity; }
// Some GraphicsLayers paint only the foreground or the background content
- GraphicsLayerPaintingPhase drawingPhase() const { return m_paintingPhase; }
- void setDrawingPhase(GraphicsLayerPaintingPhase phase) { m_paintingPhase = phase; }
+ GraphicsLayerPaintingPhase paintingPhase() const { return m_paintingPhase; }
+ void setPaintingPhase(GraphicsLayerPaintingPhase phase) { m_paintingPhase = phase; }
virtual void setNeedsDisplay() = 0;
// mark the given rect (in layer coords) as needing dispay. Never goes deep.
@@ -255,6 +262,10 @@ public:
virtual void setContentsToVideo(PlatformLayer*) { }
virtual void setContentsBackgroundColor(const Color&) { }
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*) { }
+ virtual void setGraphicsContext3DNeedsDisplay() { }
+#endif
// Callback from the underlying graphics system to draw layer contents.
void paintGraphicsLayerContents(GraphicsContext&, const IntRect& clip);
@@ -347,6 +358,8 @@ protected:
Vector<GraphicsLayer*> m_children;
GraphicsLayer* m_parent;
+ GraphicsLayer* m_maskLayer; // Reference to mask layer. We don't own this.
+
IntRect m_contentsRect;
#ifndef NDEBUG
diff --git a/WebCore/platform/graphics/GraphicsLayerClient.h b/WebCore/platform/graphics/GraphicsLayerClient.h
index 8c0b7ed..5facc94 100644
--- a/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -37,9 +37,10 @@ class IntRect;
class FloatPoint;
enum GraphicsLayerPaintingPhase {
- GraphicsLayerPaintBackgroundMask = (1 << 0),
- GraphicsLayerPaintForegroundMask = (1 << 1),
- GraphicsLayerPaintAllMask = (GraphicsLayerPaintBackgroundMask | GraphicsLayerPaintForegroundMask)
+ GraphicsLayerPaintBackground = (1 << 0),
+ GraphicsLayerPaintForeground = (1 << 1),
+ GraphicsLayerPaintMask = (1 << 2),
+ GraphicsLayerPaintAll = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
};
enum AnimatedPropertyID {
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index 2a96d3b..9432058 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -50,6 +50,11 @@ namespace WebCore {
LinearRGB
};
+ enum Multiply {
+ Premultiplied,
+ Unmultiplied
+ };
+
class ImageBuffer : public Noncopyable {
public:
// Will return a null pointer on allocation failure.
@@ -71,8 +76,11 @@ namespace WebCore {
void clearImage() { m_image.clear(); }
- PassRefPtr<ImageData> getImageData(const IntRect& rect) const;
- void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint);
+ PassRefPtr<ImageData> getUnmultipliedImageData(const IntRect&) const;
+ PassRefPtr<ImageData> getPremultipliedImageData(const IntRect&) const;
+
+ void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
+ void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint);
String toDataURL(const String& mimeType) const;
#if !PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp b/WebCore/platform/graphics/ImageSource.cpp
index df62618..bf7ae21 100644
--- a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
+++ b/WebCore/platform/graphics/ImageSource.cpp
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+ * Copyright (C) 2008, Google Inc. All rights reserved.
+ * Copyright (C) 2007-2009 Torch Mobile, Inc
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,64 +29,20 @@
#include "config.h"
#include "ImageSource.h"
-#if PLATFORM(CAIRO)
+#if PLATFORM(QT)
+#include "ImageDecoderQt.h"
+#else
+#include "ImageDecoder.h"
+#endif
-#include "BMPImageDecoder.h"
-#include "GIFImageDecoder.h"
-#include "ICOImageDecoder.h"
-#include "JPEGImageDecoder.h"
-#include "PNGImageDecoder.h"
-#include "XBMImageDecoder.h"
-#include "SharedBuffer.h"
-#include <cairo.h>
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS
+#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024)
+#endif
+#endif
namespace WebCore {
-ImageDecoder* createDecoder(const Vector<char>& data)
-{
- // We need at least 4 bytes to figure out what kind of image we're dealing with.
- int length = data.size();
- if (length < 4)
- return 0;
-
- const unsigned char* uContents = (const unsigned char*)data.data();
- const char* contents = data.data();
-
- // GIFs begin with GIF8(7 or 9).
- if (strncmp(contents, "GIF8", 4) == 0)
- return new GIFImageDecoder();
-
- // Test for PNG.
- if (uContents[0]==0x89 &&
- uContents[1]==0x50 &&
- uContents[2]==0x4E &&
- uContents[3]==0x47)
- return new PNGImageDecoder();
-
- // JPEG
- if (uContents[0]==0xFF &&
- uContents[1]==0xD8 &&
- uContents[2]==0xFF)
- return new JPEGImageDecoder();
-
- // BMP
- if (strncmp(contents, "BM", 2) == 0)
- return new BMPImageDecoder();
-
- // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
- // CURs begin with 2-byte 0 followed by 2-byte 2.
- if (!memcmp(contents, "\000\000\001\000", 4) ||
- !memcmp(contents, "\000\000\002\000", 4))
- return new ICOImageDecoder();
-
- // XBMs require 8 bytes of info.
- if (length >= 8 && strncmp(contents, "#define ", 8) == 0)
- return new XBMImageDecoder();
-
- // Give up. We don't know what the heck this is.
- return 0;
-}
-
ImageSource::ImageSource()
: m_decoder(0)
{
@@ -120,53 +78,41 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// This method will examine the data and instantiate an instance of the appropriate decoder plugin.
// If insufficient bytes are available to determine the image type, no decoder plugin will be
// made.
- if (!m_decoder)
- m_decoder = createDecoder(data->buffer());
-
- if (!m_decoder)
- return;
+ if (!m_decoder) {
+ m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data));
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+ if (m_decoder)
+ m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS);
+#endif
+ }
- m_decoder->setData(data, allDataReceived);
+ if (m_decoder)
+ m_decoder->setData(data, allDataReceived);
}
String ImageSource::filenameExtension() const
{
- if (!m_decoder)
- return String();
-
- return m_decoder->filenameExtension();
+ return m_decoder ? m_decoder->filenameExtension() : String();
}
bool ImageSource::isSizeAvailable()
{
- if (!m_decoder)
- return false;
-
- return m_decoder->isSizeAvailable();
+ return m_decoder && m_decoder->isSizeAvailable();
}
IntSize ImageSource::size() const
{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->size();
+ return m_decoder ? m_decoder->size() : IntSize();
}
IntSize ImageSource::frameSizeAtIndex(size_t index) const
{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
+ return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize();
}
int ImageSource::repetitionCount()
{
- if (!m_decoder)
- return cAnimationNone;
-
- return m_decoder->repetitionCount();
+ return m_decoder ? m_decoder->repetitionCount() : cAnimationNone;
}
size_t ImageSource::frameCount() const
@@ -176,9 +122,6 @@ size_t ImageSource::frameCount() const
NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
{
- if (!initialized())
- return 0;
-
if (!m_decoder)
return 0;
@@ -186,23 +129,16 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
return 0;
- // Cairo does not like zero height images.
- // If we have a zero height image, just pretend we don't have enough data yet.
- if (!size().height())
+ // Zero-height images can cause problems for some ports. If we have an
+ // empty image dimension, just bail.
+ if (size().isEmpty())
return 0;
+ // Return the buffer contents as a native image. For some ports, the data
+ // is already in a native container, and this just increments its refcount.
return buffer->asNewNativeImage();
}
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
-{
- if (!m_decoder)
- return false;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
-}
-
float ImageSource::frameDurationAtIndex(size_t index)
{
if (!m_decoder)
@@ -223,17 +159,23 @@ float ImageSource::frameDurationAtIndex(size_t index)
bool ImageSource::frameHasAlphaAtIndex(size_t index)
{
- // When a frame has not finished decoding, always mark it as having alpha,
- // so we don't get a black background for the undecoded sections.
- // TODO: A better solution is probably to have the underlying buffer's
- // hasAlpha() return true in these cases, since it is, in fact, technically
- // true.
- if (!frameIsCompleteAtIndex(index))
- return true;
-
- return m_decoder->frameBufferAtIndex(index)->hasAlpha();
+ // When a frame has not finished decoding, always mark it as having alpha.
+ // Ports that check the result of this function to determine their
+ // compositing op need this in order to not draw the undecoded portion as
+ // black.
+ // TODO: Perhaps we should ensure that each individual decoder returns true
+ // in this case.
+ return !frameIsCompleteAtIndex(index)
+ || m_decoder->frameBufferAtIndex(index)->hasAlpha();
}
+bool ImageSource::frameIsCompleteAtIndex(size_t index)
+{
+ if (!m_decoder)
+ return false;
+
+ RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
+ return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
}
-#endif // PLATFORM(CAIRO)
+}
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index 173d50b..eabeeab 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -51,6 +51,8 @@ class SkBitmapRef;
class PrivateAndroidImageSourceRec;
#elif PLATFORM(SKIA)
class NativeImageSkia;
+#elif PLATFORM(HAIKU)
+class BBitmap;
#elif PLATFORM(WINCE)
#include "SharedBitmap.h"
#endif
@@ -61,22 +63,14 @@ class IntSize;
class SharedBuffer;
class String;
-#if PLATFORM(WX)
-class ImageDecoder;
-typedef ImageDecoder* NativeImageSourcePtr;
-typedef const Vector<char>* NativeBytePtr;
-#if USE(WXGC)
-typedef wxGraphicsBitmap* NativeImagePtr;
-#else
-typedef wxBitmap* NativeImagePtr;
-#endif
-#elif PLATFORM(CG)
+#if PLATFORM(CG)
typedef CGImageSourceRef NativeImageSourcePtr;
typedef CGImageRef NativeImagePtr;
#elif PLATFORM(QT)
class ImageDecoderQt;
typedef ImageDecoderQt* NativeImageSourcePtr;
typedef QPixmap* NativeImagePtr;
+<<<<<<< HEAD:WebCore/platform/graphics/ImageSource.h
#elif PLATFORM(ANDROID)
#if PLATFORM(SGL)
class String;
@@ -98,18 +92,27 @@ typedef ImageDecoder* NativeImageSourcePtr;
typedef NativeImageSkia* NativeImagePtr;
#endif
#elif PLATFORM(CAIRO)
+=======
+#else
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/ImageSource.h
class ImageDecoder;
typedef ImageDecoder* NativeImageSourcePtr;
+#if PLATFORM(WX)
+#if USE(WXGC)
+typedef wxGraphicsBitmap* NativeImagePtr;
+#else
+typedef wxBitmap* NativeImagePtr;
+#endif
+#elif PLATFORM(CAIRO)
typedef cairo_surface_t* NativeImagePtr;
#elif PLATFORM(SKIA)
-class ImageDecoder;
-typedef ImageDecoder* NativeImageSourcePtr;
typedef NativeImageSkia* NativeImagePtr;
+#elif PLATFORM(HAIKU)
+typedef BBitmap* NativeImagePtr;
#elif PLATFORM(WINCE)
-class ImageDecoder;
-typedef ImageDecoder* NativeImageSourcePtr;
typedef RefPtr<SharedBitmap> NativeImagePtr;
#endif
+#endif
const int cAnimationLoopOnce = -1;
const int cAnimationNone = -2;
diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h
index e6d4816..afbfb46 100644
--- a/WebCore/platform/graphics/IntPoint.h
+++ b/WebCore/platform/graphics/IntPoint.h
@@ -55,6 +55,8 @@ class QPoint;
QT_END_NAMESPACE
#elif PLATFORM(GTK)
typedef struct _GdkPoint GdkPoint;
+#elif PLATFORM(HAIKU)
+class BPoint;
#endif
#if PLATFORM(WX)
@@ -121,6 +123,9 @@ public:
#elif PLATFORM(GTK)
IntPoint(const GdkPoint&);
operator GdkPoint() const;
+#elif PLATFORM(HAIKU)
+ explicit IntPoint(const BPoint&);
+ operator BPoint() const;
#endif
#if PLATFORM(WX)
diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h
index 0b607f5..cd912ff 100644
--- a/WebCore/platform/graphics/IntRect.h
+++ b/WebCore/platform/graphics/IntRect.h
@@ -33,7 +33,7 @@
typedef struct CGRect CGRect;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
typedef struct CGRect NSRect;
#else
@@ -49,6 +49,8 @@ class QRect;
QT_END_NAMESPACE
#elif PLATFORM(GTK)
typedef struct _GdkRectangle GdkRectangle;
+#elif PLATFORM(HAIKU)
+class BRect;
#endif
#if PLATFORM(WX)
@@ -144,6 +146,9 @@ public:
#elif PLATFORM(GTK)
IntRect(const GdkRectangle&);
operator GdkRectangle() const;
+#elif PLATFORM(HAIKU)
+ explicit IntRect(const BRect&);
+ operator BRect() const;
#endif
#if PLATFORM(CG)
@@ -156,7 +161,8 @@ public:
operator SkIRect() const;
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
operator NSRect() const;
#endif
@@ -193,7 +199,8 @@ inline bool operator!=(const IntRect& a, const IntRect& b)
IntRect enclosingIntRect(const CGRect&);
#endif
-#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+#if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \
+ || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN))
IntRect enclosingIntRect(const NSRect&);
#endif
diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h
index dc7a85d..b242784 100644
--- a/WebCore/platform/graphics/IntSize.h
+++ b/WebCore/platform/graphics/IntSize.h
@@ -47,6 +47,12 @@ typedef struct tagSIZE SIZE;
QT_BEGIN_NAMESPACE
class QSize;
QT_END_NAMESPACE
+#elif PLATFORM(HAIKU)
+class BSize;
+#endif
+
+#if PLATFORM(WX)
+class wxSize;
#endif
namespace WebCore {
@@ -113,6 +119,15 @@ public:
operator QSize() const;
#endif
+#if PLATFORM(HAIKU)
+ explicit IntSize(const BSize&);
+ operator BSize() const;
+#endif
+
+#if PLATFORM(WX)
+ IntSize(const wxSize&);
+ operator wxSize() const;
+#endif
private:
int m_width, m_height;
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index 8792640..3898386 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -35,10 +35,11 @@
#include "FrameView.h"
#include "Frame.h"
#include "Document.h"
+#include "TimeRanges.h"
#if PLATFORM(MAC)
#include "MediaPlayerPrivateQTKit.h"
-#elif PLATFORM(WINCE)
+#elif PLATFORM(WINCE) && !PLATFORM(QT)
#include "MediaPlayerPrivateWince.h"
#elif PLATFORM(WIN)
#include "MediaPlayerPrivateQuickTimeWin.h"
@@ -67,11 +68,12 @@ public:
virtual void play() { }
virtual void pause() { }
- virtual bool supportsFullscreen() const { return false; }
+ virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
virtual IntSize naturalSize() const { return IntSize(0, 0); }
virtual bool hasVideo() const { return false; }
+ virtual bool hasAudio() const { return false; }
virtual void setVisible(bool) { }
@@ -93,7 +95,7 @@ public:
virtual MediaPlayer::ReadyState readyState() const { return MediaPlayer::HaveNothing; }
virtual float maxTimeSeekable() const { return 0; }
- virtual float maxTimeBuffered() const { return 0; }
+ virtual PassRefPtr<TimeRanges> buffered() const { return TimeRanges::create(); }
virtual int dataRate() const { return 0; }
@@ -260,11 +262,19 @@ bool MediaPlayer::canLoadPoster() const
{
return m_private->canLoadPoster();
}
+<<<<<<< HEAD:WebCore/platform/graphics/MediaPlayer.cpp
+=======
+
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/MediaPlayer.cpp
void MediaPlayer::setPoster(const String& url)
{
m_private->setPoster(url);
+<<<<<<< HEAD:WebCore/platform/graphics/MediaPlayer.cpp
}
+=======
+}
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/MediaPlayer.cpp
void MediaPlayer::cancelLoad()
{
@@ -275,7 +285,11 @@ void MediaPlayer::prepareToPlay()
{
m_private->prepareToPlay();
}
+<<<<<<< HEAD:WebCore/platform/graphics/MediaPlayer.cpp
+=======
+
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/MediaPlayer.cpp
void MediaPlayer::play()
{
m_private->play();
@@ -331,11 +345,16 @@ IntSize MediaPlayer::naturalSize()
return m_private->naturalSize();
}
-bool MediaPlayer::hasVideo()
+bool MediaPlayer::hasVideo() const
{
return m_private->hasVideo();
}
+bool MediaPlayer::hasAudio() const
+{
+ return m_private->hasAudio();
+}
+
bool MediaPlayer::inMediaDocument()
{
Frame* frame = m_frameView ? m_frameView->frame() : 0;
@@ -344,6 +363,11 @@ bool MediaPlayer::inMediaDocument()
return document && document->isMediaDocument();
}
+PlatformMedia MediaPlayer::platformMedia() const
+{
+ return m_private->platformMedia();
+}
+
MediaPlayer::NetworkState MediaPlayer::networkState()
{
return m_private->networkState();
@@ -397,9 +421,9 @@ void MediaPlayer::setEndTime(float time)
m_private->setEndTime(time);
}
-float MediaPlayer::maxTimeBuffered()
+PassRefPtr<TimeRanges> MediaPlayer::buffered()
{
- return m_private->maxTimeBuffered();
+ return m_private->buffered();
}
float MediaPlayer::maxTimeSeekable()
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index d0220ed..4cc6476 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 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
@@ -38,8 +38,24 @@
#include <wtf/OwnPtr.h>
#include <wtf/Noncopyable.h>
+#ifdef __OBJC__
+@class QTMovie;
+#else
+class QTMovie;
+#endif
+
namespace WebCore {
+// Structure that will hold every native
+// types supported by the current media player.
+// We have to do that has multiple media players
+// backend can live at runtime.
+typedef struct PlatformMedia {
+ QTMovie* qtMovie;
+} PlatformMedia;
+
+static const PlatformMedia NoPlatformMedia = { 0 };
+
class ContentType;
class FrameView;
class GraphicsContext;
@@ -48,6 +64,7 @@ class IntSize;
class MediaPlayer;
class MediaPlayerPrivateInterface;
class String;
+class TimeRanges;
#if USE(ACCELERATED_COMPOSITING)
class GraphicsLayer;
@@ -109,8 +126,11 @@ public:
bool supportsFullscreen() const;
bool supportsSave() const;
+ PlatformMedia platformMedia() const;
+
IntSize naturalSize();
- bool hasVideo();
+ bool hasVideo() const;
+ bool hasAudio() const;
void setFrameView(FrameView* frameView) { m_frameView = frameView; }
FrameView* frameView() { return m_frameView; }
@@ -146,7 +166,7 @@ public:
bool preservesPitch() const;
void setPreservesPitch(bool);
- float maxTimeBuffered();
+ PassRefPtr<TimeRanges> buffered();
float maxTimeSeekable();
unsigned bytesLoaded();
diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h
index de7f75c..925e563 100644
--- a/WebCore/platform/graphics/MediaPlayerPrivate.h
+++ b/WebCore/platform/graphics/MediaPlayerPrivate.h
@@ -44,6 +44,11 @@ public:
virtual void cancelLoad() = 0;
virtual void prepareToPlay() { }
+<<<<<<< HEAD:WebCore/platform/graphics/MediaPlayerPrivate.h
+=======
+ virtual PlatformMedia platformMedia() const { return NoPlatformMedia; }
+
+>>>>>>> webkit.org at 49305:WebCore/platform/graphics/MediaPlayerPrivate.h
virtual void play() = 0;
virtual void pause() = 0;
@@ -53,6 +58,7 @@ public:
virtual IntSize naturalSize() const = 0;
virtual bool hasVideo() const = 0;
+ virtual bool hasAudio() const = 0;
virtual void setVisible(bool) = 0;
@@ -77,7 +83,7 @@ public:
virtual MediaPlayer::ReadyState readyState() const = 0;
virtual float maxTimeSeekable() const = 0;
- virtual float maxTimeBuffered() const = 0;
+ virtual PassRefPtr<TimeRanges> buffered() const = 0;
virtual int dataRate() const = 0;
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index da324bc..6b617a0 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -52,6 +52,9 @@ typedef WebCore::CairoPath PlatformPath;
#elif PLATFORM(SKIA)
class SkPath;
typedef SkPath PlatformPath;
+#elif PLATFORM(HAIKU)
+class BRegion;
+typedef BRegion PlatformPath;
#elif PLATFORM(WINCE)
namespace WebCore {
class PlatformPath;
diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h
index 02ad3ec..2f1192c 100644
--- a/WebCore/platform/graphics/Pattern.h
+++ b/WebCore/platform/graphics/Pattern.h
@@ -53,6 +53,9 @@ typedef wxGraphicsBrush* PlatformPatternPtr;
class wxBrush;
typedef wxBrush* PlatformPatternPtr;
#endif // USE(WXGC)
+#elif PLATFORM(HAIKU)
+#include <interface/GraphicsDefs.h>
+typedef pattern* PlatformPatternPtr;
#elif PLATFORM(WINCE)
typedef void* PlatformPatternPtr;
#endif
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
index c879228..2ec8abb 100644
--- a/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -48,7 +48,9 @@ using namespace std;
namespace WebCore {
SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool loading, SVGFontData* svgFontData)
- : m_unitsPerEm(defaultUnitsPerEm)
+ : m_maxCharWidth(-1)
+ , m_avgCharWidth(-1)
+ , m_unitsPerEm(defaultUnitsPerEm)
, m_platformData(f)
, m_treatAsFixedPitch(false)
#if ENABLE(SVG_FONTS)
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
index cb472b0..387a5c7 100644
--- a/WebCore/platform/graphics/SimpleFontData.h
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -2,6 +2,7 @@
* This file is part of the internal font implementation.
*
* Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2008 Torch Mobile, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,13 +28,14 @@
#include "FontPlatformData.h"
#include "GlyphPageTreeNode.h"
#include "GlyphWidthMap.h"
+#include "TextRenderingMode.h"
#include <wtf/OwnPtr.h>
#if USE(ATSUI)
typedef struct OpaqueATSUStyle* ATSUStyle;
#endif
-#if PLATFORM(WIN)
+#if PLATFORM(WIN) && !PLATFORM(WINCE)
#include <usp10.h>
#endif
@@ -45,6 +47,10 @@ typedef struct OpaqueATSUStyle* ATSUStyle;
#include <QFont>
#endif
+#if PLATFORM(HAIKU)
+#include <Font.h>
+#endif
+
namespace WebCore {
class FontDescription;
@@ -115,7 +121,7 @@ public:
#if USE(CORE_TEXT)
CTFontRef getCTFont() const;
- CFDictionaryRef getCFStringAttributes() const;
+ CFDictionaryRef getCFStringAttributes(TextRenderingMode) const;
#endif
#if USE(ATSUI)
@@ -134,17 +140,14 @@ public:
#if PLATFORM(WIN)
bool isSystemFont() const { return m_isSystemFont; }
+#if !PLATFORM(WINCE) // disable unused members to save space
SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
-
+#endif
static void setShouldApplyMacAscentHack(bool);
static bool shouldApplyMacAscentHack();
#endif
-#if PLATFORM(CAIRO)
- void setFont(cairo_t*) const;
-#endif
-
#if PLATFORM(WX)
wxFont* getWxFont() const { return m_platformData.font(); }
#endif
@@ -159,7 +162,7 @@ private:
void commonInit();
-#if PLATFORM(WIN)
+#if PLATFORM(WIN) && !PLATFORM(WINCE)
void initGDIFont();
void platformCommonDestroy();
float widthForGDIGlyph(Glyph glyph) const;
@@ -224,9 +227,11 @@ private:
#if PLATFORM(WIN)
bool m_isSystemFont;
+#if !PLATFORM(WINCE) // disable unused members to save space
mutable SCRIPT_CACHE m_scriptCache;
mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
#endif
+#endif
};
diff --git a/WebCore/platform/graphics/TextRenderingMode.h b/WebCore/platform/graphics/TextRenderingMode.h
new file mode 100644
index 0000000..4f817a4
--- /dev/null
+++ b/WebCore/platform/graphics/TextRenderingMode.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 TextRenderingMode_h
+#define TextRenderingMode_h
+
+namespace WebCore {
+
+ enum TextRenderingMode { AutoTextRendering, OptimizeSpeed, OptimizeLegibility, GeometricPrecision };
+
+} // namespace WebCore
+
+#endif // TextRenderingMode_h
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index 0f7ae79..1a951c2 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -46,7 +46,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_t* cr = context->platformContext();
cairo_save(cr);
- font->setFont(cr);
+ cairo_set_scaled_font(cr, font->platformData().scaledFont());
GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 5765546..de8afb3 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -31,7 +31,6 @@
#if PLATFORM(CAIRO)
-#include "TransformationMatrix.h"
#include "CairoPath.h"
#include "FloatRect.h"
#include "Font.h"
@@ -41,6 +40,7 @@
#include "Path.h"
#include "Pattern.h"
#include "SimpleFontData.h"
+#include "TransformationMatrix.h"
#include <cairo.h>
#include <math.h>
@@ -53,8 +53,8 @@
#elif PLATFORM(WIN)
#include <cairo-win32.h>
#endif
-#include "GraphicsContextPrivate.h"
#include "GraphicsContextPlatformPrivateCairo.h"
+#include "GraphicsContextPrivate.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
@@ -142,38 +142,6 @@ void GraphicsContext::drawRect(const IntRect& rect)
cairo_restore(cr);
}
-// FIXME: Now that this is refactored, it should be shared by all contexts.
-static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, StrokeStyle style)
-{
- // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
- // works out. For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g.,
- // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
- // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
- if (style == DottedStroke || style == DashedStroke) {
- if (p1.x() == p2.x()) {
- p1.setY(p1.y() + strokeWidth);
- p2.setY(p2.y() - strokeWidth);
- }
- else {
- p1.setX(p1.x() + strokeWidth);
- p2.setX(p2.x() - strokeWidth);
- }
- }
-
- if (static_cast<int>(strokeWidth) % 2) {
- if (p1.x() == p2.x()) {
- // We're a vertical line. Adjust our x.
- p1.setX(p1.x() + 0.5);
- p2.setX(p2.x() + 0.5);
- }
- else {
- // We're a horizontal line. Adjust our y.
- p1.setY(p1.y() + 0.5);
- p2.setY(p2.y() + 0.5);
- }
- }
-}
-
// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
@@ -239,20 +207,18 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0;
else {
- bool evenNumberOfSegments = numSegments%2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
if (remainder) {
patternOffset += patWidth - remainder;
- patternOffset += remainder/2;
- }
- else
- patternOffset = patWidth/2;
- }
- else if (!evenNumberOfSegments) {
+ patternOffset += remainder / 2;
+ } else
+ patternOffset = patWidth / 2;
+ } else if (!evenNumberOfSegments) {
if (remainder)
- patternOffset = (patWidth - remainder)/2;
+ patternOffset = (patWidth - remainder) / 2;
}
}
@@ -318,7 +284,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (w != h)
cairo_scale(cr, 1., scaleFactor);
-
+
cairo_arc_negative(cr, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, -fa * M_PI/180, -falen * M_PI/180);
if (w != h)
@@ -326,16 +292,16 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
float width = strokeThickness();
int patWidth = 0;
-
+
switch (strokeStyle()) {
- case DottedStroke:
- patWidth = static_cast<int>(width / 2);
- break;
- case DashedStroke:
- patWidth = 3 * static_cast<int>(width / 2);
- break;
- default:
- break;
+ case DottedStroke:
+ patWidth = static_cast<int>(width / 2);
+ break;
+ case DashedStroke:
+ patWidth = 3 * static_cast<int>(width / 2);
+ break;
+ default:
+ break;
}
setColor(cr, strokeColor());
@@ -349,7 +315,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
distance = static_cast<int>((M_PI * hRadius) / 2.0);
else // We are elliptical and will have to estimate the distance
distance = static_cast<int>((M_PI * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0)) / 2.0);
-
+
int remainder = distance % patWidth;
int coverage = distance - remainder;
int numSegments = coverage / patWidth;
@@ -359,7 +325,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (patWidth == 1)
patternOffset = 1.0;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -828,15 +794,15 @@ void GraphicsContext::setLineCap(LineCap lineCap)
cairo_line_cap_t cairoCap = CAIRO_LINE_CAP_BUTT;
switch (lineCap) {
- case ButtCap:
- // no-op
- break;
- case RoundCap:
- cairoCap = CAIRO_LINE_CAP_ROUND;
- break;
- case SquareCap:
- cairoCap = CAIRO_LINE_CAP_SQUARE;
- break;
+ case ButtCap:
+ // no-op
+ break;
+ case RoundCap:
+ cairoCap = CAIRO_LINE_CAP_ROUND;
+ break;
+ case SquareCap:
+ cairoCap = CAIRO_LINE_CAP_SQUARE;
+ break;
}
cairo_set_line_cap(m_data->cr, cairoCap);
}
@@ -853,15 +819,15 @@ void GraphicsContext::setLineJoin(LineJoin lineJoin)
cairo_line_join_t cairoJoin = CAIRO_LINE_JOIN_MITER;
switch (lineJoin) {
- case MiterJoin:
- // no-op
- break;
- case RoundJoin:
- cairoJoin = CAIRO_LINE_JOIN_ROUND;
- break;
- case BevelJoin:
- cairoJoin = CAIRO_LINE_JOIN_BEVEL;
- break;
+ case MiterJoin:
+ // no-op
+ break;
+ case RoundJoin:
+ cairoJoin = CAIRO_LINE_JOIN_ROUND;
+ break;
+ case BevelJoin:
+ cairoJoin = CAIRO_LINE_JOIN_BEVEL;
+ break;
}
cairo_set_line_join(m_data->cr, cairoJoin);
}
@@ -887,37 +853,37 @@ float GraphicsContext::getAlpha()
static inline cairo_operator_t toCairoOperator(CompositeOperator op)
{
switch (op) {
- case CompositeClear:
- return CAIRO_OPERATOR_CLEAR;
- case CompositeCopy:
- return CAIRO_OPERATOR_SOURCE;
- case CompositeSourceOver:
- return CAIRO_OPERATOR_OVER;
- case CompositeSourceIn:
- return CAIRO_OPERATOR_IN;
- case CompositeSourceOut:
- return CAIRO_OPERATOR_OUT;
- case CompositeSourceAtop:
- return CAIRO_OPERATOR_ATOP;
- case CompositeDestinationOver:
- return CAIRO_OPERATOR_DEST_OVER;
- case CompositeDestinationIn:
- return CAIRO_OPERATOR_DEST_IN;
- case CompositeDestinationOut:
- return CAIRO_OPERATOR_DEST_OUT;
- case CompositeDestinationAtop:
- return CAIRO_OPERATOR_DEST_ATOP;
- case CompositeXOR:
- return CAIRO_OPERATOR_XOR;
- case CompositePlusDarker:
- return CAIRO_OPERATOR_SATURATE;
- case CompositeHighlight:
- // There is no Cairo equivalent for CompositeHighlight.
- return CAIRO_OPERATOR_OVER;
- case CompositePlusLighter:
- return CAIRO_OPERATOR_ADD;
- default:
- return CAIRO_OPERATOR_SOURCE;
+ case CompositeClear:
+ return CAIRO_OPERATOR_CLEAR;
+ case CompositeCopy:
+ return CAIRO_OPERATOR_SOURCE;
+ case CompositeSourceOver:
+ return CAIRO_OPERATOR_OVER;
+ case CompositeSourceIn:
+ return CAIRO_OPERATOR_IN;
+ case CompositeSourceOut:
+ return CAIRO_OPERATOR_OUT;
+ case CompositeSourceAtop:
+ return CAIRO_OPERATOR_ATOP;
+ case CompositeDestinationOver:
+ return CAIRO_OPERATOR_DEST_OVER;
+ case CompositeDestinationIn:
+ return CAIRO_OPERATOR_DEST_IN;
+ case CompositeDestinationOut:
+ return CAIRO_OPERATOR_DEST_OUT;
+ case CompositeDestinationAtop:
+ return CAIRO_OPERATOR_DEST_ATOP;
+ case CompositeXOR:
+ return CAIRO_OPERATOR_XOR;
+ case CompositePlusDarker:
+ return CAIRO_OPERATOR_SATURATE;
+ case CompositeHighlight:
+ // There is no Cairo equivalent for CompositeHighlight.
+ return CAIRO_OPERATOR_OVER;
+ case CompositePlusLighter:
+ return CAIRO_OPERATOR_ADD;
+ default:
+ return CAIRO_OPERATOR_SOURCE;
}
}
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index c905ee8..0213944 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -138,16 +138,17 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size)
{
- ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+ ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
- unsigned char* dataSrc = cairo_image_surface_get_data(m_data.m_surface);
+ unsigned char* dataSrc = cairo_image_surface_get_data(data.m_surface);
unsigned char* dataDst = result->data()->data()->data();
- if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
- memset(dataSrc, 0, result->data()->length());
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
+ memset(dataDst, 0, result->data()->length());
int originx = rect.x();
int destx = 0;
@@ -156,8 +157,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -167,11 +168,11 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- int stride = cairo_image_surface_get_stride(m_data.m_surface);
+ int stride = cairo_image_surface_get_stride(data.m_surface);
unsigned destBytesPerRow = 4 * rect.width();
unsigned char* destRows = dataDst + desty * destBytesPerRow + destx * 4;
@@ -180,7 +181,11 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
unsigned* pixel = row + x + originx;
- Color pixelColor = colorFromPremultipliedARGB(*pixel);
+ Color pixelColor;
+ if (multiplied == Unmultiplied)
+ pixelColor = colorFromPremultipliedARGB(*pixel);
+ else
+ pixelColor = Color(*pixel);
destRows[basex] = pixelColor.red();
destRows[basex + 1] = pixelColor.green();
destRows[basex + 2] = pixelColor.blue();
@@ -192,11 +197,22 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
- ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
- unsigned char* dataDst = cairo_image_surface_get_data(m_data.m_surface);
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
+{
+ ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+
+ unsigned char* dataDst = cairo_image_surface_get_data(data.m_surface);
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -204,28 +220,28 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= size.width());
int numColumns = endx - destx;
int originy = sourceRect.y();
int desty = destPoint.y() + sourceRect.y();
ASSERT(desty >= 0);
- ASSERT(desty < m_size.height());
+ ASSERT(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- int stride = cairo_image_surface_get_stride(m_data.m_surface);
+ int stride = cairo_image_surface_get_stride(data.m_surface);
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
for (int y = 0; y < numRows; ++y) {
@@ -237,12 +253,25 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
srcRows[basex + 1],
srcRows[basex + 2],
srcRows[basex + 3]);
- *pixel = premultipliedARGBFromColor(pixelColor);
+ if (multiplied == Unmultiplied)
+ *pixel = premultipliedARGBFromColor(pixelColor);
+ else
+ *pixel = pixelColor.rgb();
}
srcRows += srcBytesPerRow;
}
}
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
static cairo_status_t writeFunction(void* closure, const unsigned char* data, unsigned int length)
{
Vector<char>* in = reinterpret_cast<Vector<char>*>(closure);
diff --git a/WebCore/platform/graphics/cg/ColorCG.cpp b/WebCore/platform/graphics/cg/ColorCG.cpp
index 0465c0b..40aacc5 100644
--- a/WebCore/platform/graphics/cg/ColorCG.cpp
+++ b/WebCore/platform/graphics/cg/ColorCG.cpp
@@ -29,6 +29,7 @@
#if PLATFORM(CG)
#include <wtf/Assertions.h>
+#include <wtf/RetainPtr.h>
#include <ApplicationServices/ApplicationServices.h>
namespace WebCore {
@@ -75,13 +76,12 @@ CGColorRef createCGColor(const Color& c)
CMProfileRef prof = NULL;
CMGetSystemProfile(&prof);
- CGColorSpaceRef rgbSpace = CGColorSpaceCreateWithPlatformColorSpace(prof);
+ RetainPtr<CGColorSpaceRef> rgbSpace(AdoptCF, CGColorSpaceCreateWithPlatformColorSpace(prof));
- if (rgbSpace != NULL)
- {
- float components[4] = {c.red() / 255.0f, c.green() / 255.0f, c.blue() / 255.0f, c.alpha() / 255.0f};
- color = CGColorCreate(rgbSpace, components);
- CGColorSpaceRelease(rgbSpace);
+ if (rgbSpace) {
+ CGFloat components[4] = { static_cast<CGFloat>(c.red()) / 255, static_cast<CGFloat>(c.green()) / 255,
+ static_cast<CGFloat>(c.blue()) / 255, static_cast<CGFloat>(c.alpha()) / 255 };
+ color = CGColorCreate(rgbSpace.get(), components);
}
CMCloseProfile(prof);
diff --git a/WebCore/platform/graphics/cg/GradientCG.cpp b/WebCore/platform/graphics/cg/GradientCG.cpp
index c189fd5..05a0aad 100644
--- a/WebCore/platform/graphics/cg/GradientCG.cpp
+++ b/WebCore/platform/graphics/cg/GradientCG.cpp
@@ -58,17 +58,14 @@ CGShadingRef Gradient::platformGradient()
const CGFloat intervalRanges[2] = { 0, 1 };
const CGFloat colorComponentRanges[4 * 2] = { 0, 1, 0, 1, 0, 1, 0, 1 };
const CGFunctionCallbacks gradientCallbacks = { 0, gradientCallback, 0 };
- CGFunctionRef colorFunction = CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks);
+ RetainPtr<CGFunctionRef> colorFunction(AdoptCF, CGFunctionCreate(this, 1, intervalRanges, 4, colorComponentRanges, &gradientCallbacks));
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ static CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
if (m_radial)
- m_gradient = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction, true, true);
+ m_gradient = CGShadingCreateRadial(colorSpace, m_p0, m_r0, m_p1, m_r1, colorFunction.get(), true, true);
else
- m_gradient = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction, true, true);
-
- CGColorSpaceRelease(colorSpace);
- CGFunctionRelease(colorFunction);
+ m_gradient = CGShadingCreateAxial(colorSpace, m_p0, m_p1, colorFunction.get(), true, true);
return m_gradient;
}
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index ab8eb3c..1b843e4 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -28,14 +28,15 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "TransformationMatrix.h"
#include "FloatConversion.h"
-#include "GraphicsContextPrivate.h"
#include "GraphicsContextPlatformPrivateCG.h"
+#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "KURL.h"
#include "Path.h"
#include "Pattern.h"
+#include "TransformationMatrix.h"
+
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGPDFContext.h>
#include <wtf/MathExtras.h>
@@ -86,7 +87,7 @@ CGContextRef GraphicsContext::platformContext() const
{
ASSERT(!paintingDisabled());
ASSERT(m_data->m_cgContext);
- return m_data->m_cgContext;
+ return m_data->m_cgContext.get();
}
void GraphicsContext::savePlatformState()
@@ -178,19 +179,19 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
int patWidth = 0;
switch (strokeStyle()) {
- case NoStroke:
- case SolidStroke:
- break;
- case DottedStroke:
- patWidth = (int)width;
- break;
- case DashedStroke:
- patWidth = 3 * (int)width;
- break;
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = (int)width;
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)width;
+ break;
}
CGContextRef context = platformContext();
-
+
if (shouldAntialias())
CGContextSetShouldAntialias(context, false);
@@ -221,7 +222,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -235,7 +236,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
patternOffset = (patWidth - remainder)/2;
}
}
-
+
const CGFloat dottedLine[2] = { patWidth, patWidth };
CGContextSetLineDash(context, patternOffset, dottedLine, 2);
}
@@ -248,7 +249,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth)
CGContextRestoreGState(context);
-
+
if (shouldAntialias())
CGContextSetShouldAntialias(context, true);
}
@@ -263,7 +264,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
if (paintingDisabled())
return;
-
+
CGContextRef context = platformContext();
CGContextBeginPath(context);
float r = (float)rect.width() / 2;
@@ -275,25 +276,25 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
-{
+{
if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f)
return;
-
+
CGContextRef context = platformContext();
CGContextSaveGState(context);
CGContextBeginPath(context);
CGContextSetShouldAntialias(context, false);
-
+
int x = rect.x();
int y = rect.y();
float w = (float)rect.width();
float h = (float)rect.height();
float scaleFactor = h / w;
float reverseScaleFactor = w / h;
-
+
if (w != h)
scale(FloatSize(1, scaleFactor));
-
+
float hRadius = w / 2;
float vRadius = h / 2;
float fa = startAngle;
@@ -304,22 +305,21 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (w != h)
scale(FloatSize(1, reverseScaleFactor));
-
-
+
float width = strokeThickness();
int patWidth = 0;
-
+
switch (strokeStyle()) {
- case DottedStroke:
- patWidth = (int)(width / 2);
- break;
- case DashedStroke:
- patWidth = 3 * (int)(width / 2);
- break;
- default:
- break;
+ case DottedStroke:
+ patWidth = (int)(width / 2);
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)(width / 2);
+ break;
+ default:
+ break;
}
-
+
if (patWidth) {
// Example: 80 pixels with a width of 30 pixels.
// Remainder is 20. The maximum pixels of line we could paint
@@ -329,7 +329,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
distance = static_cast<int>((piFloat * hRadius) / 2.0f);
else // We are elliptical and will have to estimate the distance
distance = static_cast<int>((piFloat * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0f)) / 2.0f);
-
+
int remainder = distance % patWidth;
int coverage = distance - remainder;
int numSegments = coverage / patWidth;
@@ -339,7 +339,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -353,13 +353,13 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
patternOffset = (patWidth - remainder) / 2.0f;
}
}
-
+
const CGFloat dottedLine[2] = { patWidth, patWidth };
CGContextSetLineDash(context, patternOffset, dottedLine, 2);
}
CGContextStrokePath(context);
-
+
CGContextRestoreGState(context);
}
@@ -375,7 +375,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, antialiased);
-
+
CGContextBeginPath(context);
CGContextMoveToPoint(context, points[0].x(), points[0].y());
for (size_t i = 1; i < npoints; i++)
@@ -383,7 +383,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
CGContextClosePath(context);
drawPath();
-
+
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, shouldAntialias());
}
@@ -391,35 +391,31 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
void GraphicsContext::applyStrokePattern()
{
CGContextRef cgContext = platformContext();
-
- CGPatternRef platformPattern = m_common->state.strokePattern.get()->createPlatformPattern(getCTM());
+
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern.get()->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
- CGContextSetStrokeColorSpace(cgContext, patternSpace);
- CGColorSpaceRelease(patternSpace);
+ RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0));
+ CGContextSetStrokeColorSpace(cgContext, patternSpace.get());
const CGFloat patternAlpha = 1;
- CGContextSetStrokePattern(cgContext, platformPattern, &patternAlpha);
- CGPatternRelease(platformPattern);
+ CGContextSetStrokePattern(cgContext, platformPattern.get(), &patternAlpha);
}
void GraphicsContext::applyFillPattern()
{
CGContextRef cgContext = platformContext();
- CGPatternRef platformPattern = m_common->state.fillPattern.get()->createPlatformPattern(getCTM());
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern.get()->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(0);
- CGContextSetFillColorSpace(cgContext, patternSpace);
- CGColorSpaceRelease(patternSpace);
+ RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0));
+ CGContextSetFillColorSpace(cgContext, patternSpace.get());
const CGFloat patternAlpha = 1;
- CGContextSetFillPattern(cgContext, platformPattern, &patternAlpha);
- CGPatternRelease(platformPattern);
+ CGContextSetFillPattern(cgContext, platformPattern.get(), &patternAlpha);
}
static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPathDrawingMode& mode)
@@ -463,7 +459,7 @@ void GraphicsContext::drawPath()
strokePath();
return;
}
-
+
if (state.fillColorSpace == PatternColorSpace)
applyFillPattern();
if (state.strokeColorSpace == PatternColorSpace)
@@ -599,7 +595,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
CGRect rects[2] = { CGContextGetClipBoundingBox(platformContext()), rect };
CGContextBeginPath(platformContext());
CGContextAddRects(platformContext(), rects, 2);
@@ -610,7 +606,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
CGContextBeginPath(platformContext());
CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
CGContextAddEllipseInRect(platformContext(), rect);
@@ -639,13 +635,13 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
clip(rect);
CGContextRef context = platformContext();
-
+
// Add outer ellipse
CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()));
// Add inner ellipse.
CGContextAddEllipseInRect(context, CGRectMake(rect.x() + thickness, rect.y() + thickness,
rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
-
+
CGContextEOClip(context);
}
@@ -653,7 +649,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer
{
if (paintingDisabled())
return;
-
+
CGContextTranslateCTM(platformContext(), rect.x(), rect.y() + rect.height());
CGContextScaleCTM(platformContext(), 1, -1);
CGContextClipToMask(platformContext(), FloatRect(FloatPoint(), rect.size()), imageBuffer->image()->getCGImageRef());
@@ -731,12 +727,11 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
if (!color.isValid())
CGContextSetShadow(context, CGSizeMake(width, height), blurRadius);
else {
- CGColorRef colorCG = createCGColor(color);
+ RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColor(color));
CGContextSetShadowWithColor(context,
CGSizeMake(width, height),
- blurRadius,
- colorCG);
- CGColorRelease(colorCG);
+ blurRadius,
+ colorCG.get());
}
}
@@ -799,15 +794,15 @@ void GraphicsContext::setLineCap(LineCap cap)
if (paintingDisabled())
return;
switch (cap) {
- case ButtCap:
- CGContextSetLineCap(platformContext(), kCGLineCapButt);
- break;
- case RoundCap:
- CGContextSetLineCap(platformContext(), kCGLineCapRound);
- break;
- case SquareCap:
- CGContextSetLineCap(platformContext(), kCGLineCapSquare);
- break;
+ case ButtCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapButt);
+ break;
+ case RoundCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapRound);
+ break;
+ case SquareCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapSquare);
+ break;
}
}
@@ -821,15 +816,15 @@ void GraphicsContext::setLineJoin(LineJoin join)
if (paintingDisabled())
return;
switch (join) {
- case MiterJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
- break;
- case RoundJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinRound);
- break;
- case BevelJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinBevel);
- break;
+ case MiterJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
+ break;
+ case RoundJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinRound);
+ break;
+ case BevelJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinBevel);
+ break;
}
}
@@ -858,7 +853,7 @@ void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
return;
-
+
CGContextBeginPath(platformContext());
CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
CGContextAddPath(platformContext(), path.platformPath());
@@ -909,9 +904,9 @@ TransformationMatrix GraphicsContext::getCTM() const
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
{
- // It is not enough just to round to pixels in device space. The rotation part of the
+ // It is not enough just to round to pixels in device space. The rotation part of the
// affine transform matrix to device space can mess with this conversion if we have a
- // rotating image like the hands of the world clock widget. We just need the scale, so
+ // rotating image like the hands of the world clock widget. We just need the scale, so
// we get the affine transform matrix and extract the scale.
if (m_data->m_userToDeviceTransformKnownToBeIdentity)
@@ -934,11 +929,11 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
deviceOrigin.y = roundf(deviceOrigin.y);
deviceLowerRight.x = roundf(deviceLowerRight.x);
deviceLowerRight.y = roundf(deviceLowerRight.y);
-
+
// Don't let the height or width round to 0 unless either was originally 0
- if (deviceOrigin.y == deviceLowerRight.y && rect.height() != 0)
+ if (deviceOrigin.y == deviceLowerRight.y && rect.height())
deviceLowerRight.y += 1;
- if (deviceOrigin.x == deviceLowerRight.x && rect.width() != 0)
+ if (deviceOrigin.x == deviceLowerRight.x && rect.width())
deviceLowerRight.x += 1;
FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x / deviceScaleX, deviceOrigin.y / deviceScaleY);
@@ -984,13 +979,13 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
}
}
}
-
+
if (fillColor() != strokeColor())
setCGFillColor(platformContext(), strokeColor());
CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
if (fillColor() != strokeColor())
setCGFillColor(platformContext(), fillColor());
-
+
if (restoreAntialiasMode)
CGContextSetShouldAntialias(platformContext(), true);
}
@@ -999,51 +994,50 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
if (paintingDisabled())
return;
-
- CFURLRef urlRef = link.createCFURL();
- if (urlRef) {
- CGContextRef context = platformContext();
-
- // Get the bounding box to handle clipping.
- CGRect box = CGContextGetClipBoundingBox(context);
-
- IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height);
- IntRect rect = destRect;
- rect.intersect(intBox);
-
- CGPDFContextSetURLForRect(context, urlRef,
- CGRectApplyAffineTransform(rect, CGContextGetCTM(context)));
-
- CFRelease(urlRef);
- }
+
+ RetainPtr<CFURLRef> urlRef(AdoptCF, link.createCFURL());
+ if (!urlRef)
+ return;
+
+ CGContextRef context = platformContext();
+
+ // Get the bounding box to handle clipping.
+ CGRect box = CGContextGetClipBoundingBox(context);
+
+ IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height);
+ IntRect rect = destRect;
+ rect.intersect(intBox);
+
+ CGPDFContextSetURLForRect(context, urlRef.get(),
+ CGRectApplyAffineTransform(rect, CGContextGetCTM(context)));
}
void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
{
if (paintingDisabled())
return;
-
+
CGInterpolationQuality quality = kCGInterpolationDefault;
switch (mode) {
- case InterpolationDefault:
- quality = kCGInterpolationDefault;
- break;
- case InterpolationNone:
- quality = kCGInterpolationNone;
- break;
- case InterpolationLow:
- quality = kCGInterpolationLow;
- break;
-
- // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
- case InterpolationMedium:
+ case InterpolationDefault:
+ quality = kCGInterpolationDefault;
+ break;
+ case InterpolationNone:
+ quality = kCGInterpolationNone;
+ break;
+ case InterpolationLow:
+ quality = kCGInterpolationLow;
+ break;
+
+ // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
+ case InterpolationMedium:
#if HAVE(CG_INTERPOLATION_MEDIUM)
- quality = kCGInterpolationMedium;
- break;
+ quality = kCGInterpolationMedium;
+ break;
#endif
- case InterpolationHigh:
- quality = kCGInterpolationHigh;
- break;
+ case InterpolationHigh:
+ quality = kCGInterpolationHigh;
+ break;
}
CGContextSetInterpolationQuality(platformContext(), quality);
}
@@ -1055,18 +1049,18 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
CGInterpolationQuality quality = CGContextGetInterpolationQuality(platformContext());
switch (quality) {
- case kCGInterpolationDefault:
- return InterpolationDefault;
- case kCGInterpolationNone:
- return InterpolationNone;
- case kCGInterpolationLow:
- return InterpolationLow;
+ case kCGInterpolationDefault:
+ return InterpolationDefault;
+ case kCGInterpolationNone:
+ return InterpolationNone;
+ case kCGInterpolationLow:
+ return InterpolationLow;
#if HAVE(CG_INTERPOLATION_MEDIUM)
- case kCGInterpolationMedium:
- return InterpolationMedium;
+ case kCGInterpolationMedium:
+ return InterpolationMedium;
#endif
- case kCGInterpolationHigh:
- return InterpolationHigh;
+ case kCGInterpolationHigh:
+ return InterpolationHigh;
}
return InterpolationDefault;
}
@@ -1079,32 +1073,32 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
// Wow, wish CG had used bits here.
CGContextRef context = platformContext();
switch (mode) {
- case cTextInvisible: // Invisible
- CGContextSetTextDrawingMode(context, kCGTextInvisible);
- break;
- case cTextFill: // Fill
- CGContextSetTextDrawingMode(context, kCGTextFill);
- break;
- case cTextStroke: // Stroke
- CGContextSetTextDrawingMode(context, kCGTextStroke);
- break;
- case 3: // Fill | Stroke
- CGContextSetTextDrawingMode(context, kCGTextFillStroke);
- break;
- case cTextClip: // Clip
- CGContextSetTextDrawingMode(context, kCGTextClip);
- break;
- case 5: // Fill | Clip
- CGContextSetTextDrawingMode(context, kCGTextFillClip);
- break;
- case 6: // Stroke | Clip
- CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
- break;
- case 7: // Fill | Stroke | Clip
- CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
- break;
- default:
- break;
+ case cTextInvisible: // Invisible
+ CGContextSetTextDrawingMode(context, kCGTextInvisible);
+ break;
+ case cTextFill: // Fill
+ CGContextSetTextDrawingMode(context, kCGTextFill);
+ break;
+ case cTextStroke: // Stroke
+ CGContextSetTextDrawingMode(context, kCGTextStroke);
+ break;
+ case 3: // Fill | Stroke
+ CGContextSetTextDrawingMode(context, kCGTextFillStroke);
+ break;
+ case cTextClip: // Clip
+ CGContextSetTextDrawingMode(context, kCGTextClip);
+ break;
+ case 5: // Fill | Clip
+ CGContextSetTextDrawingMode(context, kCGTextFillClip);
+ break;
+ case 6: // Stroke | Clip
+ CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
+ break;
+ case 7: // Fill | Stroke | Clip
+ CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
+ break;
+ default:
+ break;
}
}
@@ -1138,54 +1132,54 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
#ifndef BUILDING_ON_TIGER // Tiger's setCompositeOperation() is defined in GraphicsContextMac.mm.
void GraphicsContext::setCompositeOperation(CompositeOperator mode)
-{
+{
if (paintingDisabled())
return;
- CGBlendMode target = kCGBlendModeNormal;
+ CGBlendMode target = kCGBlendModeNormal;
switch (mode) {
- case CompositeClear:
- target = kCGBlendModeClear;
- break;
- case CompositeCopy:
- target = kCGBlendModeCopy;
- break;
- case CompositeSourceOver:
- //kCGBlendModeNormal
- break;
- case CompositeSourceIn:
- target = kCGBlendModeSourceIn;
- break;
- case CompositeSourceOut:
- target = kCGBlendModeSourceOut;
- break;
- case CompositeSourceAtop:
- target = kCGBlendModeSourceAtop;
- break;
- case CompositeDestinationOver:
- target = kCGBlendModeDestinationOver;
- break;
- case CompositeDestinationIn:
- target = kCGBlendModeDestinationIn;
- break;
- case CompositeDestinationOut:
- target = kCGBlendModeDestinationOut;
- break;
- case CompositeDestinationAtop:
- target = kCGBlendModeDestinationAtop;
- break;
- case CompositeXOR:
- target = kCGBlendModeXOR;
- break;
- case CompositePlusDarker:
- target = kCGBlendModePlusDarker;
- break;
- case CompositeHighlight:
- // currently unsupported
- break;
- case CompositePlusLighter:
- target = kCGBlendModePlusLighter;
- break;
+ case CompositeClear:
+ target = kCGBlendModeClear;
+ break;
+ case CompositeCopy:
+ target = kCGBlendModeCopy;
+ break;
+ case CompositeSourceOver:
+ //kCGBlendModeNormal
+ break;
+ case CompositeSourceIn:
+ target = kCGBlendModeSourceIn;
+ break;
+ case CompositeSourceOut:
+ target = kCGBlendModeSourceOut;
+ break;
+ case CompositeSourceAtop:
+ target = kCGBlendModeSourceAtop;
+ break;
+ case CompositeDestinationOver:
+ target = kCGBlendModeDestinationOver;
+ break;
+ case CompositeDestinationIn:
+ target = kCGBlendModeDestinationIn;
+ break;
+ case CompositeDestinationOut:
+ target = kCGBlendModeDestinationOut;
+ break;
+ case CompositeDestinationAtop:
+ target = kCGBlendModeDestinationAtop;
+ break;
+ case CompositeXOR:
+ target = kCGBlendModeXOR;
+ break;
+ case CompositePlusDarker:
+ target = kCGBlendModePlusDarker;
+ break;
+ case CompositeHighlight:
+ // currently unsupported
+ break;
+ case CompositePlusLighter:
+ target = kCGBlendModePlusLighter;
+ break;
}
CGContextSetBlendMode(platformContext(), target);
}
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
index f63a8dd..38c5506 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -38,12 +38,10 @@ public:
#endif
, m_userToDeviceTransformKnownToBeIdentity(false)
{
- CGContextRetain(m_cgContext);
}
~GraphicsContextPlatformPrivate()
{
- CGContextRelease(m_cgContext);
}
#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
@@ -80,7 +78,7 @@ public:
bool m_shouldIncludeChildWindows;
#endif
- CGContextRef m_cgContext;
+ RetainPtr<CGContextRef> m_cgContext;
bool m_userToDeviceTransformKnownToBeIdentity;
};
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 6db7e88..b1896f8 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -65,37 +65,37 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
bytesPerRow *= 4;
}
- m_data.m_data = tryFastCalloc(size.height(), bytesPerRow);
+ if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
+ return;
+
ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
- CGColorSpaceRef colorSpace;
+ RetainPtr<CGColorSpaceRef> colorSpace;
switch(imageColorSpace) {
case DeviceRGB:
- colorSpace = CGColorSpaceCreateDeviceRGB();
+ colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
break;
case GrayScale:
- colorSpace = CGColorSpaceCreateDeviceGray();
+ colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
break;
#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER)
case LinearRGB:
- colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear);
+ colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
break;
#endif
default:
- colorSpace = CGColorSpaceCreateDeviceRGB();
+ colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
break;
}
- CGContextRef cgContext = CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
- colorSpace, (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast);
- CGColorSpaceRelease(colorSpace);
+ RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
+ colorSpace.get(), (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast));
if (!cgContext)
return;
- m_context.set(new GraphicsContext(cgContext));
+ m_context.set(new GraphicsContext(cgContext.get()));
m_context->scale(FloatSize(1, -1));
m_context->translate(0, -size.height());
- CGContextRelease(cgContext);
success = true;
}
@@ -122,12 +122,13 @@ Image* ImageBuffer::image() const
return m_image.get();
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
{
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
unsigned char* data = result->data()->data()->data();
- if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originx = rect.x();
@@ -137,8 +138,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -148,20 +149,21 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- unsigned srcBytesPerRow = 4 * m_size.width();
+ unsigned srcBytesPerRow = 4 * size.width();
unsigned destBytesPerRow = 4 * rect.width();
// ::create ensures that all ImageBuffers have valid data, so we don't need to check it here.
- unsigned char* srcRows = reinterpret_cast<unsigned char*>(m_data.m_data) + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4;
unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
- if (unsigned char alpha = srcRows[basex + 3]) {
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha) {
destRows[basex] = (srcRows[basex] * 255) / alpha;
destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
@@ -175,7 +177,18 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -183,36 +196,36 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= size.width());
int numColumns = endx - destx;
int originy = sourceRect.y();
int desty = destPoint.y() + sourceRect.y();
ASSERT(desty >= 0);
- ASSERT(desty < m_size.height());
+ ASSERT(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- unsigned destBytesPerRow = 4 * m_size.width();
+ unsigned destBytesPerRow = 4 * size.width();
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
- unsigned char* destRows = reinterpret_cast<unsigned char*>(m_data.m_data) + desty * destBytesPerRow + destx * 4;
+ unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
unsigned char alpha = srcRows[basex + 3];
- if (alpha != 255) {
+ if (multiplied == Unmultiplied && alpha != 255) {
destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
@@ -225,6 +238,16 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
}
}
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
{
#if PLATFORM(MAC)
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
index a5620e8..4da7018 100644
--- a/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -101,30 +101,29 @@ BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
void BitmapImage::checkForSolidColor()
{
m_checkedForSolidColor = true;
- if (frameCount() > 1)
+ if (frameCount() > 1) {
m_isSolidColor = false;
- else {
- CGImageRef image = frameAtIndex(0);
-
- // Currently we only check for solid color in the important special case of a 1x1 image.
- if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
- unsigned char pixel[4]; // RGBA
- CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
- CGContextRef bmap = CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), space,
- kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
- if (bmap) {
- GraphicsContext(bmap).setCompositeOperation(CompositeCopy);
- CGRect dst = { {0, 0}, {1, 1} };
- CGContextDrawImage(bmap, dst, image);
- if (pixel[3] == 0)
- m_solidColor = Color(0, 0, 0, 0);
- else
- m_solidColor = Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
- m_isSolidColor = true;
- CFRelease(bmap);
- }
- CFRelease(space);
- }
+ return;
+ }
+
+ CGImageRef image = frameAtIndex(0);
+
+ // Currently we only check for solid color in the important special case of a 1x1 image.
+ if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
+ unsigned char pixel[4]; // RGBA
+ static CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+ RetainPtr<CGContextRef> bmap(AdoptCF, CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), space,
+ kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big));
+ if (!bmap)
+ return;
+ GraphicsContext(bmap.get()).setCompositeOperation(CompositeCopy);
+ CGRect dst = { {0, 0}, {1, 1} };
+ CGContextDrawImage(bmap.get(), dst, image);
+ if (pixel[3] == 0)
+ m_solidColor = Color(0, 0, 0, 0);
+ else
+ m_solidColor = Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
+ m_isSolidColor = true;
}
}
@@ -252,14 +251,14 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
CGImageRef tileImage = nativeImageForCurrentFrame();
float h = CGImageGetHeight(tileImage);
- CGImageRef subImage;
+ RetainPtr<CGImageRef> subImage;
if (tileRect.size() == size())
subImage = tileImage;
else {
// Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen
// because sub-images are only used for border-image, which only renders when the image is fully decoded.
ASSERT(h == height());
- subImage = CGImageCreateWithImageInRect(tileImage, tileRect);
+ subImage.adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect));
}
#ifndef BUILDING_ON_TIGER
@@ -275,7 +274,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
#else
if (w == size().width() && h == size().height())
#endif
- CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage);
+ CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get());
else {
#endif
@@ -288,39 +287,31 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
// The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
- CGPatternRef pattern = CGPatternCreate(subImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()),
- matrix, tileRect.width(), tileRect.height(),
- kCGPatternTilingConstantSpacing, true, &patternCallbacks);
- if (pattern == NULL) {
- if (subImage != tileImage)
- CGImageRelease(subImage);
+ RetainPtr<CGPatternRef> pattern(AdoptCF, CGPatternCreate(subImage.get(), CGRectMake(0, 0, tileRect.width(), tileRect.height()),
+ matrix, tileRect.width(), tileRect.height(),
+ kCGPatternTilingConstantSpacing, true, &patternCallbacks));
+ if (!pattern) {
ctxt->restore();
return;
}
- CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+ RetainPtr<CGColorSpaceRef> patternSpace(AdoptCF, CGColorSpaceCreatePattern(0));
CGFloat alpha = 1;
- CGColorRef color = CGColorCreateWithPattern(patternSpace, pattern, &alpha);
- CGContextSetFillColorSpace(context, patternSpace);
- CGColorSpaceRelease(patternSpace);
- CGPatternRelease(pattern);
+ RetainPtr<CGColorRef> color(AdoptCF, CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha));
+ CGContextSetFillColorSpace(context, patternSpace.get());
// FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
wkSetPatternBaseCTM(context, CGAffineTransformIdentity);
CGContextSetPatternPhase(context, CGSizeZero);
- CGContextSetFillColorWithColor(context, color);
+ CGContextSetFillColorWithColor(context, color.get());
CGContextFillRect(context, CGContextGetClipBoundingBox(context));
-
- CGColorRelease(color);
-
+
#ifndef BUILDING_ON_TIGER
}
#endif
- if (subImage != tileImage)
- CGImageRelease(subImage);
ctxt->restore();
if (imageObserver())
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index b716060..66246fe 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -109,18 +109,16 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
#if PLATFORM(MAC)
// 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.
- CFDataRef cfData = data->createCFData();
+ RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData());
#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.
data->ref();
CFAllocatorContext context = {0, data, 0, 0, 0, 0, 0, &sharedBufferDerefCallback, 0};
- CFAllocatorRef derefAllocator = CFAllocatorCreate(kCFAllocatorDefault, &context);
- CFDataRef cfData = CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data->data()), data->size(), derefAllocator);
- CFRelease(derefAllocator);
+ RetainPtr<CFAllocatorRef> derefAllocator(AdoptCF, CFAllocatorCreate(kCFAllocatorDefault, &context));
+ RetainPtr<CFDataRef> cfData(AdoptCF, CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data->data()), data->size(), derefAllocator.get()));
#endif
- CGImageSourceUpdateData(m_decoder, cfData, allDataReceived);
- CFRelease(cfData);
+ CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived);
}
String ImageSource::filenameExtension() const
@@ -138,12 +136,11 @@ bool ImageSource::isSizeAvailable()
// Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
if (imageSourceStatus >= kCGImageStatusIncomplete) {
- CFDictionaryRef image0Properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> image0Properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions()));
if (image0Properties) {
- CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties, kCGImagePropertyPixelWidth);
- CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties, kCGImagePropertyPixelHeight);
+ CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelWidth);
+ CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties.get(), kCGImagePropertyPixelHeight);
result = widthNumber && heightNumber;
- CFRelease(image0Properties);
}
}
@@ -153,17 +150,16 @@ bool ImageSource::isSizeAvailable()
IntSize ImageSource::frameSizeAtIndex(size_t index) const
{
IntSize result;
- CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions()));
if (properties) {
int w = 0, h = 0;
- CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth);
+ CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
if (num)
CFNumberGetValue(num, kCFNumberIntType, &w);
- num = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight);
+ num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
if (num)
CFNumberGetValue(num, kCFNumberIntType, &h);
result = IntSize(w, h);
- CFRelease(properties);
}
return result;
}
@@ -180,17 +176,15 @@ int ImageSource::repetitionCount()
return result;
// A property with value 0 means loop forever.
- CFDictionaryRef properties = CGImageSourceCopyProperties(m_decoder, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyProperties(m_decoder, imageSourceOptions()));
if (properties) {
- CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
+ CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (gifProperties) {
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount);
if (num)
CFNumberGetValue(num, kCFNumberIntType, &result);
} else
result = cAnimationNone; // Turns out we're not a GIF after all, so we don't animate.
-
- CFRelease(properties);
}
return result;
@@ -206,20 +200,19 @@ CGImageRef ImageSource::createFrameAtIndex(size_t index)
if (!initialized())
return 0;
- CGImageRef image = CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions());
+ RetainPtr<CGImageRef> image(AdoptCF, CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions()));
CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
if (!imageUTI || !CFEqual(imageUTI, xbmUTI))
- return image;
+ return image.releaseRef();
// If it is an xbm image, mask out all the white areas to render them transparent.
const CGFloat maskingColors[6] = {255, 255, 255, 255, 255, 255};
- CGImageRef maskedImage = CGImageCreateWithMaskingColors(image, maskingColors);
+ RetainPtr<CGImageRef> maskedImage(AdoptCF, CGImageCreateWithMaskingColors(image.get(), maskingColors));
if (!maskedImage)
- return image;
-
- CGImageRelease(image);
- return maskedImage;
+ return image.releaseRef();
+
+ return maskedImage.releaseRef();
}
bool ImageSource::frameIsCompleteAtIndex(size_t index)
@@ -233,15 +226,14 @@ float ImageSource::frameDurationAtIndex(size_t index)
return 0;
float duration = 0;
- CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions());
+ RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions()));
if (properties) {
- CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
+ CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
if (typeProperties) {
CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(typeProperties, kCGImagePropertyGIFDelayTime);
if (num)
CFNumberGetValue(num, kCFNumberFloatType, &duration);
}
- CFRelease(properties);
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
index 858b18e..2f5c15e 100644
--- a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -68,16 +68,14 @@ bool PDFDocumentImage::dataChanged(bool allDataReceived)
#if PLATFORM(MAC)
// 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.
- CFDataRef data = this->data()->createCFData();
+ RetainPtr<CFDataRef> data(AdoptCF, this->data()->createCFData());
#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.
- CFDataRef data = CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(this->data()->data()), this->data()->size(), kCFAllocatorNull);
+ RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(this->data()->data()), this->data()->size(), kCFAllocatorNull));
#endif
- CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data);
- CFRelease(data);
- m_document = CGPDFDocumentCreateWithProvider(dataProvider);
- CGDataProviderRelease(dataProvider);
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get()));
+ m_document = CGPDFDocumentCreateWithProvider(dataProvider.get());
setCurrentPage(0);
}
return m_document; // return true if size is available
diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp
index 5812cea..3b05641 100644
--- a/WebCore/platform/graphics/cg/PathCG.cpp
+++ b/WebCore/platform/graphics/cg/PathCG.cpp
@@ -49,9 +49,8 @@ static size_t putBytesNowhere(void*, const void*, size_t count)
static CGContextRef createScratchContext()
{
CGDataConsumerCallbacks callbacks = { putBytesNowhere, 0 };
- CGDataConsumerRef consumer = CGDataConsumerCreate(0, &callbacks);
- CGContextRef context = CGPDFContextCreate(consumer, 0, 0);
- CGDataConsumerRelease(consumer);
+ RetainPtr<CGDataConsumerRef> consumer(AdoptCF, CGDataConsumerCreate(0, &callbacks));
+ CGContextRef context = CGPDFContextCreate(consumer.get(), 0, 0);
CGFloat black[4] = { 0, 0, 0, 1 };
CGContextSetFillColor(context, black);
@@ -129,9 +128,8 @@ bool Path::contains(const FloatPoint &point, WindRule rule) const
return false;
// CGPathContainsPoint returns false for non-closed paths, as a work-around, we copy and close the path first. Radar 4758998 asks for a better CG API to use
- CGMutablePathRef path = copyCGPathClosingSubpaths(m_path);
- bool ret = CGPathContainsPoint(path, 0, point, rule == RULE_EVENODD ? true : false);
- CGPathRelease(path);
+ RetainPtr<CGMutablePathRef> path(AdoptCF, copyCGPathClosingSubpaths(m_path));
+ bool ret = CGPathContainsPoint(path.get(), 0, point, rule == RULE_EVENODD ? true : false);
return ret;
}
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 9252ae0..e8fa860 100644
--- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -261,7 +261,7 @@ static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winf
// characters. Because it's family names rather than font faces we use
// as keys, there might be edge cases where one face of a font family
// has a different repertoire from another face of the same family.
-typedef HashMap<const wchar_t*, UnicodeSet*> FontCmapCache;
+typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache;
static bool fontContainsCharacter(const FontPlatformData* fontData,
const wchar_t* family, UChar32 character)
@@ -277,7 +277,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
if (!fontCmapCache)
fontCmapCache = new FontCmapCache;
- HashMap<const wchar_t*, UnicodeSet*>::iterator it = fontCmapCache->find(family);
+ HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family);
if (it != fontCmapCache->end())
return it->second->contains(character);
@@ -308,7 +308,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
// 1) port back ICU 4.0's faster look-up code for UnicodeSet
// 2) port Mozilla's CompressedCharMap or gfxSparseBitset
unsigned i = 0;
- UnicodeSet* cmap = new UnicodeSet;
+ icu::UnicodeSet* cmap = new icu::UnicodeSet;
while (i < glyphset->cRanges) {
WCHAR start = glyphset->ranges[i].wcLow;
cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 3d67992..229188e 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -459,14 +459,16 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
TransparencyAwareUniscribePainter painter(graphicsContext, this, run, from, to, point);
HDC hdc = painter.hdc();
- if (!hdc)
+ if (windowsCanHandleTextDrawing(graphicsContext) && !hdc)
return;
// TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
// Enforce non-transparent color.
color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
- SetTextColor(hdc, skia::SkColorToCOLORREF(color));
- SetBkMode(hdc, TRANSPARENT);
+ if (hdc) {
+ SetTextColor(hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+ }
// If there is a non-blur shadow and both the fill color and shadow color
// are opaque, handle without skia.
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index d4e45fb..dca0efb 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -45,6 +45,11 @@
#include "SkTypeface.h"
#include "SkUtils.h"
+#include <unicode/normlzr.h>
+#include <unicode/uchar.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/OwnPtr.h>
+
namespace WebCore {
bool Font::canReturnFallbackFontsForComplexText()
@@ -136,27 +141,29 @@ class TextRunWalker {
public:
TextRunWalker(const TextRun& run, unsigned startingX, const Font* font)
: m_font(font)
- , m_run(run)
, m_startingX(startingX)
, m_offsetX(m_startingX)
- , m_iterateBackwards(run.rtl())
+ , m_run(getTextRun(run))
+ , m_iterateBackwards(m_run.rtl())
{
+ // Do not use |run| inside this constructor. Use |m_run| instead.
+
memset(&m_item, 0, sizeof(m_item));
// We cannot know, ahead of time, how many glyphs a given script run
// will produce. We take a guess that script runs will not produce more
// than twice as many glyphs as there are code points and fallback if
// we find that we are wrong.
- m_maxGlyphs = run.length() * 2;
+ m_maxGlyphs = m_run.length() * 2;
createGlyphArrays();
- m_item.log_clusters = new unsigned short[run.length()];
+ m_item.log_clusters = new unsigned short[m_run.length()];
m_item.face = 0;
m_item.font = allocHarfbuzzFont();
- m_item.string = run.characters();
- m_item.stringLength = run.length();
- m_item.item.bidiLevel = run.rtl();
+ m_item.string = m_run.characters();
+ m_item.stringLength = m_run.length();
+ m_item.item.bidiLevel = m_run.rtl();
reset();
}
@@ -283,6 +290,43 @@ public:
}
private:
+ const TextRun& getTextRun(const TextRun& originalRun)
+ {
+ // Convert the |originalRun| to NFC normalized form if combining diacritical marks
+ // (U+0300..) are used in the run. This conversion is necessary since most OpenType
+ // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
+ // their GSUB tables.
+ //
+ // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
+ // the API returns FALSE (= not normalized) for complex runs that don't require NFC
+ // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
+ // Harfbuzz will do the same thing for us using the GSUB table.
+ for (unsigned i = 0; i < originalRun.length(); ++i) {
+ UBlockCode block = ::ublock_getCode(originalRun[i]);
+ if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS) {
+ return getNormalizedTextRun(originalRun);
+ }
+ }
+ return originalRun;
+ }
+
+ const TextRun& getNormalizedTextRun(const TextRun& originalRun)
+ {
+ icu::UnicodeString normalizedString;
+ UErrorCode error = U_ZERO_ERROR;
+ icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(), originalRun.length()), UNORM_NFC, 0 /* no options */, normalizedString, error);
+ if (U_FAILURE(error))
+ return originalRun;
+
+ m_normalizedBuffer.set(new UChar[normalizedString.length() + 1]);
+ normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error);
+ ASSERT(U_SUCCESS(error));
+
+ m_normalizedRun.set(new TextRun(originalRun));
+ m_normalizedRun->setText(m_normalizedBuffer.get(), normalizedString.length());
+ return *m_normalizedRun;
+ }
+
void setupFontForScriptRun()
{
const FontData* fontData = m_font->fontDataAt(0);
@@ -379,7 +423,6 @@ private:
}
const Font* const m_font;
- const TextRun& m_run;
HB_ShaperItem m_item;
uint16_t* m_glyphs16; // A vector of 16-bit glyph ids.
SkScalar* m_xPositions; // A vector of x positions for each glyph.
@@ -389,6 +432,10 @@ private:
unsigned m_pixelWidth; // Width (in px) of the current script run.
unsigned m_numCodePoints; // Code points in current script run.
unsigned m_maxGlyphs; // Current size of all the Harfbuzz arrays.
+
+ OwnPtr<TextRun> m_normalizedRun;
+ OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run.
+ const TextRun& m_run;
bool m_iterateBackwards;
};
diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
index 9596a4c..4e2a226 100644
--- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -100,11 +100,11 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
// Initialize the locale-dependent mapping.
// Since Chrome synchronizes the ICU default locale with its UI locale,
// this ICU locale tells the current UI locale of Chrome.
- Locale locale = Locale::getDefault();
+ icu::Locale locale = icu::Locale::getDefault();
const UChar* localeFamily = 0;
- if (locale == Locale::getJapanese())
+ if (locale == icu::Locale::getJapanese())
localeFamily = scriptFontMap[USCRIPT_HIRAGANA];
- else if (locale == Locale::getKorean())
+ else if (locale == icu::Locale::getKorean())
localeFamily = scriptFontMap[USCRIPT_HANGUL];
else {
// Use Simplified Chinese font for all other locales including
diff --git a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index 39b0847..10fcdf6 100644
--- a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -375,11 +375,13 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
// Pass 0 in when there is no justification.
const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];
- if (firstRun) {
- oldFont = SelectObject(dc, shaping.m_hfont);
- firstRun = false;
- } else
- SelectObject(dc, shaping.m_hfont);
+ if (useWindowsDrawing) {
+ if (firstRun) {
+ oldFont = SelectObject(dc, shaping.m_hfont);
+ firstRun = false;
+ } else
+ SelectObject(dc, shaping.m_hfont);
+ }
// Fonts with different ascents can be used to render different
// runs. 'Across-runs' y-coordinate correction needs to be
@@ -401,7 +403,7 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext,
} else {
SkPoint origin;
origin.fX = curX + + innerOffset;
- origin.fY = y + m_ascent - shaping.m_ascentOffset;
+ origin.fY = y + m_ascent;
textOutOk = paintSkiaText(graphicsContext,
shaping.m_hfont,
glyphCount,
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 86b702f..2364cc4 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,7 +25,13 @@
#if ENABLE(FILTERS)
#include "FEBlend.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+
+typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
namespace WebCore {
@@ -61,8 +68,77 @@ void FEBlend::setBlendMode(BlendModeType mode)
m_mode = mode;
}
-void FEBlend::apply(Filter*)
+static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
+{
+ return 0;
+}
+
+static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
+{
+ return (((255 - alphaA) * colorB + colorA * 255) / 255);
+}
+
+static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
+{
+ return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255);
+}
+
+static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
+{
+ return (((colorB + colorA) * 255 - colorA * colorB) / 255);
+}
+
+static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
+{
+ return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
+}
+
+static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
{
+ return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
+}
+
+void FEBlend::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ if (m_mode == FEBLEND_MODE_UNKNOWN)
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
+
+ IntRect imageRect(IntPoint(), resultImage()->size());
+ RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
+
+ // Keep synchronized with BlendModeType
+ static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
+
+ ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
+ unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3);
+ unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3);
+ for (unsigned channel = 0; channel < 3; ++channel) {
+ unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel);
+ unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel);
+
+ unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB);
+ imageData->data()->set(pixelOffset + channel, result);
+ }
+ unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
+ imageData->data()->set(pixelOffset + 3, alphaR);
+ }
+
+ resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEBlend::dump()
diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h
index b09cd72..31c625f 100644
--- a/WebCore/platform/graphics/filters/FEBlend.h
+++ b/WebCore/platform/graphics/filters/FEBlend.h
@@ -41,7 +41,7 @@ namespace WebCore {
class FEBlend : public FilterEffect {
public:
static PassRefPtr<FEBlend> create(FilterEffect*, FilterEffect*, BlendModeType);
-
+
FilterEffect* in2() const;
void setIn2(FilterEffect*);
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index fb0a194..1e2e552 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -166,7 +166,7 @@ void FEColorMatrix::apply(Filter* filter)
filterContext->drawImage(m_in->resultImage()->image(), calculateDrawingRect(m_in->subRegion()));
IntRect imageRect(IntPoint(), resultImage()->size());
- PassRefPtr<ImageData> imageData(resultImage()->getImageData(imageRect));
+ PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
PassRefPtr<CanvasPixelArray> srcPixelArray(imageData->data());
switch (m_type) {
@@ -186,7 +186,7 @@ void FEColorMatrix::apply(Filter* filter)
break;
}
- resultImage()->putImageData(imageData.get(), imageRect, IntPoint());
+ resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEColorMatrix::dump()
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 54ac123..43e5edd 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,10 +25,16 @@
#if ENABLE(FILTERS)
#include "FEComponentTransfer.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include <math.h>
namespace WebCore {
+typedef void (*TransferType)(unsigned char*, const ComponentTransferFunction&);
+
FEComponentTransfer::FEComponentTransfer(FilterEffect* in, const ComponentTransferFunction& redFunc,
const ComponentTransferFunction& greenFunc, const ComponentTransferFunction& blueFunc, const ComponentTransferFunction& alphaFunc)
: FilterEffect()
@@ -85,8 +92,91 @@ void FEComponentTransfer::setAlphaFunction(const ComponentTransferFunction& func
m_alphaFunc = func;
}
-void FEComponentTransfer::apply(Filter*)
+void identity(unsigned char*, const ComponentTransferFunction&)
+{
+}
+
+void table(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ const Vector<float>& tableValues = transferFunction.tableValues;
+ unsigned n = tableValues.size();
+ if (n < 1)
+ return;
+ for (unsigned i = 0; i < 256; ++i) {
+ double c = i / 255.0;
+ unsigned k = static_cast<unsigned>(c * (n - 1));
+ double v1 = tableValues[k];
+ double v2 = tableValues[std::min((k + 1), (n - 1))];
+ double val = 255.0 * (v1 + (c * (n - 1) - k) * (v2 - v1));
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+void discrete(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ const Vector<float>& tableValues = transferFunction.tableValues;
+ unsigned n = tableValues.size();
+ if (n < 1)
+ return;
+ for (unsigned i = 0; i < 256; ++i) {
+ unsigned k = static_cast<unsigned>((i * n) / 255.0);
+ k = std::min(k, n - 1);
+ double val = 255 * tableValues[k];
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+void linear(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ for (unsigned i = 0; i < 256; ++i) {
+ double val = transferFunction.slope * i + 255 * transferFunction.intercept;
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction)
+{
+ for (unsigned i = 0; i < 256; ++i) {
+ double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), transferFunction.exponent) + transferFunction.offset);
+ val = std::max(0.0, std::min(255.0, val));
+ values[i] = static_cast<unsigned char>(val);
+ }
+}
+
+void FEComponentTransfer::apply(Filter* filter)
{
+ m_in->apply(filter);
+ if (!m_in->resultImage())
+ return;
+
+ if (!getEffectContext())
+ return;
+
+ unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
+ for (unsigned i = 0; i < 256; ++i)
+ rValues[i] = gValues[i] = bValues[i] = aValues[i] = i;
+ unsigned char* tables[] = { rValues, gValues, bValues, aValues };
+ ComponentTransferFunction transferFunction[] = {m_redFunc, m_greenFunc, m_blueFunc, m_alphaFunc};
+ TransferType callEffect[] = {identity, identity, table, discrete, linear, gamma};
+
+ for (unsigned channel = 0; channel < 4; channel++)
+ (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
+
+ IntRect drawingRect = calculateDrawingIntRect(m_in->subRegion());
+ RefPtr<ImageData> imageData(m_in->resultImage()->getUnmultipliedImageData(drawingRect));
+ CanvasPixelArray* srcPixelArray(imageData->data());
+
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ unsigned char c = srcPixelArray->get(pixelOffset + channel);
+ imageData->data()->set(pixelOffset + channel, tables[channel][c]);
+ }
+ }
+
+ resultImage()->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
}
void FEComponentTransfer::dump()
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 0706358..1b41165 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
+ 2009 Dirk Schulze <krit@webkit.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -24,7 +25,10 @@
#if ENABLE(FILTERS)
#include "FEComposite.h"
+#include "CanvasPixelArray.h"
#include "Filter.h"
+#include "GraphicsContext.h"
+#include "ImageData.h"
namespace WebCore {
@@ -97,8 +101,74 @@ void FEComposite::setK4(float k4)
m_k4 = k4;
}
-void FEComposite::apply(Filter*)
+inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPixelArray*& srcPixelArrayB,
+ float k1, float k2, float k3, float k4)
{
+ float scaledK1 = k1 / 255.f;
+ float scaledK4 = k4 * 255.f;
+ for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
+ for (unsigned channel = 0; channel < 4; ++channel) {
+ unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel);
+ unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel);
+
+ unsigned char result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4;
+ if (channel == 3 && i1 == 0 && i2 == 0)
+ result = 0;
+ srcPixelArrayB->set(pixelOffset + channel, result);
+ }
+ }
+}
+
+void FEComposite::apply(Filter* filter)
+{
+ m_in->apply(filter);
+ m_in2->apply(filter);
+ if (!m_in->resultImage() || !m_in2->resultImage())
+ return;
+
+ GraphicsContext* filterContext = getEffectContext();
+ if (!filterContext)
+ return;
+
+ 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()));
+ 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->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);
+ 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);
+ 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);
+ break;
+ case FECOMPOSITE_OPERATOR_ARITHMETIC: {
+ IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
+ RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
+
+ IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
+ RefPtr<ImageData> imageData(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
+ CanvasPixelArray* srcPixelArrayB(imageData->data());
+
+ arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4);
+ resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
+ }
+ break;
+ default:
+ break;
+ }
}
void FEComposite::dump()
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index 41e8a39..5818e50 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -59,6 +59,13 @@ FloatRect FilterEffect::calculateEffectRect(Filter* filter)
return subRegion();
}
+IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect)
+{
+ IntPoint location = roundedIntPoint(FloatPoint(subRegion().x() - effectRect.x(),
+ subRegion().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());
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index 8dc6233..e2b8a0e 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -77,6 +77,7 @@ namespace WebCore {
GraphicsContext* getEffectContext();
FloatRect calculateDrawingRect(const FloatRect&);
+ IntRect calculateDrawingIntRect(const FloatRect&);
virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return filter->filterRegion(); }
virtual FloatRect calculateEffectRect(Filter*);
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index 646a57b..57436be 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -22,6 +22,7 @@
#if ENABLE(FILTERS)
#include "SourceAlpha.h"
+#include "Color.h"
#include "GraphicsContext.h"
#include "PlatformString.h"
#include "Filter.h"
@@ -41,8 +42,28 @@ const AtomicString& SourceAlpha::effectName()
return s_effectName;
}
-void SourceAlpha::apply(Filter*)
+FloatRect SourceAlpha::calculateEffectRect(Filter* filter)
{
+ FloatRect clippedSourceRect = filter->sourceImageRect();
+ if (filter->sourceImageRect().x() < filter->filterRegion().x())
+ clippedSourceRect.setX(filter->filterRegion().x());
+ if (filter->sourceImageRect().y() < filter->filterRegion().y())
+ clippedSourceRect.setY(filter->filterRegion().y());
+ setSubRegion(clippedSourceRect);
+ return filter->filterRegion();
+}
+
+void SourceAlpha::apply(Filter* filter)
+{
+ GraphicsContext* filterContext = getEffectContext();
+ if (!filterContext)
+ return;
+
+ FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size());
+ filterContext->save();
+ filterContext->clipToImageBuffer(imageRect, filter->sourceImage());
+ filterContext->fillRect(imageRect, Color::black);
+ filterContext->restore();
}
void SourceAlpha::dump()
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h
index 5341562..172d05a 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.h
+++ b/WebCore/platform/graphics/filters/SourceAlpha.h
@@ -35,7 +35,7 @@ namespace WebCore {
static const AtomicString& effectName();
virtual bool isSourceInput() { return true; }
- virtual FloatRect calculateEffectRect(Filter* filter) { return filter->sourceImageRect(); }
+ virtual FloatRect calculateEffectRect(Filter*);
void apply(Filter*);
void dump();
diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp
new file mode 100644
index 0000000..a6c2dfb
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2009 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "DataSourceGStreamer.h"
+
+#include <gio/gio.h>
+#include <glib.h>
+#include <gst/gst.h>
+#include <gst/pbutils/missing-plugins.h>
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+GST_DEBUG_CATEGORY_STATIC(webkit_data_src_debug);
+#define GST_CAT_DEFAULT webkit_data_src_debug
+
+static void webkit_data_src_uri_handler_init(gpointer g_iface,
+ gpointer iface_data);
+
+static void webkit_data_src_finalize(WebkitDataSrc* src);
+static GstStateChangeReturn webkit_data_src_change_state(GstElement* element,
+ GstStateChange transition);
+
+static const GInterfaceInfo urihandler_info = {
+ webkit_data_src_uri_handler_init,
+ 0, 0
+};
+
+
+static void _do_init(GType datasrc_type)
+{
+ GST_DEBUG_CATEGORY_INIT(webkit_data_src_debug, "webkit_data_src", 0, "datasrc element");
+ g_type_add_interface_static(datasrc_type, GST_TYPE_URI_HANDLER,
+ &urihandler_info);
+}
+
+GST_BOILERPLATE_FULL(WebkitDataSrc, webkit_data_src, GstBin, GST_TYPE_BIN, _do_init);
+
+static void webkit_data_src_base_init(gpointer klass)
+{
+ GstElementClass* element_class = GST_ELEMENT_CLASS(klass);
+
+ gst_element_class_add_pad_template(element_class,
+ gst_static_pad_template_get(&src_template));
+ gst_element_class_set_details_simple(element_class, (gchar*) "WebKit data source element",
+ (gchar*) "Source",
+ (gchar*) "Handles data: uris",
+ (gchar*) "Philippe Normand <pnormand@igalia.com>");
+
+}
+
+static void webkit_data_src_class_init(WebkitDataSrcClass* klass)
+{
+ GObjectClass* oklass = G_OBJECT_CLASS(klass);
+ GstElementClass* eklass = GST_ELEMENT_CLASS(klass);
+
+ oklass->finalize = (GObjectFinalizeFunc) webkit_data_src_finalize;
+ eklass->change_state = webkit_data_src_change_state;
+}
+
+
+static gboolean webkit_data_src_reset(WebkitDataSrc* src)
+{
+ GstPad* targetpad;
+
+ if (src->kid) {
+ gst_element_set_state(src->kid, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(src), src->kid);
+ }
+
+ src->kid = gst_element_factory_make("giostreamsrc", "streamsrc");
+ if (!src->kid) {
+ GST_ERROR_OBJECT(src, "Failed to create giostreamsrc");
+ return FALSE;
+ }
+
+ gst_bin_add(GST_BIN(src), src->kid);
+
+ targetpad = gst_element_get_static_pad(src->kid, "src");
+ gst_ghost_pad_set_target(GST_GHOST_PAD(src->pad), targetpad);
+ gst_object_unref(targetpad);
+
+ return TRUE;
+}
+
+static void webkit_data_src_init(WebkitDataSrc* src,
+ WebkitDataSrcClass* g_class)
+{
+ GstPadTemplate* pad_template = gst_static_pad_template_get(&src_template);
+ src->pad = gst_ghost_pad_new_no_target_from_template("src",
+ pad_template);
+
+ gst_element_add_pad(GST_ELEMENT(src), src->pad);
+
+ webkit_data_src_reset(src);
+}
+
+static void webkit_data_src_finalize(WebkitDataSrc* src)
+{
+ g_free(src->uri);
+
+ if (src->kid) {
+ GST_DEBUG_OBJECT(src, "Removing giostreamsrc element");
+ gst_element_set_state(src->kid, GST_STATE_NULL);
+ gst_bin_remove(GST_BIN(src), src->kid);
+ src->kid = 0;
+ }
+
+ GST_CALL_PARENT(G_OBJECT_CLASS, finalize, ((GObject* )(src)));
+}
+
+static GstStateChangeReturn webkit_data_src_change_state(GstElement* element, GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ WebkitDataSrc* src = WEBKIT_DATA_SRC(element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (!src->kid) {
+ gst_element_post_message(element,
+ gst_missing_element_message_new(element, "giostreamsrc"));
+ GST_ELEMENT_ERROR(src, CORE, MISSING_PLUGIN, (0), ("no giostreamsrc"));
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
+ if (G_UNLIKELY(ret == GST_STATE_CHANGE_FAILURE))
+ return ret;
+
+ // Downwards state change code should be here, after chaining up
+ // to the parent class.
+
+ return ret;
+}
+
+/*** GSTURIHANDLER INTERFACE *************************************************/
+
+static GstURIType webkit_data_src_uri_get_type(void)
+{
+ return GST_URI_SRC;
+}
+
+static gchar** webkit_data_src_uri_get_protocols(void)
+{
+ static gchar* protocols[] = {(gchar*) "data", 0 };
+
+ return protocols;
+}
+
+static const gchar* webkit_data_src_uri_get_uri(GstURIHandler* handler)
+{
+ WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);
+
+ return src->uri;
+}
+
+static gboolean webkit_data_src_uri_set_uri(GstURIHandler* handler, const gchar* uri)
+{
+ WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);
+
+ // URI as defined in RFC2397:
+ // "data:" [ mediatype ] [ ";base64" ] "," data
+ // we parse URIs like this one:
+ // data:audio/3gpp;base64,AA...
+
+ gchar** scheme_and_remains = g_strsplit(uri, ":", 2);
+ gchar** mime_type_and_options = g_strsplit(scheme_and_remains[1], ";", 0);
+ gint options_size = g_strv_length(mime_type_and_options);
+ gchar* data = 0;
+ gchar* mime_type = 0;
+ gint ret = FALSE;
+
+ // we require uris with a specified mime-type and base64-encoded
+ // data. It doesn't make much sense anyway to play plain/text data
+ // with very few allowed characters (as per the RFC).
+
+ if (GST_STATE(src) >= GST_STATE_PAUSED) {
+ GST_ERROR_OBJECT(src, "Element already configured. Reset it and retry");
+ } else if (!options_size)
+ GST_ERROR_OBJECT(src, "A mime-type is needed in %s", uri);
+ else {
+ mime_type = mime_type_and_options[0];
+ data = mime_type_and_options[options_size-1];
+
+ guchar* decoded_data = 0;
+ gsize decoded_size;
+
+ if (!g_str_has_prefix(data, "base64"))
+ GST_ERROR_OBJECT(src, "Data has to be base64-encoded in %s", uri);
+ else {
+ decoded_data = g_base64_decode(data+7, &decoded_size);
+ GInputStream* stream = g_memory_input_stream_new_from_data(decoded_data,
+ decoded_size,
+ g_free);
+ g_object_set(src->kid, "stream", stream, 0);
+ g_object_unref(stream);
+
+ if (src->uri) {
+ g_free(src->uri);
+ src->uri = 0;
+ }
+
+ src->uri = g_strdup(uri);
+ ret = TRUE;
+ }
+ }
+
+ g_strfreev(scheme_and_remains);
+ g_strfreev(mime_type_and_options);
+ return ret;
+}
+
+static void webkit_data_src_uri_handler_init(gpointer g_iface, gpointer iface_data)
+{
+ GstURIHandlerInterface* iface = (GstURIHandlerInterface *) g_iface;
+
+ iface->get_type = webkit_data_src_uri_get_type;
+ iface->get_protocols = webkit_data_src_uri_get_protocols;
+ iface->get_uri = webkit_data_src_uri_get_uri;
+ iface->set_uri = webkit_data_src_uri_set_uri;
+}
diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h b/WebCore/platform/graphics/gtk/DataSourceGStreamer.h
new file mode 100644
index 0000000..3e88f63
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/DataSourceGStreamer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 Igalia S.L
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef DATA_SOURCE_GSTREAMER_H
+#define DATA_SOURCE_GSTREAMER_H
+
+#include <glib-object.h>
+#include <gst/base/gstbasesrc.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_DATA_SRC (webkit_data_src_get_type ())
+#define WEBKIT_DATA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_DATA_SRC, WebkitDataSrc))
+#define WEBKIT_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_DATA_SRC, WebkitDataSrcClass))
+#define WEBKIT_IS_DATA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_DATA_SRC))
+#define WEBKIT_IS_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_DATA_SRC))
+
+typedef struct _WebkitDataSrc WebkitDataSrc;
+typedef struct _WebkitDataSrcClass WebkitDataSrcClass;
+
+
+struct _WebkitDataSrc {
+ GstBin parent;
+
+ /* explicit pointers to stuff used */
+ GstElement* kid;
+ GstPad* pad;
+ gchar* uri;
+};
+
+struct _WebkitDataSrcClass {
+ GstBinClass parent_class;
+};
+
+GType webkit_data_src_get_type(void);
+
+G_END_DECLS
+
+#endif
diff --git a/WebCore/platform/graphics/gtk/FontPlatformData.h b/WebCore/platform/graphics/gtk/FontPlatformData.h
index 2a65f1e..d30b480 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformData.h
+++ b/WebCore/platform/graphics/gtk/FontPlatformData.h
@@ -87,7 +87,7 @@ public:
bool syntheticBold() const { return m_syntheticBold; }
bool syntheticOblique() const { return m_syntheticOblique; }
- void setFont(cairo_t*) const;
+ cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
unsigned hash() const
{
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
index f2c5f0c..0b1280e 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
@@ -224,10 +224,8 @@ FontPlatformData::~FontPlatformData()
m_fallbacks = 0;
}
- if (m_scaledFont) {
+ if (m_scaledFont)
cairo_scaled_font_destroy(m_scaledFont);
- m_scaledFont = 0;
- }
}
bool FontPlatformData::isFixedPitch()
@@ -242,13 +240,6 @@ bool FontPlatformData::isFixedPitch()
return false;
}
-void FontPlatformData::setFont(cairo_t* cr) const
-{
- ASSERT(m_scaledFont);
-
- cairo_set_scaled_font(cr, m_scaledFont);
-}
-
bool FontPlatformData::operator==(const FontPlatformData& other) const
{
if (m_pattern == other.m_pattern)
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
index 9ea6811..8a1a5f1 100644
--- a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp
@@ -214,13 +214,6 @@ bool FontPlatformData::isFixedPitch()
return pango_font_family_is_monospace(family);
}
-void FontPlatformData::setFont(cairo_t* cr) const
-{
- ASSERT(m_scaledFont);
-
- cairo_set_scaled_font(cr, m_scaledFont);
-}
-
FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other)
{
// Check for self-assignment.
diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp
index 0e92d6c..38da70d 100644
--- a/WebCore/platform/graphics/gtk/ImageGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -88,26 +88,67 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name)
return img.release();
}
+static inline unsigned char* getCairoSurfacePixel(unsigned char* data, uint x, uint y, uint rowStride)
+{
+ return data + (y * rowStride) + x * 4;
+}
+
+static inline guchar* getGdkPixbufPixel(guchar* data, uint x, uint y, uint rowStride)
+{
+ return data + (y * rowStride) + x * 4;
+}
+
GdkPixbuf* BitmapImage::getGdkPixbuf()
{
int width = cairo_image_surface_get_width(frameAtIndex(currentFrame()));
int height = cairo_image_surface_get_height(frameAtIndex(currentFrame()));
-
- int bestDepth = gdk_visual_get_best_depth();
- GdkColormap* cmap = gdk_colormap_new(gdk_visual_get_best_with_depth(bestDepth), true);
-
- GdkPixmap* pixmap = gdk_pixmap_new(0, width, height, bestDepth);
- gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap), cmap);
- cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(pixmap));
- cairo_set_source_surface(cr, frameAtIndex(currentFrame()), 0, 0);
- cairo_paint(cr);
- cairo_destroy(cr);
-
- GdkPixbuf* pixbuf = gdk_pixbuf_get_from_drawable(0, GDK_DRAWABLE(pixmap), 0, 0, 0, 0, 0, width, height);
- g_object_unref(pixmap);
- g_object_unref(cmap);
-
- return pixbuf;
+ unsigned char* surfaceData = cairo_image_surface_get_data(frameAtIndex(currentFrame()));
+ int surfaceRowStride = cairo_image_surface_get_stride(frameAtIndex(currentFrame()));
+
+ GdkPixbuf* dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+ if (!dest)
+ return 0;
+
+ guchar* pixbufData = gdk_pixbuf_get_pixels(dest);
+ int pixbufRowStride = gdk_pixbuf_get_rowstride(dest);
+
+ /* From: http://cairographics.org/manual/cairo-image-surface.html#cairo-format-t
+ * "CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with alpha in
+ * the upper 8 bits, then red, then green, then blue. The 32-bit
+ * quantities are stored native-endian. Pre-multiplied alpha is used.
+ * (That is, 50% transparent red is 0x80800000, not 0x80ff0000.)"
+ *
+ * See http://developer.gimp.org/api/2.0/gdk-pixbuf/gdk-pixbuf-gdk-pixbuf.html#GdkPixbuf
+ * for information on the structure of GdkPixbufs stored with GDK_COLORSPACE_RGB.
+ *
+ * RGB color channels in CAIRO_FORMAT_ARGB32 are stored based on the
+ * endianness of the machine and are also multiplied by the alpha channel.
+ * To properly transfer the data from the Cairo surface we must divide each
+ * of the RGB channels by the alpha channel and then reorder all channels
+ * if this machine is little-endian.
+ */
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ unsigned char* source = getCairoSurfacePixel(surfaceData, x, y, surfaceRowStride);
+ guchar* dest = getGdkPixbufPixel(pixbufData, x, y, pixbufRowStride);
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ guchar alpha = source[3];
+ dest[0] = alpha ? ((source[2] * 255) / alpha) : 0;
+ dest[1] = alpha ? ((source[1] * 255) / alpha) : 0;
+ dest[2] = alpha ? ((source[0] * 255) / alpha) : 0;
+ dest[3] = alpha;
+#else
+ guchar alpha = source[0];
+ dest[0] = alpha ? ((source[1] * 255) / alpha) : 0;
+ dest[1] = alpha ? ((source[2] * 255) / alpha) : 0;
+ dest[2] = alpha ? ((source[3] * 255) / alpha) : 0;
+ dest[3] = alpha;
+#endif
+ }
+ }
+
+ return dest;
}
}
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
index 4e4bda9..65c64b4 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Collabora Ltd. All rights reserved.
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,6 +25,7 @@
#if ENABLE(VIDEO)
#include "MediaPlayerPrivateGStreamer.h"
+#include "DataSourceGStreamer.h"
#include "CString.h"
#include "GraphicsContext.h"
@@ -35,6 +37,7 @@
#include "ScrollView.h"
#include "VideoSinkGStreamer.h"
#include "Widget.h"
+#include "TimeRanges.h"
#include <gst/base/gstbasesrc.h>
#include <gst/gst.h>
@@ -56,13 +59,19 @@ gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpoin
GOwnPtr<gchar> debug;
gst_message_parse_error(message, &err.outPtr(), &debug.outPtr());
- if (err->code == 3) {
- LOG_VERBOSE(Media, "File not found");
- MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
- if (mp)
- mp->loadingFailed();
- } else
- LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
+ LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message);
+
+ MediaPlayer::NetworkState error = MediaPlayer::Empty;
+ if (err->domain == GST_CORE_ERROR || err->domain == GST_LIBRARY_ERROR)
+ error = MediaPlayer::DecodeError;
+ else if (err->domain == GST_RESOURCE_ERROR)
+ error = MediaPlayer::FormatError;
+ else if (err->domain == GST_STREAM_ERROR)
+ error = MediaPlayer::NetworkError;
+
+ MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ if (mp)
+ mp->loadingFailed(error);
}
return true;
}
@@ -112,6 +121,19 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
registrar(create, getSupportedTypes, supportsType);
}
+static bool gstInitialized = false;
+
+static void 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);
+
+ }
+}
+
MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
: m_player(player)
, m_playBin(0)
@@ -119,7 +141,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_source(0)
, m_rate(1.0f)
, m_endTime(numeric_limits<float>::infinity())
- , m_isEndReached(false)
, m_volume(0.5f)
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
@@ -127,19 +148,22 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_isStreaming(false)
, m_size(IntSize())
, m_visible(true)
+ , m_paused(true)
+ , m_seeking(false)
+ , m_errorOccured(false)
{
-
- static bool gstInitialized = false;
- // FIXME: We should pass the arguments from the command line
- if (!gstInitialized) {
- gst_init(0, 0);
- gstInitialized = true;
- }
+ do_gst_init();
// FIXME: The size shouldn't be fixed here, this is just a quick hack.
m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 640, 480);
}
+static gboolean idleUnref(gpointer data)
+{
+ g_object_unref(reinterpret_cast<GObject*>(data));
+ return FALSE;
+}
+
MediaPlayerPrivate::~MediaPlayerPrivate()
{
if (m_surface)
@@ -149,6 +173,18 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
gst_element_set_state(m_playBin, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(m_playBin));
}
+
+ // FIXME: We should find a better way to handle the lifetime of this object; this is
+ // needed because the object is sometimes being destroyed inbetween a call to
+ // webkit_video_sink_render, and the idle it schedules. Adding a ref in
+ // webkit_video_sink_render that would be balanced by the idle is not an option,
+ // because in some cases the destruction of the sink may happen in time for the idle
+ // to be removed from the queue, so it may not run. It would also cause lots of ref
+ // counting churn (render/idle are called many times). This is an ugly race.
+ if (m_videoSink) {
+ g_idle_add(idleUnref, m_videoSink);
+ m_videoSink = 0;
+ }
}
void MediaPlayerPrivate::load(const String& url)
@@ -170,20 +206,13 @@ void MediaPlayerPrivate::load(const String& url)
void MediaPlayerPrivate::play()
{
LOG_VERBOSE(Media, "Play");
- // When end reached, rewind for Test video-seek-past-end-playing
- if (m_isEndReached)
- seek(0);
- m_isEndReached = false;
-
gst_element_set_state(m_playBin, GST_STATE_PLAYING);
- m_startedPlaying = true;
}
void MediaPlayerPrivate::pause()
{
LOG_VERBOSE(Media, "Pause");
gst_element_set_state(m_playBin, GST_STATE_PAUSED);
- m_startedPlaying = false;
}
float MediaPlayerPrivate::duration() const
@@ -191,17 +220,24 @@ float MediaPlayerPrivate::duration() const
if (!m_playBin)
return 0.0;
+ if (m_errorOccured)
+ return 0.0;
+
GstFormat timeFormat = GST_FORMAT_TIME;
gint64 timeLength = 0;
- // FIXME: We try to get the duration, but we do not trust the
+#if !GST_CHECK_VERSION(0, 10, 23)
+ // We try to get the duration, but we do not trust the
// return value of the query function only; the problem we are
// trying to work-around here is that pipelines in stream mode may
// not be able to figure out the duration, but still return true!
- // See https://bugs.webkit.org/show_bug.cgi?id=24639.
+ // See https://bugs.webkit.org/show_bug.cgi?id=24639 which has been
+ // fixed in gst-plugins-base 0.10.23
if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength) || timeLength <= 0) {
+#else
+ if (!gst_element_query_duration(m_playBin, &timeFormat, &timeLength)) {
+#endif
LOG_VERBOSE(Media, "Time duration query failed.");
- m_isStreaming = true;
return numeric_limits<float>::infinity();
}
@@ -215,22 +251,24 @@ float MediaPlayerPrivate::currentTime() const
{
if (!m_playBin)
return 0;
- // Necessary as sometimes, gstreamer return 0:00 at the EOS
- if (m_isEndReached)
- return m_endTime;
- float ret;
+ if (m_errorOccured)
+ return 0;
+
+ float ret = 0.0;
GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
- if (gst_element_query(m_playBin, query)) {
- 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));
- } else {
+ if (!gst_element_query(m_playBin, query)) {
LOG_VERBOSE(Media, "Position query failed...");
- ret = 0.0;
+ gst_query_unref(query);
+ return ret;
}
+
+ 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;
@@ -246,35 +284,23 @@ void MediaPlayerPrivate::seek(float time)
if (m_isStreaming)
return;
+ if (m_errorOccured)
+ return;
+
LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(sec));
- // FIXME: What happens when the seeked position is not available?
if (!gst_element_seek( m_playBin, m_rate,
GST_FORMAT_TIME,
(GstSeekFlags)(GST_SEEK_FLAG_FLUSH),
GST_SEEK_TYPE_SET, sec,
GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
LOG_VERBOSE(Media, "Seek to %f failed", time);
+ else
+ m_seeking = true;
}
void MediaPlayerPrivate::setEndTime(float time)
{
- if (!m_playBin)
- return;
- if (m_isStreaming)
- return;
- if (m_endTime != time) {
- m_endTime = time;
- GstClockTime start = (GstClockTime)(currentTime() * GST_SECOND);
- GstClockTime end = (GstClockTime)(time * GST_SECOND);
- LOG_VERBOSE(Media, "setEndTime: %" GST_TIME_FORMAT, GST_TIME_ARGS(end));
- // FIXME: What happens when the seeked position is not available?
- if (!gst_element_seek(m_playBin, m_rate,
- GST_FORMAT_TIME,
- (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
- GST_SEEK_TYPE_SET, start,
- GST_SEEK_TYPE_SET, end))
- LOG_VERBOSE(Media, "Seek to %f failed", time);
- }
+ notImplemented();
}
void MediaPlayerPrivate::startEndPointTimerIfNeeded()
@@ -294,12 +320,12 @@ void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*)
bool MediaPlayerPrivate::paused() const
{
- return !m_startedPlaying;
+ return m_paused;
}
bool MediaPlayerPrivate::seeking() const
{
- return false;
+ return m_seeking;
}
// Returns the size of the video
@@ -308,13 +334,28 @@ IntSize MediaPlayerPrivate::naturalSize() const
if (!hasVideo())
return IntSize();
- int x = 0, y = 0;
+ // TODO: handle possible clean aperture data. See
+ // https://bugzilla.gnome.org/show_bug.cgi?id=596571
+ // TODO: handle possible transformation matrix. See
+ // https://bugzilla.gnome.org/show_bug.cgi?id=596326
+ int width = 0, height = 0;
if (GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink")) {
- gst_video_get_size(GST_PAD(pad), &x, &y);
+ gst_video_get_size(GST_PAD(pad), &width, &height);
+ GstCaps* caps = GST_PAD_CAPS(pad);
+ gfloat pixelAspectRatio;
+ gint pixelAspectRatioNumerator, pixelAspectRatioDenominator;
+
+ if (!gst_video_parse_caps_pixel_aspect_ratio(caps, &pixelAspectRatioNumerator,
+ &pixelAspectRatioDenominator))
+ pixelAspectRatioNumerator = pixelAspectRatioDenominator = 1;
+
+ pixelAspectRatio = (gfloat) pixelAspectRatioNumerator / (gfloat) pixelAspectRatioDenominator;
+ width *= pixelAspectRatio;
+ height /= pixelAspectRatio;
gst_object_unref(GST_OBJECT(pad));
}
- return IntSize(x, y);
+ return IntSize(width, height);
}
bool MediaPlayerPrivate::hasVideo() const
@@ -325,24 +366,31 @@ bool MediaPlayerPrivate::hasVideo() const
return currentVideo > -1;
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ gint currentAudio = -1;
+ if (m_playBin)
+ g_object_get(G_OBJECT(m_playBin), "current-audio", &currentAudio, NULL);
+ return currentAudio > -1;
+}
+
void MediaPlayerPrivate::setVolume(float volume)
{
m_volume = volume;
LOG_VERBOSE(Media, "Volume to %f", volume);
- setMuted(false);
+
+ if (!m_playBin)
+ return;
+
+ g_object_set(G_OBJECT(m_playBin), "volume", m_volume, NULL);
}
-void MediaPlayerPrivate::setMuted(bool b)
+void MediaPlayerPrivate::setMuted(bool mute)
{
if (!m_playBin)
return;
- if (b) {
- g_object_get(G_OBJECT(m_playBin), "volume", &m_volume, NULL);
- g_object_set(G_OBJECT(m_playBin), "volume", (double)0.0, NULL);
- } else
- g_object_set(G_OBJECT(m_playBin), "volume", m_volume, NULL);
-
+ g_object_set(G_OBJECT(m_playBin), "mute", mute, NULL);
}
void MediaPlayerPrivate::setRate(float rate)
@@ -351,17 +399,13 @@ void MediaPlayerPrivate::setRate(float rate)
gst_element_set_state(m_playBin, GST_STATE_PAUSED);
return;
}
+
if (m_isStreaming)
return;
m_rate = rate;
LOG_VERBOSE(Media, "Set Rate to %f", rate);
- if (!gst_element_seek(m_playBin, rate,
- GST_FORMAT_TIME,
- (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
- GST_SEEK_TYPE_SET, (GstClockTime) (currentTime() * GST_SECOND),
- GST_SEEK_TYPE_SET, (GstClockTime) (m_endTime * GST_SECOND)))
- LOG_VERBOSE(Media, "Set Rate to %f failed", rate);
+ seek(currentTime());
}
int MediaPlayerPrivate::dataRate() const
@@ -380,16 +424,20 @@ MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const
return m_readyState;
}
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
- notImplemented();
- LOG_VERBOSE(Media, "maxTimeBuffered");
- // rtsp streams are not buffered
- return m_isStreaming ? 0 : maxTimeLoaded();
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
+ if (!m_errorOccured && !m_isStreaming && loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
{
+ if (m_errorOccured)
+ return 0.0;
+
// TODO
LOG_VERBOSE(Media, "maxTimeSeekable");
if (m_isStreaming)
@@ -400,6 +448,9 @@ float MediaPlayerPrivate::maxTimeSeekable() const
float MediaPlayerPrivate::maxTimeLoaded() const
{
+ if (m_errorOccured)
+ return 0.0;
+
// TODO
LOG_VERBOSE(Media, "maxTimeLoaded");
notImplemented();
@@ -416,29 +467,30 @@ unsigned MediaPlayerPrivate::bytesLoaded() const
float maxTime = maxTimeLoaded();
if (!dur)
return 0;*/
+
return 1;//totalBytes() * maxTime / dur;
}
bool MediaPlayerPrivate::totalBytesKnown() const
{
- notImplemented();
LOG_VERBOSE(Media, "totalBytesKnown");
return totalBytes() > 0;
}
unsigned MediaPlayerPrivate::totalBytes() const
{
- notImplemented();
LOG_VERBOSE(Media, "totalBytes");
- if (!m_playBin)
+ if (!m_source)
return 0;
- if (!m_source)
+ if (m_errorOccured)
return 0;
- // Do something with m_source to get the total bytes of the media
+ GstFormat fmt = GST_FORMAT_BYTES;
+ gint64 length = 0;
+ gst_element_query_duration(m_source, &fmt, &length);
- return 100;
+ return length;
}
void MediaPlayerPrivate::cancelLoad()
@@ -452,17 +504,21 @@ void MediaPlayerPrivate::updateStates()
// the state of GStreamer, therefore, when in PAUSED state,
// we are sure we can display the first frame and go to play
+ if (!m_playBin)
+ return;
+
+ if (m_errorOccured)
+ return;
+
MediaPlayer::NetworkState oldNetworkState = m_networkState;
MediaPlayer::ReadyState oldReadyState = m_readyState;
GstState state;
GstState pending;
- if (!m_playBin)
- return;
-
GstStateChangeReturn ret = gst_element_get_state(m_playBin,
&state, &pending, 250 * GST_NSECOND);
+ bool shouldUpdateAfterSeek = false;
switch (ret) {
case GST_STATE_CHANGE_SUCCESS:
LOG_VERBOSE(Media, "State: %s, pending: %s",
@@ -474,6 +530,16 @@ void MediaPlayerPrivate::updateStates()
} else if (state == GST_STATE_PAUSED)
m_readyState = MediaPlayer::HaveEnoughData;
+ if (state == GST_STATE_PLAYING)
+ m_paused = false;
+ else
+ m_paused = true;
+
+ if (m_seeking) {
+ shouldUpdateAfterSeek = true;
+ m_seeking = false;
+ }
+
m_networkState = MediaPlayer::Loaded;
g_object_get(m_playBin, "source", &m_source, NULL);
@@ -486,11 +552,17 @@ void MediaPlayerPrivate::updateStates()
gst_element_state_get_name(pending));
// Change in progress
return;
- break;
+ case GST_STATE_CHANGE_FAILURE:
+ LOG_VERBOSE(Media, "Failure: State: %s, pending: %s",
+ gst_element_state_get_name(state),
+ gst_element_state_get_name(pending));
+ // Change failed
+ return;
case GST_STATE_CHANGE_NO_PREROLL:
LOG_VERBOSE(Media, "No preroll: State: %s, pending: %s",
gst_element_state_get_name(state),
gst_element_state_get_name(pending));
+
if (state == GST_STATE_READY) {
m_readyState = MediaPlayer::HaveFutureData;
} else if (state == GST_STATE_PAUSED)
@@ -506,6 +578,9 @@ void MediaPlayerPrivate::updateStates()
if (seeking())
m_readyState = MediaPlayer::HaveNothing;
+ if (shouldUpdateAfterSeek)
+ timeChanged();
+
if (m_networkState != oldNetworkState) {
LOG_VERBOSE(Media, "Network State Changed from %u to %u",
oldNetworkState, m_networkState);
@@ -546,15 +621,14 @@ void MediaPlayerPrivate::volumeChanged()
void MediaPlayerPrivate::didEnd()
{
- m_isEndReached = true;
- pause();
timeChanged();
}
-void MediaPlayerPrivate::loadingFailed()
+void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error)
{
- if (m_networkState != MediaPlayer::NetworkError) {
- m_networkState = MediaPlayer::NetworkError;
+ m_errorOccured = true;
+ if (m_networkState != error) {
+ m_networkState = error;
m_player->networkStateChanged();
}
if (m_readyState != MediaPlayer::HaveNothing) {
@@ -565,7 +639,18 @@ void MediaPlayerPrivate::loadingFailed()
void MediaPlayerPrivate::setSize(const IntSize& size)
{
+ // Destroy and re-create the cairo surface only if the size
+ // changed.
+ if (size != m_size) {
+ if (m_surface)
+ cairo_surface_destroy(m_surface);
+ m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(),
+ size.height());
+ g_object_set(m_videoSink, "surface", m_surface, 0);
+ }
+
m_size = size;
+
}
void MediaPlayerPrivate::setVisible(bool visible)
@@ -586,11 +671,12 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
if (!m_visible)
return;
- //TODO: m_size vs rect?
cairo_t* cr = context->platformContext();
cairo_save(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+
+ // paint the rectangle on the context and draw the surface inside.
cairo_translate(cr, rect.x(), rect.y());
cairo_rectangle(cr, 0, 0, rect.width(), rect.height());
cairo_set_source_surface(cr, m_surface, 0, 0);
@@ -598,24 +684,124 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
cairo_restore(cr);
}
+static HashSet<String> mimeTypeCache()
+{
+
+ do_gst_init();
+
+ static HashSet<String> cache;
+ 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"));
+
+ 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")) {
+ cache.add(String("video/mp4"));
+ cache.add(String("audio/aac"));
+ }
+
+ if (g_str_equal(capability[0], "video/x-theora"))
+ cache.add(String("video/ogg"));
+
+ if (g_str_equal(capability[0], "audio/x-wav"))
+ cache.add(String("audio/wav"));
+
+ 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_has_suffix (versionAndLayer[0], "(int)1")) {
+ for (int i = 0; versionAndLayer[1][i] != '\0'; i++) {
+ if (versionAndLayer[1][i] == '1')
+ cache.add(String("audio/mp1"));
+ else if (versionAndLayer[1][i] == '2')
+ cache.add(String("audio/mp2"));
+ else if (versionAndLayer[1][i] == '3')
+ cache.add(String("audio/mp3"));
+ }
+ }
+
+ g_strfreev(versionAndLayer);
+ }
+ }
+
+ g_strfreev(capability);
+ g_strfreev(mimetype);
+ }
+
+ gst_plugin_feature_list_free(factories);
+ typeListInitialized = true;
+ }
+
+ return cache;
+}
+
void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
{
- // FIXME: query the engine to see what types are supported
- notImplemented();
- types.add(String("video/x-theora+ogg"));
+ types = mimeTypeCache();
}
MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
{
- // FIXME: query the engine to see what types are supported
- notImplemented();
- return type == "video/x-theora+ogg" ? (codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported) : MediaPlayer::IsNotSupported;
+ if (type.isNull() || type.isEmpty())
+ return MediaPlayer::IsNotSupported;
+
+ // spec says we should not return "probably" if the codecs string is empty
+ if (mimeTypeCache().contains(type))
+ return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
+ return MediaPlayer::IsNotSupported;
+}
+
+bool MediaPlayerPrivate::hasSingleSecurityOrigin() const
+{
+ return true;
+}
+
+bool MediaPlayerPrivate::supportsFullscreen() const
+{
+ return true;
}
void MediaPlayerPrivate::createGSTPlayBin(String url)
{
ASSERT(!m_playBin);
- m_playBin = gst_element_factory_make("playbin", "play");
+ m_playBin = gst_element_factory_make("playbin2", "play");
GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_playBin));
gst_bus_add_signal_watch(bus);
@@ -627,10 +813,12 @@ void MediaPlayerPrivate::createGSTPlayBin(String url)
g_object_set(G_OBJECT(m_playBin), "uri", url.utf8().data(), NULL);
- GstElement* audioSink = gst_element_factory_make("gconfaudiosink", 0);
m_videoSink = webkit_video_sink_new(m_surface);
- g_object_set(m_playBin, "audio-sink", audioSink, NULL);
+ // This ref is to protect the sink from being destroyed before we stop the idle it
+ // creates internally. See the comment in ~MediaPlayerPrivate.
+ g_object_ref(m_videoSink);
+
g_object_set(m_playBin, "video-sink", m_videoSink, NULL);
g_signal_connect(m_videoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this);
@@ -641,4 +829,3 @@ void MediaPlayerPrivate::createGSTPlayBin(String url)
}
#endif
-
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
index 8842f84..d305759 100644
--- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
@@ -56,6 +56,7 @@ namespace WebCore {
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
void load(const String &url);
void cancelLoad();
@@ -80,7 +81,7 @@ namespace WebCore {
MediaPlayer::NetworkState networkState() const;
MediaPlayer::ReadyState readyState() const;
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
@@ -95,11 +96,15 @@ namespace WebCore {
void timeChanged();
void volumeChanged();
void didEnd();
- void loadingFailed();
+ void loadingFailed(MediaPlayer::NetworkState);
void repaint();
void paint(GraphicsContext*, const IntRect&);
+ bool hasSingleSecurityOrigin() const;
+
+ bool supportsFullscreen() const;
+
private:
MediaPlayerPrivate(MediaPlayer*);
static MediaPlayerPrivateInterface* create(MediaPlayer* player);
@@ -132,6 +137,10 @@ namespace WebCore {
IntSize m_size;
bool m_visible;
cairo_surface_t* m_surface;
+
+ bool m_paused;
+ bool m_seeking;
+ bool m_errorOccured;
};
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
index a77c1cf..9a616f4 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
@@ -50,9 +50,9 @@ void SimpleFontData::platformInit()
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
- m_ascent = static_cast<int>(font_extents.ascent);
- m_descent = static_cast<int>(font_extents.descent);
- m_lineSpacing = static_cast<int>(font_extents.height);
+ m_ascent = static_cast<int>(lroundf(font_extents.ascent));
+ m_descent = static_cast<int>(lroundf(font_extents.descent));
+ m_lineSpacing = static_cast<int>(lroundf(font_extents.height));
// There seems to be some rounding error in cairo (or in how we
// use cairo) with some fonts, like DejaVu Sans Mono, which makes
// cairo report a height smaller than ascent + descent, which is
@@ -63,7 +63,7 @@ void SimpleFontData::platformInit()
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
m_xHeight = text_extents.height;
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
- m_spaceWidth = static_cast<int>(text_extents.x_advance);
+ m_spaceWidth = static_cast<float>(text_extents.x_advance);
m_lineGap = m_lineSpacing - m_ascent - m_descent;
m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
@@ -130,10 +130,4 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
return w;
}
-void SimpleFontData::setFont(cairo_t* cr) const
-{
- ASSERT(cr);
- m_platformData.setFont(cr);
-}
-
}
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
index e57d9e6..975143e 100644
--- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp
@@ -49,9 +49,9 @@ void SimpleFontData::platformInit()
cairo_font_extents_t font_extents;
cairo_text_extents_t text_extents;
cairo_scaled_font_extents(m_platformData.m_scaledFont, &font_extents);
- m_ascent = static_cast<int>(font_extents.ascent);
- m_descent = static_cast<int>(font_extents.descent);
- m_lineSpacing = static_cast<int>(font_extents.height);
+ m_ascent = static_cast<int>(lroundf(font_extents.ascent));
+ m_descent = static_cast<int>(lroundf(font_extents.descent));
+ m_lineSpacing = static_cast<int>(lroundf(font_extents.height));
// There seems to be some rounding error in cairo (or in how we
// use cairo) with some fonts, like DejaVu Sans Mono, which makes
// cairo report a height smaller than ascent + descent, which is
@@ -62,7 +62,7 @@ void SimpleFontData::platformInit()
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, "x", &text_extents);
m_xHeight = text_extents.height;
cairo_scaled_font_text_extents(m_platformData.m_scaledFont, " ", &text_extents);
- m_spaceWidth = static_cast<int>(text_extents.x_advance);
+ m_spaceWidth = static_cast<float>(text_extents.x_advance);
m_lineGap = m_lineSpacing - m_ascent - m_descent;
m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
}
@@ -133,10 +133,4 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
return w;
}
-void SimpleFontData::setFont(cairo_t* cr) const
-{
- ASSERT(cr);
- m_platformData.setFont(cr);
-}
-
}
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
index f049998..fb86fe9 100644
--- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
@@ -33,8 +33,14 @@
#include <gst/video/video.h>
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE("sink",
- GST_PAD_SINK, GST_PAD_ALWAYS,
- GST_STATIC_CAPS(GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx));
+ 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)
+#else
+ GST_STATIC_CAPS(GST_VIDEO_CAPS_xRGB)
+#endif
+);
GST_DEBUG_CATEGORY_STATIC(webkit_video_sink_debug);
#define GST_CAT_DEFAULT webkit_video_sink_debug
@@ -102,9 +108,14 @@ webkit_video_sink_init(WebKitVideoSink* sink, WebKitVideoSinkClass* klass)
static gboolean
webkit_video_sink_idle_func(gpointer data)
{
- WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(data);
+ WebKitVideoSink* sink = reinterpret_cast<WebKitVideoSink*>(data);
WebKitVideoSinkPrivate* priv = sink->priv;
GstBuffer* buffer;
+ GstCaps* caps;
+ GstVideoFormat format;
+ gint par_n, par_d;
+ gfloat par;
+ gint bwidth, bheight;
if (!priv->async_queue)
return FALSE;
@@ -113,19 +124,35 @@ webkit_video_sink_idle_func(gpointer data)
if (!buffer || G_UNLIKELY(!GST_IS_BUFFER(buffer)))
return FALSE;
+ caps = GST_BUFFER_CAPS(buffer);
+ if (!gst_video_format_parse_caps(caps, &format, &bwidth, &bheight)) {
+ GST_ERROR_OBJECT(sink, "Unknown video format in buffer caps '%s'",
+ gst_caps_to_string(caps));
+ return FALSE;
+ }
+
+ if (!gst_video_parse_caps_pixel_aspect_ratio(caps, &par_n, &par_d))
+ par_n = par_d = 1;
+
+ par = (gfloat) par_n / (gfloat) par_d;
+
// TODO: consider priv->rgb_ordering?
- cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), CAIRO_FORMAT_RGB24, priv->width, priv->height, (4 * priv->width + 3) & ~3);
+ cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer),
+ CAIRO_FORMAT_RGB24,
+ bwidth, bheight,
+ 4 * bwidth);
// TODO: We copy the data twice right now. This could be easily improved.
cairo_t* cr = cairo_create(priv->surface);
+ cairo_scale(cr, par, 1.0 / par);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface(cr, src, 0, 0);
cairo_surface_destroy(src);
cairo_rectangle(cr, 0, 0, priv->width, priv->height);
cairo_fill(cr);
cairo_destroy(cr);
-
gst_buffer_unref(buffer);
+ g_async_queue_unref(priv->async_queue);
g_signal_emit(sink, webkit_video_sink_signals[REPAINT_REQUESTED], 0);
@@ -138,6 +165,7 @@ webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer)
WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(bsink);
WebKitVideoSinkPrivate* priv = sink->priv;
+ g_async_queue_ref(priv->async_queue);
g_async_queue_push(priv->async_queue, gst_buffer_ref(buffer));
g_idle_add_full(G_PRIORITY_HIGH_IDLE, webkit_video_sink_idle_func, sink, 0);
@@ -151,9 +179,7 @@ webkit_video_sink_set_caps(GstBaseSink* bsink, GstCaps* caps)
WebKitVideoSinkPrivate* priv = sink->priv;
GstStructure* structure;
gboolean ret;
- const GValue* fps;
- const GValue* par;
- gint width, height;
+ gint width, height, fps_n, fps_d;
int red_mask;
GstCaps* intersection = gst_caps_intersect(gst_static_pad_template_get_caps(&sinktemplate), caps);
@@ -167,25 +193,19 @@ webkit_video_sink_set_caps(GstBaseSink* bsink, GstCaps* caps)
ret = gst_structure_get_int(structure, "width", &width);
ret &= gst_structure_get_int(structure, "height", &height);
- fps = gst_structure_get_value(structure, "framerate");
- ret &= (fps != 0);
-
- par = gst_structure_get_value(structure, "pixel-aspect-ratio");
- if (!ret)
- return FALSE;
+ /* We dont yet use fps but handy to have */
+ ret &= gst_structure_get_fraction(structure, "framerate",
+ &fps_n, &fps_d);
+ g_return_val_if_fail(ret, FALSE);
priv->width = width;
priv->height = height;
+ priv->fps_n = fps_n;
+ priv->fps_d = fps_d;
- /* We dont yet use fps or pixel aspect into but handy to have */
- priv->fps_n = gst_value_get_fraction_numerator(fps);
- priv->fps_d = gst_value_get_fraction_denominator(fps);
-
- if (par) {
- priv->par_n = gst_value_get_fraction_numerator(par);
- priv->par_d = gst_value_get_fraction_denominator(par);
- } else
+ if (!gst_structure_get_fraction(structure, "pixel-aspect-ratio",
+ &priv->par_n, &priv->par_d))
priv->par_n = priv->par_d = 1;
gst_structure_get_int(structure, "red_mask", &red_mask);
@@ -265,6 +285,8 @@ webkit_video_sink_stop(GstBaseSink* base_sink)
g_async_queue_unlock(priv->async_queue);
+ g_idle_remove_by_data(base_sink);
+
return TRUE;
}
diff --git a/WebCore/platform/graphics/haiku/ColorHaiku.cpp b/WebCore/platform/graphics/haiku/ColorHaiku.cpp
new file mode 100644
index 0000000..a9ac186
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ColorHaiku.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "Color.h"
+
+#include <InterfaceDefs.h>
+
+
+namespace WebCore {
+
+Color::Color(const rgb_color& color)
+ : m_color(makeRGBA(color.red, color.green, color.blue, color.alpha))
+ , m_valid(true)
+{
+}
+
+Color::operator rgb_color() const
+{
+ return make_color(red(), green(), blue(), alpha());
+}
+
+
+Color focusRingColor()
+{
+ return Color(keyboard_navigation_color());
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FloatPointHaiku.cpp b/WebCore/platform/graphics/haiku/FloatPointHaiku.cpp
new file mode 100644
index 0000000..0f50898
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FloatPointHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "FloatPoint.h"
+
+#include <Point.h>
+
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const BPoint& point)
+ : m_x(point.x)
+ , m_y(point.y)
+{
+}
+
+FloatPoint::operator BPoint() const
+{
+ return BPoint(m_x, m_y);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp b/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp
new file mode 100644
index 0000000..67af3af
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "FloatRect.h"
+
+#include <Rect.h>
+
+
+namespace WebCore {
+
+FloatRect::FloatRect(const BRect& rect)
+ : m_location(rect.LeftTop())
+ , m_size(rect.Width(), rect.Height())
+{
+}
+
+FloatRect::operator BRect() const
+{
+ return BRect(BPoint(x(), y()), BSize(width(), height()));
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
new file mode 100644
index 0000000..b99bf42
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "FontCache.h"
+
+#include "Font.h"
+#include "FontData.h"
+#include "FontPlatformData.h"
+#include "NotImplemented.h"
+#include <String.h>
+
+
+namespace WebCore {
+
+void FontCache::platformInit()
+{
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ FontPlatformData data(font.fontDescription(), font.family().family());
+ return getCachedFontData(&data);
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ notImplemented();
+ return 0;
+}
+
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
+{
+ // FIXME: Would be even better to somehow get the user's default font here.
+ // For now we'll pick the default that the user would get without changing any prefs.
+ static AtomicString defaultString("DejaVu Serif");
+ return getCachedFontPlatformData(fontDescription, defaultString);
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ return new FontPlatformData(fontDescription, family);
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp b/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..6008bb1
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 Alp Toker <alp@atoker.com>
+ *
+ * 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 "FontCustomPlatformData.h"
+
+#include "SharedBuffer.h"
+#include "FontPlatformData.h"
+
+
+namespace WebCore {
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode)
+{
+ return FontPlatformData(size, bold, italic);
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ // FIXME: We need support in Haiku to read fonts from memory to implement this.
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/graphics/haiku/FontCustomPlatformData.h b/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
new file mode 100644
index 0000000..c5a814e
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Alp Toker <alp@atoker.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef FontCustomPlatformData_h
+#define FontCustomPlatformData_h
+
+#include "FontRenderingMode.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+ class FontPlatformData;
+ class SharedBuffer;
+
+ struct FontCustomPlatformData : Noncopyable {
+ public:
+ FontCustomPlatformData() { }
+ ~FontCustomPlatformData();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode);
+ };
+
+ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/haiku/FontHaiku.cpp b/WebCore/platform/graphics/haiku/FontHaiku.cpp
new file mode 100644
index 0000000..48744d9
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontHaiku.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "FontData.h"
+#include "FontDescription.h"
+#include "FontSelector.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include <Font.h>
+#include <String.h>
+#include <View.h>
+
+
+// FIXME: Temp routine to convert unicode character to UTF8.
+int charUnicodeToUTF8HACK(unsigned short glyph, char* out)
+{
+ int i = 0;
+
+ if (glyph < 0x0080)
+ out[i++] = static_cast<char>(glyph);
+ else if (glyph < 0x0800) { // 2 bytes
+ out[i++] = 0xc0 | (glyph >> 6);
+ out[i++] = 0x80 | (glyph & 0x3F);
+ } else if (glyph > 0x0800) { // 3 bytes
+ out[i++] = 0xe0 | (glyph >> 12);
+ out[i++] = 0x80 | ((glyph >> 6) & 0x3F);
+ out[i++] = 0x80 | (glyph & 0x3F);
+ }
+
+ out[i] = '\0';
+ return i;
+}
+
+namespace WebCore {
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
+{
+ Color color = graphicsContext->fillColor();
+ BView* view = graphicsContext->platformContext();
+ BFont* m_font = font->platformData().font();
+
+ graphicsContext->setCompositeOperation(CompositeSourceOver);
+ view->SetHighColor(color);
+ view->SetFont(m_font);
+
+ GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(from));
+ float offset = point.x();
+ for (int i = 0; i < numGlyphs; i++) {
+ char out[4];
+ charUnicodeToUTF8HACK(glyphs[i], out);
+
+ view->DrawString(out, sizeof(out), BPoint(offset, point.y()));
+ offset += glyphBuffer.advanceAt(from + i);
+ }
+}
+
+void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point,
+ int from, int to) const
+{
+ notImplemented();
+}
+
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+{
+ notImplemented();
+ return 0;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const
+{
+ notImplemented();
+ return 0;
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/FontPlatformData.h b/WebCore/platform/graphics/haiku/FontPlatformData.h
new file mode 100644
index 0000000..9feab8e
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/FontPlatformData.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef FontPlatformData_H
+#define FontPlatformData_H
+
+#include "FontDescription.h"
+#include "GlyphBuffer.h"
+#include <interface/Font.h>
+
+namespace WebCore {
+
+ class FontPlatformData {
+ public:
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_font(hashTableDeletedFontValue())
+ { }
+
+ FontPlatformData()
+ : m_font(0)
+ { }
+
+ FontPlatformData(const FontDescription&, const AtomicString& family);
+ FontPlatformData(float size, bool bold, bool oblique);
+ FontPlatformData(const FontPlatformData&);
+
+ ~FontPlatformData();
+
+ BFont* font() const { return m_font; }
+
+ bool isFixedPitch();
+ float size() const { return m_size; }
+ bool bold() const { return m_bold; }
+ bool oblique() const { return m_oblique; }
+
+ unsigned hash() const;
+ bool isHashTableDeletedValue() const;
+
+ bool operator==(const FontPlatformData&) const;
+
+#ifndef NDEBUG
+ String description() const;
+#endif
+
+ BFont* m_font;
+ float m_size;
+ bool m_bold;
+ bool m_oblique;
+
+ private:
+ static BFont* hashTableDeletedFontValue() { return reinterpret_cast<BFont*>(-1); }
+ };
+
+} // namespace WebCore
+
+#endif
+
diff --git a/WebCore/platform/graphics/haiku/GradientHaiku.cpp b/WebCore/platform/graphics/haiku/GradientHaiku.cpp
new file mode 100644
index 0000000..469a17f
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/GradientHaiku.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com> All rights reserved.
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@theolliviers.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "Gradient.h"
+
+#include "CSSParser.h"
+#include "NotImplemented.h"
+
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+ notImplemented();
+}
+
+PlatformGradient Gradient::platformGradient()
+{
+ notImplemented();
+ return 0;
+}
+
+void Gradient::fill(GraphicsContext*, const FloatRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
new file mode 100644
index 0000000..d785ef4
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "GraphicsContext.h"
+
+#include "CString.h"
+#include "Color.h"
+#include "Font.h"
+#include "FontData.h"
+#include "NotImplemented.h"
+#include "Path.h"
+#include "Pen.h"
+#include "TransformationMatrix.h"
+#include <GraphicsDefs.h>
+#include <Region.h>
+#include <View.h>
+#include <Window.h>
+#include <stdio.h>
+
+
+namespace WebCore {
+
+class GraphicsContextPlatformPrivate {
+public:
+ GraphicsContextPlatformPrivate(BView* view);
+ ~GraphicsContextPlatformPrivate();
+
+ BView* m_view;
+};
+
+GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(BView* view)
+ : m_view(view)
+{
+}
+
+GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
+{
+}
+
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate(context))
+{
+ setPaintingDisabled(!context);
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ destroyGraphicsContextPrivate(m_common);
+ delete m_data;
+}
+
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+ return m_data->m_view;
+}
+
+void GraphicsContext::savePlatformState()
+{
+ m_data->m_view->PushState();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ m_data->m_view->PopState();
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->FillRect(rect);
+ if (strokeStyle() != NoStroke)
+ m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle());
+}
+
+// This is only used to draw borders.
+void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
+{
+ if (paintingDisabled())
+ return;
+
+ if (strokeStyle() == NoStroke)
+ return;
+
+ m_data->m_view->StrokeLine(point1, point2, getHaikuStrokeStyle());
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->FillEllipse(rect);
+ if (strokeStyle() != NoStroke)
+ m_data->m_view->StrokeEllipse(rect, getHaikuStrokeStyle());
+}
+
+void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->StrokeArc(rect, startAngle, angleSpan, getHaikuStrokeStyle());
+}
+
+void GraphicsContext::strokePath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::drawConvexPolygon(size_t pointsLength, const FloatPoint* points, bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ BPoint bPoints[pointsLength];
+ for (size_t i = 0; i < pointsLength; i++)
+ bPoints[i] = points[i];
+
+ m_data->m_view->FillPolygon(bPoints, pointsLength);
+ if (strokeStyle() != NoStroke)
+ // Stroke with low color
+ m_data->m_view->StrokePolygon(bPoints, pointsLength, true, getHaikuStrokeStyle());
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ rgb_color oldColor = m_data->m_view->HighColor();
+ m_data->m_view->SetHighColor(color);
+ m_data->m_view->FillRect(rect);
+ m_data->m_view->SetHighColor(oldColor);
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+}
+
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+{
+ if (paintingDisabled() || !color.alpha())
+ return;
+
+ notImplemented();
+ // FIXME: A simple implementation could just use FillRoundRect if all
+ // the sizes are the same, or even if they are not. Otherwise several
+ // FillRect and FillArc calls are needed.
+}
+
+void GraphicsContext::fillPath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::beginPath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clip(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ BRegion region(rect);
+ m_data->m_view->ConstrainClippingRegion(&region);
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ const Vector<IntRect>& rects = focusRingRects();
+ unsigned rectCount = rects.size();
+
+ // FIXME: maybe we should implement this with BShape?
+
+ if (rects.size() > 1) {
+ BRegion region;
+ for (int i = 0; i < rectCount; ++i)
+ region.Include(BRect(rects[i]));
+
+ m_data->m_view->SetHighColor(color);
+ m_data->m_view->StrokeRect(region.Frame(), B_MIXED_COLORS);
+ }
+}
+
+void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
+{
+ if (paintingDisabled())
+ return;
+
+ IntPoint endPoint = origin + IntSize(width, 0);
+ drawLine(origin, endPoint);
+}
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+{
+ notImplemented();
+ return rect;
+}
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect, float width)
+{
+ if (paintingDisabled())
+ return;
+
+ float oldSize = m_data->m_view->PenSize();
+ m_data->m_view->SetPenSize(width);
+ m_data->m_view->StrokeRect(rect, getHaikuStrokeStyle());
+ m_data->m_view->SetPenSize(oldSize);
+}
+
+void GraphicsContext::setLineCap(LineCap lineCap)
+{
+ if (paintingDisabled())
+ return;
+
+ cap_mode mode = B_BUTT_CAP;
+ switch (lineCap) {
+ case RoundCap:
+ mode = B_ROUND_CAP;
+ break;
+ case SquareCap:
+ mode = B_SQUARE_CAP;
+ break;
+ case ButtCap:
+ default:
+ break;
+ }
+
+ m_data->m_view->SetLineMode(mode, m_data->m_view->LineJoinMode(), m_data->m_view->LineMiterLimit());
+}
+
+void GraphicsContext::setLineJoin(LineJoin lineJoin)
+{
+ if (paintingDisabled())
+ return;
+
+ join_mode mode = B_MITER_JOIN;
+ switch (lineJoin) {
+ case RoundJoin:
+ mode = B_ROUND_JOIN;
+ break;
+ case BevelJoin:
+ mode = B_BEVEL_JOIN;
+ break;
+ case MiterJoin:
+ default:
+ break;
+ }
+
+ m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), mode, m_data->m_view->LineMiterLimit());
+}
+
+void GraphicsContext::setMiterLimit(float limit)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetLineMode(m_data->m_view->LineCapMode(), m_data->m_view->LineJoinMode(), limit);
+}
+
+void GraphicsContext::setAlpha(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+
+ drawing_mode mode = B_OP_COPY;
+ switch (op) {
+ case CompositeClear:
+ case CompositeCopy:
+ // Use the default above
+ break;
+ case CompositeSourceOver:
+ mode = B_OP_OVER;
+ break;
+ default:
+ printf("GraphicsContext::setCompositeOperation: Unsupported composite operation %s\n",
+ compositeOperatorName(op).utf8().data());
+ }
+ m_data->m_view->SetDrawingMode(mode);
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->ConstrainClippingRegion(path.platformPath());
+}
+
+void GraphicsContext::clipOut(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
+{
+ notImplemented();
+}
+
+TransformationMatrix GraphicsContext::getCTM() const
+{
+ notImplemented();
+ return TransformationMatrix();
+}
+
+void GraphicsContext::translate(float x, float y)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+IntPoint GraphicsContext::origin()
+{
+ notImplemented();
+ return IntPoint(0, 0);
+}
+
+void GraphicsContext::rotate(float radians)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::scale(const FloatSize& size)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clipOut(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::concatCTM(const TransformationMatrix& transform)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformShouldAntialias(bool enable)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
+{
+}
+
+void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformFont(const Font& font)
+{
+ m_data->m_view->SetFont(font.primaryFont()->platformData().font());
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetHighColor(color);
+}
+
+pattern GraphicsContext::getHaikuStrokeStyle()
+{
+ switch (strokeStyle()) {
+ case SolidStroke:
+ return B_SOLID_HIGH;
+ break;
+ case DottedStroke:
+ return B_MIXED_COLORS;
+ break;
+ case DashedStroke:
+ // FIXME: use a better dashed stroke!
+ notImplemented();
+ return B_MIXED_COLORS;
+ break;
+ default:
+ return B_SOLID_LOW;
+ break;
+ }
+}
+
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
+{
+ // FIXME: see getHaikuStrokeStyle.
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetPenSize(thickness);
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->m_view->SetHighColor(color);
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IconHaiku.cpp b/WebCore/platform/graphics/haiku/IconHaiku.cpp
new file mode 100644
index 0000000..dccac4a
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IconHaiku.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+#include "Icon.h"
+
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+
+namespace WebCore {
+
+Icon::~Icon()
+{
+ notImplemented();
+}
+
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+{
+ notImplemented();
+ return 0;
+}
+
+void Icon::paint(GraphicsContext*, const IntRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/ImageBufferData.h b/WebCore/platform/graphics/haiku/ImageBufferData.h
new file mode 100644
index 0000000..f978c34
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ImageBufferData.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * 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 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.
+ */
+
+#ifndef ImageBufferData_h
+#define ImageBufferData_h
+
+namespace WebCore {
+
+ class IntSize;
+
+ class ImageBufferData {
+ public:
+ ImageBufferData(const IntSize&);
+ };
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
+
diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
new file mode 100644
index 0000000..276c968
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "ImageBuffer.h"
+
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include "NotImplemented.h"
+
+
+namespace WebCore {
+
+ImageBufferData::ImageBufferData(const IntSize&)
+{
+}
+
+ImageBuffer::ImageBuffer(const IntSize&, ImageColorSpace imageColorSpace, bool& success)
+ : m_data(IntSize())
+{
+ notImplemented();
+ success = false;
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ notImplemented();
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ notImplemented();
+}
+
+String ImageBuffer::toDataURL(const String&) const
+{
+ notImplemented();
+ return String();
+}
+
+Image* ImageBuffer::image() const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/ImageHaiku.cpp b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
new file mode 100644
index 0000000..323d6ab
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/ImageHaiku.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ * Copyright (C) 2008 Andrea Anzani <andrea.anzani@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "Image.h"
+
+#include "BitmapImage.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include <Application.h>
+#include <Bitmap.h>
+#include <View.h>
+
+
+// This function loads resources from WebKit
+Vector<char> loadResourceIntoArray(const char*);
+
+
+namespace WebCore {
+
+bool FrameData::clear(bool clearMetadata)
+{
+ if (clearMetadata)
+ m_haveMetadata = false;
+
+ if (m_frame) {
+ delete m_frame;
+ m_frame = 0;
+ m_duration = 0.0f;
+ m_hasAlpha = true;
+ return true;
+ }
+
+ return false;
+}
+
+WTF::PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+{
+ Vector<char> array = loadResourceIntoArray(name);
+ WTF::PassRefPtr<BitmapImage> image = BitmapImage::create();
+ RefPtr<SharedBuffer> buffer = SharedBuffer::create(array.data(), array.size());
+ image->setData(buffer, true);
+
+ return image;
+}
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+// Drawing Routines
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+{
+ startAnimation();
+
+ BBitmap* image = nativeImageForCurrentFrame();
+ if (!image || !image->IsValid()) // If the image hasn't fully loaded.
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(ctxt, dst, solidColor(), op);
+ return;
+ }
+
+ ctxt->save();
+ ctxt->setCompositeOperation(op);
+
+ BRect srcRect(src);
+ BRect dstRect(dst);
+
+ // Test using example site at
+ // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ ctxt->platformContext()->SetDrawingMode(B_OP_ALPHA);
+ ctxt->platformContext()->DrawBitmap(image, srcRect & image->Bounds(), dstRect);
+ ctxt->restore();
+}
+
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& srcPoint, CompositeOperator op, const FloatRect& dstRect)
+{
+ // FIXME: finish this to support also phased position (srcPoint)
+ startAnimation();
+
+ BBitmap* image = nativeImageForCurrentFrame();
+ if (!image || !image->IsValid()) // If the image hasn't fully loaded.
+ return;
+
+ float currentW = 0;
+ float currentH = 0;
+
+ context->save();
+ context->platformContext()->SetDrawingMode(B_OP_ALPHA);
+ context->clip(enclosingIntRect(dstRect));
+
+ while (currentW < dstRect.width()) {
+ while (currentH < dstRect.height()) {
+ context->platformContext()->DrawBitmap(image, BPoint(dstRect.x() + currentW, dstRect.y() + currentH));
+ currentH += tileRect.height();
+ }
+ currentW += tileRect.width();
+ currentH = 0;
+ }
+ context->restore();
+}
+
+void BitmapImage::checkForSolidColor()
+{
+ // FIXME: need to check the RGBA32 buffer to see if it is 1x1.
+ m_isSolidColor = false;
+ m_checkedForSolidColor = true;
+}
+
+BBitmap* BitmapImage::getBBitmap() const
+{
+ return const_cast<BitmapImage*>(this)->frameAtIndex(0);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IntPointHaiku.cpp b/WebCore/platform/graphics/haiku/IntPointHaiku.cpp
new file mode 100644
index 0000000..327e503
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IntPointHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "IntPoint.h"
+
+#include <Point.h>
+
+
+namespace WebCore {
+
+IntPoint::IntPoint(const BPoint& point)
+ : m_x(static_cast<int>(point.x))
+ , m_y(static_cast<int>(point.y))
+{
+}
+
+IntPoint::operator BPoint() const
+{
+ return BPoint(m_x, m_y);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IntRectHaiku.cpp b/WebCore/platform/graphics/haiku/IntRectHaiku.cpp
new file mode 100644
index 0000000..74a0b9d
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IntRectHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "IntRect.h"
+
+#include <Rect.h>
+
+
+namespace WebCore {
+
+IntRect::IntRect(const BRect& rect)
+ : m_location(rect.LeftTop())
+ , m_size(rect.IntegerWidth(), rect.IntegerHeight())
+{
+}
+
+IntRect::operator BRect() const
+{
+ return BRect(BPoint(x(), y()), BSize(width(), height()));
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/IntSizeHaiku.cpp b/WebCore/platform/graphics/haiku/IntSizeHaiku.cpp
new file mode 100644
index 0000000..08c3a9d
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/IntSizeHaiku.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "IntSize.h"
+
+#include <Size.h>
+
+
+namespace WebCore {
+
+IntSize::IntSize(const BSize& size)
+ : m_width(size.IntegerWidth())
+ , m_height(size.IntegerHeight())
+{
+}
+
+IntSize::operator BSize() const
+{
+ return BSize(width(), height());
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/PathHaiku.cpp b/WebCore/platform/graphics/haiku/PathHaiku.cpp
new file mode 100644
index 0000000..d0da025
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/PathHaiku.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 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.
+ */
+
+#include "config.h"
+#include "Path.h"
+
+#include "FloatRect.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include <Region.h>
+
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(new BRegion())
+{
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path::Path(const Path& other)
+ : m_path(new BRegion(*other.platformPath()))
+{
+}
+
+Path& Path::operator=(const Path& other)
+{
+ if (&other != this)
+ m_path = other.platformPath();
+
+ return *this;
+}
+
+bool Path::hasCurrentPoint() const
+{
+ return !isEmpty();
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ return m_path->Contains(point);
+}
+
+void Path::translate(const FloatSize& size)
+{
+ notImplemented();
+}
+
+FloatRect Path::boundingRect() const
+{
+ return m_path->Frame();
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ // FIXME: Use OffsetBy?
+ notImplemented();
+}
+
+void Path::addLineTo(const FloatPoint& p)
+{
+ notImplemented();
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ notImplemented();
+}
+
+void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ notImplemented();
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ notImplemented();
+}
+
+void Path::closeSubpath()
+{
+ notImplemented();
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
+{
+ notImplemented();
+}
+
+void Path::addRect(const FloatRect& r)
+{
+ m_path->Include(r);
+}
+
+void Path::addEllipse(const FloatRect& r)
+{
+ notImplemented();
+}
+
+void Path::clear()
+{
+ m_path->MakeEmpty();
+}
+
+bool Path::isEmpty() const
+{
+ return !m_path->Frame().IsValid();
+}
+
+String Path::debugString() const
+{
+ notImplemented();
+ return String();
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ notImplemented();
+}
+
+void Path::transform(const TransformationMatrix& transform)
+{
+ notImplemented();
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
+{
+ notImplemented();
+ return FloatRect();
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
new file mode 100644
index 0000000..34941c0
--- /dev/null
+++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "SimpleFontData.h"
+
+#include "FloatRect.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "NotImplemented.h"
+#include <Rect.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+
+
+namespace WebCore {
+
+void SimpleFontData::platformInit()
+{
+ BFont* font = m_platformData.font();
+ if (!font)
+ return;
+
+ font_height height;
+ font->GetHeight(&height);
+ m_ascent = static_cast<int>(height.ascent);
+ m_descent = static_cast<int>(height.descent);
+ m_lineSpacing = m_ascent + m_descent;
+ m_xHeight = height.ascent * 0.56f; // Hack taken from the win port.
+ m_lineGap = height.leading;
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+ m_maxCharWidth = 0.f;
+ initCharWidths();
+}
+
+void SimpleFontData::platformDestroy()
+{
+ delete m_smallCapsFontData;
+ m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(0.70f * fontDescription.computedSize());
+ const FontPlatformData* fontPlatformData = new FontPlatformData(desc, desc.family().family());
+ m_smallCapsFontData = new SimpleFontData(*fontPlatformData);
+ }
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ // FIXME: We will need to implement this to load non-ASCII encoding sites
+ return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+ m_treatAsFixedPitch = m_platformData.font() && m_platformData.font()->IsFixed();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ const char charArray[1] = { glyph };
+ float escapements[1];
+
+ if (m_platformData.font()) {
+ m_platformData.font()->GetEscapements(charArray, 1, escapements);
+ return escapements[0] * m_platformData.font()->Size();
+ }
+
+ return 0;
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/Canvas3DLayer.h
new file mode 100644
index 0000000..6c65676
--- /dev/null
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.h
@@ -0,0 +1,50 @@
+/*
+ * 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 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.
+ */
+
+#ifndef Canvas3DLayer_h
+#define Canvas3DLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#import "WebLayer.h"
+
+namespace WebCore {
+ class GraphicsLayer;
+}
+
+@interface Canvas3DLayer : CAOpenGLLayer
+{
+ WebCore::GraphicsLayer* m_layerOwner;
+ CGLContextObj m_contextObj;
+ GLuint m_texture;
+}
+
+-(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture;
+
+@end
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // Canvas3DLayer_h
diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
new file mode 100644
index 0000000..545c58b
--- /dev/null
+++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm
@@ -0,0 +1,123 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#if ENABLE(3D_CANVAS)
+
+#import "Canvas3DLayer.h"
+
+#import "GraphicsLayer.h"
+#import <QuartzCore/QuartzCore.h>
+#import <OpenGL/OpenGL.h>
+
+using namespace WebCore;
+
+@implementation Canvas3DLayer
+
+-(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture
+{
+ m_contextObj = context;
+ m_texture = texture;
+ self = [super init];
+ return self;
+}
+
+-(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
+{
+ CGLPixelFormatAttribute attribs[] =
+ {
+ (CGLPixelFormatAttribute) kCGLPFAAccelerated,
+ (CGLPixelFormatAttribute) kCGLPFAColorSize, (CGLPixelFormatAttribute) 32,
+ (CGLPixelFormatAttribute) kCGLPFADisplayMask, (CGLPixelFormatAttribute) mask,
+ (CGLPixelFormatAttribute) 0
+ };
+
+ CGLPixelFormatObj pixelFormatObj;
+ GLint numPixelFormats;
+
+ CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats);
+ return pixelFormatObj;
+}
+
+-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+{
+ CGLContextObj contextObj;
+ CGLCreateContext(pixelFormat, m_contextObj, &contextObj);
+ return contextObj;
+}
+
+-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
+{
+ CGRect frame = [self frame];
+
+ // draw the FBO into the layer
+ glViewport(0, 0, frame.size.width, frame.size.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1, 1, -1, 1, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+
+ glBegin(GL_TRIANGLE_FAN);
+ glTexCoord2f(0, 0);
+ glVertex2f(-1, -1);
+ glTexCoord2f(1, 0);
+ glVertex2f(1, -1);
+ glTexCoord2f(1, 1);
+ glVertex2f(1, 1);
+ glTexCoord2f(0, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ // Call super to finalize the drawing. By default all it does is call glFlush().
+ [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
+}
+
+@end
+
+@implementation Canvas3DLayer(WebLayerAdditions)
+
+-(void)setLayerOwner:(GraphicsLayer*)aLayer
+{
+ m_layerOwner = aLayer;
+}
+
+-(GraphicsLayer*)layerOwner
+{
+ return m_layerOwner;
+}
+
+@end
+
+#endif // ENABLE(3D_CANVAS)
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/CoreTextController.cpp
index 05f29b5..b2682e4 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/CoreTextController.cpp
@@ -365,7 +365,7 @@ void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsig
RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
- RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes()));
+ RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
RetainPtr<CTTypesetterRef> typesetter;
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
index e40bbab..5e72101 100644
--- a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -46,11 +46,13 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
ATSFontContainerRef containerRef = 0;
ATSFontRef fontRef = 0;
+ RetainPtr<CGFontRef> cgFontRef;
+
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
RetainPtr<CFDataRef> bufferData(AdoptCF, buffer->createCFData());
RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(bufferData.get()));
- CGFontRef cgFontRef = CGFontCreateWithDataProvider(dataProvider.get());
+ cgFontRef.adoptCF(CGFontCreateWithDataProvider(dataProvider.get()));
if (!cgFontRef)
return 0;
#else
@@ -75,13 +77,11 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
return 0;
}
- CGFontRef cgFontRef = CGFontCreateWithPlatformFont(&fontRef);
+ cgFontRef.adoptCF(CGFontCreateWithPlatformFont(&fontRef));
#ifndef BUILDING_ON_TIGER
// Workaround for <rdar://problem/5675504>.
- if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef)) {
- CFRelease(cgFontRef);
+ if (cgFontRef && !CGFontGetNumberOfGlyphs(cgFontRef.get()))
cgFontRef = 0;
- }
#endif
if (!cgFontRef) {
ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
@@ -89,7 +89,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
}
#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- return new FontCustomPlatformData(containerRef, fontRef, cgFontRef);
+ return new FontCustomPlatformData(containerRef, fontRef, cgFontRef.releaseRef());
}
}
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index df9494a..b2b9a5c 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -50,10 +50,33 @@ bool Font::canReturnFallbackFontsForComplexText()
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
+ bool newShouldUseFontSmoothing = shouldUseSmoothing();
+
+ switch(fontDescription().fontSmoothing()) {
+ case Antialiased: {
+ context->setShouldAntialias(true);
+ newShouldUseFontSmoothing = false;
+ break;
+ }
+ case SubpixelAntialiased: {
+ context->setShouldAntialias(true);
+ newShouldUseFontSmoothing = true;
+ break;
+ }
+ case NoSmoothing: {
+ context->setShouldAntialias(false);
+ newShouldUseFontSmoothing = false;
+ break;
+ }
+ case AutoSmoothing: {
+ // For the AutoSmooth case, don't do anything! Keep the default settings.
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
- bool newShouldUseFontSmoothing = shouldUseSmoothing();
-
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
index 051abb7..409bda4 100644
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ b/WebCore/platform/graphics/mac/FontMacATSUI.mm
@@ -105,12 +105,12 @@ static bool fontHasMirroringInfo(ATSUFontID fontID)
return false;
}
-static void disableLigatures(const SimpleFontData* fontData)
+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 (fontData->platformData().allowsLigatures())
+ if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
return;
ATSUFontFeatureType featureTypes[] = { kLigaturesType };
@@ -120,7 +120,7 @@ static void disableLigatures(const SimpleFontData* fontData)
LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", status);
}
-static void initializeATSUStyle(const SimpleFontData* fontData)
+static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
{
if (fontData->m_ATSUStyleInitialized)
return;
@@ -141,19 +141,28 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
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) };
- // 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);
+ 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);
+ disableLigatures(fontData, textMode);
fontData->m_ATSUStyleInitialized = true;
}
@@ -329,7 +338,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
OSStatus status;
ATSULayoutOperationOverrideSpecifier overrideSpecifier;
- initializeATSUStyle(fontData);
+ 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.
@@ -393,7 +402,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);
substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;
if (substituteFontData) {
- initializeATSUStyle(substituteFontData);
+ initializeATSUStyle(substituteFontData, m_font->fontDescription().textRenderingMode());
if (substituteFontData->m_ATSUStyle)
ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);
} else
@@ -412,7 +421,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
if (i == substituteOffset || i == substituteOffset + substituteLength) {
if (isSmallCap) {
isSmallCap = false;
- initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()));
+ 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)
@@ -456,7 +465,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
} else {
if (isSmallCap) {
isSmallCap = false;
- initializeATSUStyle(smallCapsData);
+ initializeATSUStyle(smallCapsData, m_font->fontDescription().textRenderingMode());
ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
}
m_fonts[i] = r;
@@ -504,8 +513,8 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint&
firstGlyphBounds = zeroTrapezoid;
}
- float beforeWidth = MIN(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
- float afterWidth = MAX(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
+ 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);
@@ -591,8 +600,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
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));
+ 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
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
new file mode 100644
index 0000000..cd66445
--- /dev/null
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp
@@ -0,0 +1,1698 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "GraphicsContext3D.h"
+
+#include "CachedImage.h"
+#include "CanvasBuffer.h"
+#include "CanvasFramebuffer.h"
+#include "CanvasArray.h"
+#include "CanvasFloatArray.h"
+#include "CanvasIntArray.h"
+#include "CanvasObject.h"
+#include "CanvasProgram.h"
+#include "CanvasRenderbuffer.h"
+#include "CanvasShader.h"
+#include "CanvasTexture.h"
+#include "CanvasUnsignedByteArray.h"
+#include "CString.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "ImageBuffer.h"
+#include "NotImplemented.h"
+#include "WebKitCSSMatrix.h"
+
+#include <CoreGraphics/CGBitmapContext.h>
+
+namespace WebCore {
+
+GraphicsContext3D::GraphicsContext3D()
+{
+ CGLPixelFormatAttribute attribs[] =
+ {
+ (CGLPixelFormatAttribute) kCGLPFAAccelerated,
+ (CGLPixelFormatAttribute) kCGLPFAColorSize, (CGLPixelFormatAttribute) 32,
+ (CGLPixelFormatAttribute) kCGLPFADepthSize, (CGLPixelFormatAttribute) 32,
+ (CGLPixelFormatAttribute) kCGLPFASupersample,
+ (CGLPixelFormatAttribute) 0
+ };
+
+ CGLPixelFormatObj pixelFormatObj;
+ GLint numPixelFormats;
+
+ CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats);
+
+ CGLCreateContext(pixelFormatObj, 0, &m_contextObj);
+
+ CGLDestroyPixelFormat(pixelFormatObj);
+
+ // Set the current context to the one given to us.
+ CGLSetCurrentContext(m_contextObj);
+
+ // create a texture to render into
+ ::glGenTextures(1, &m_texture);
+ ::glBindTexture(GL_TEXTURE_2D, m_texture);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+
+ // create an FBO
+ ::glGenFramebuffersEXT(1, &m_fbo);
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+
+ ::glGenRenderbuffersEXT(1, &m_depthBuffer);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
+ ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 1, 1);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
+
+ ::glClearColor(0, 0, 0, 0);
+}
+
+GraphicsContext3D::~GraphicsContext3D()
+{
+ CGLSetCurrentContext(m_contextObj);
+ ::glDeleteRenderbuffersEXT(1, & m_depthBuffer);
+ ::glDeleteTextures(1, &m_texture);
+ ::glDeleteFramebuffersEXT(1, &m_fbo);
+ CGLSetCurrentContext(0);
+ CGLDestroyContext(m_contextObj);
+}
+
+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)
+{
+ UNUSED_PARAM(context);
+}
+
+void GraphicsContext3D::endPaint()
+{
+}
+
+void GraphicsContext3D::reshape(int width, int height)
+{
+ if (width == m_currentWidth && height == m_currentHeight)
+ return;
+
+ m_currentWidth = width;
+ m_currentHeight = height;
+
+ CGLSetCurrentContext(m_contextObj);
+
+ ::glBindTexture(GL_TEXTURE_2D, m_texture);
+ ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ ::glBindTexture(GL_TEXTURE_2D, 0);
+
+ ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer);
+ ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
+ ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+
+ ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
+ ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer);
+ GLenum status = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ // FIXME: cleanup
+ notImplemented();
+ }
+
+ ::glViewport(0, 0, m_currentWidth, m_currentHeight);
+ ::glClear(GL_COLOR_BUFFER_BIT);
+ ::glFlush();
+}
+
+static inline void ensureContext(CGLContextObj context)
+{
+ CGLContextObj currentContext = CGLGetCurrentContext();
+ if (currentContext != context)
+ CGLSetCurrentContext(context);
+}
+
+void GraphicsContext3D::activeTexture(unsigned long texture)
+{
+ ensureContext(m_contextObj);
+ ::glActiveTexture(texture);
+}
+
+void GraphicsContext3D::attachShader(CanvasProgram* program, CanvasShader* shader)
+{
+ if (!program || !shader)
+ return;
+ ensureContext(m_contextObj);
+ ::glAttachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::bindAttribLocation(CanvasProgram* program, unsigned long index, const String& name)
+{
+ if (!program)
+ return;
+ ensureContext(m_contextObj);
+ ::glBindAttribLocation((GLuint) program->object(), index, name.utf8().data());
+}
+
+void GraphicsContext3D::bindBuffer(unsigned long target, CanvasBuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindBuffer(target, buffer ? (GLuint) buffer->object() : 0);
+}
+
+
+void GraphicsContext3D::bindFramebuffer(unsigned long target, CanvasFramebuffer* buffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindFramebufferEXT(target, buffer ? (GLuint) buffer->object() : m_fbo);
+}
+
+void GraphicsContext3D::bindRenderbuffer(unsigned long target, CanvasRenderbuffer* renderbuffer)
+{
+ ensureContext(m_contextObj);
+ ::glBindBuffer(target, renderbuffer ? (GLuint) renderbuffer->object() : 0);
+}
+
+
+void GraphicsContext3D::bindTexture(unsigned long target, CanvasTexture* texture)
+{
+ ensureContext(m_contextObj);
+ ::glBindTexture(target, texture ? (GLuint) texture->object() : 0);
+}
+
+void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha));
+}
+
+void GraphicsContext3D::blendEquation( unsigned long mode )
+{
+ ensureContext(m_contextObj);
+ ::glBlendEquation(mode);
+}
+
+void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendEquationSeparate(modeRGB, modeAlpha);
+}
+
+
+void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor)
+{
+ ensureContext(m_contextObj);
+ ::glBlendFunc(sfactor, dfactor);
+}
+
+void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha)
+{
+ ensureContext(m_contextObj);
+ ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage)
+{
+ ensureContext(m_contextObj);
+ ::glBufferData(target, size, 0, usage);
+}
+void GraphicsContext3D::bufferData(unsigned long target, CanvasArray* array, unsigned long usage)
+{
+ if (!array || !array->length())
+ return;
+
+ ensureContext(m_contextObj);
+ ::glBufferData(target, array->sizeInBytes(), array->baseAddress(), usage);
+}
+
+void GraphicsContext3D::bufferSubData(unsigned long target, long offset, CanvasArray* array)
+{
+ if (!array || !array->length())
+ return;
+
+ ensureContext(m_contextObj);
+ ::glBufferSubData(target, offset, array->sizeInBytes(), array->baseAddress());
+}
+
+unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target)
+{
+ ensureContext(m_contextObj);
+ return ::glCheckFramebufferStatusEXT(target);
+}
+
+void GraphicsContext3D::clearColor(double r, double g, double b, double a)
+{
+ ensureContext(m_contextObj);
+ ::glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a));
+}
+
+void GraphicsContext3D::clear(unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glClear(mask);
+}
+
+void GraphicsContext3D::clearDepth(double depth)
+{
+ ensureContext(m_contextObj);
+ ::glClearDepth(depth);
+}
+
+void GraphicsContext3D::clearStencil(long s)
+{
+ ensureContext(m_contextObj);
+ ::glClearStencil(s);
+}
+
+void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha)
+{
+ ensureContext(m_contextObj);
+ ::glColorMask(red, green, blue, alpha);
+}
+
+void GraphicsContext3D::compileShader(CanvasShader* shader)
+{
+ if (!shader)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glCompileShader((GLuint) shader->object());
+}
+
+void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border)
+{
+ ensureContext(m_contextObj);
+ ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
+}
+
+void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+}
+
+void GraphicsContext3D::cullFace(unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glCullFace(mode);
+}
+
+void GraphicsContext3D::depthFunc(unsigned long func)
+{
+ ensureContext(m_contextObj);
+ ::glDepthFunc(func);
+}
+
+void GraphicsContext3D::depthMask(bool flag)
+{
+ ensureContext(m_contextObj);
+ ::glDepthMask(flag);
+}
+
+void GraphicsContext3D::depthRange(double zNear, double zFar)
+{
+ ensureContext(m_contextObj);
+ ::glDepthRange(zNear, zFar);
+}
+
+void GraphicsContext3D::detachShader(CanvasProgram* program, CanvasShader* shader)
+{
+ if (!program || !shader)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glDetachShader((GLuint) program->object(), (GLuint) shader->object());
+}
+
+void GraphicsContext3D::disable(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ ::glDisable(cap);
+}
+
+void GraphicsContext3D::disableVertexAttribArray(unsigned long index)
+{
+ ensureContext(m_contextObj);
+ ::glDisableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count)
+{
+ ensureContext(m_contextObj);
+ ::glDrawArrays(mode, first, count);
+}
+
+void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset)
+{
+ ensureContext(m_contextObj);
+ ::glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::enable(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ ::glEnable(cap);
+}
+
+void GraphicsContext3D::enableVertexAttribArray(unsigned long index)
+{
+ ensureContext(m_contextObj);
+ ::glEnableVertexAttribArray(index);
+}
+
+void GraphicsContext3D::finish()
+{
+ ensureContext(m_contextObj);
+ ::glFinish();
+}
+
+void GraphicsContext3D::flush()
+{
+ ensureContext(m_contextObj);
+ ::glFlush();
+}
+
+void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, CanvasRenderbuffer* buffer)
+{
+ if (!buffer)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, (GLuint) buffer->object());
+}
+
+void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, CanvasTexture* texture, long level)
+{
+ if (!texture)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glFramebufferTexture2DEXT(target, attachment, textarget, (GLuint) texture->object(), level);
+}
+
+void GraphicsContext3D::frontFace(unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glFrontFace(mode);
+}
+
+void GraphicsContext3D::generateMipmap(unsigned long target)
+{
+ ensureContext(m_contextObj);
+ ::glGenerateMipmapEXT(target);
+}
+
+int GraphicsContext3D::getAttribLocation(CanvasProgram* program, const String& name)
+{
+ if (!program)
+ return -1;
+
+ ensureContext(m_contextObj);
+ return ::glGetAttribLocation((GLuint) program->object(), name.utf8().data());
+}
+
+unsigned long GraphicsContext3D::getError()
+{
+ ensureContext(m_contextObj);
+ return ::glGetError();
+}
+
+String GraphicsContext3D::getString(unsigned long name)
+{
+ ensureContext(m_contextObj);
+ return String((const char*) ::glGetString(name));
+}
+
+void GraphicsContext3D::hint(unsigned long target, unsigned long mode)
+{
+ ensureContext(m_contextObj);
+ ::glHint(target, mode);
+}
+
+bool GraphicsContext3D::isBuffer(CanvasBuffer* buffer)
+{
+ if (!buffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsBuffer((GLuint) buffer->object());
+}
+
+bool GraphicsContext3D::isEnabled(unsigned long cap)
+{
+ ensureContext(m_contextObj);
+ return ::glIsEnabled(cap);
+}
+
+bool GraphicsContext3D::isFramebuffer(CanvasFramebuffer* framebuffer)
+{
+ if (!framebuffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsFramebufferEXT((GLuint) framebuffer->object());
+}
+
+bool GraphicsContext3D::isProgram(CanvasProgram* program)
+{
+ if (!program)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsProgram((GLuint) program->object());
+}
+
+bool GraphicsContext3D::isRenderbuffer(CanvasRenderbuffer* renderbuffer)
+{
+ if (!renderbuffer)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsRenderbufferEXT((GLuint) renderbuffer->object());
+}
+
+bool GraphicsContext3D::isShader(CanvasShader* shader)
+{
+ if (!shader)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsShader((GLuint) shader->object());
+}
+
+bool GraphicsContext3D::isTexture(CanvasTexture* texture)
+{
+ if (!texture)
+ return false;
+
+ ensureContext(m_contextObj);
+ return ::glIsTexture((GLuint) texture->object());
+}
+
+void GraphicsContext3D::lineWidth(double width)
+{
+ ensureContext(m_contextObj);
+ ::glLineWidth(static_cast<float>(width));
+}
+
+void GraphicsContext3D::linkProgram(CanvasProgram* program)
+{
+ if (!program)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glLinkProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::pixelStorei(unsigned long pname, long param)
+{
+ ensureContext(m_contextObj);
+ ::glPixelStorei(pname, param);
+}
+
+void GraphicsContext3D::polygonOffset(double factor, double units)
+{
+ ensureContext(m_contextObj);
+ ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units));
+}
+
+void GraphicsContext3D::releaseShaderCompiler()
+{
+ // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants
+ ensureContext(m_contextObj);
+ //::glReleaseShaderCompiler();
+}
+
+void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glRenderbufferStorageEXT(target, internalformat, width, height);
+}
+
+void GraphicsContext3D::sampleCoverage(double value, bool invert)
+{
+ ensureContext(m_contextObj);
+ ::glSampleCoverage(static_cast<float>(value), invert);
+}
+
+void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::glScissor(x, y, width, height);
+}
+
+void GraphicsContext3D::shaderSource(CanvasShader* shader, const String& string)
+{
+ if (!shader)
+ return;
+
+ ensureContext(m_contextObj);
+ const CString& cs = string.utf8();
+ const char* s = cs.data();
+
+ int length = string.length();
+ ::glShaderSource((GLuint) shader->object(), 1, &s, &length);
+}
+
+void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilFunc(func, ref, mask);
+}
+
+void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilFuncSeparate(face, func, ref, mask);
+}
+
+void GraphicsContext3D::stencilMask(unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilMask(mask);
+}
+
+void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask)
+{
+ ensureContext(m_contextObj);
+ ::glStencilMaskSeparate(face, mask);
+}
+
+void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ ensureContext(m_contextObj);
+ ::glStencilOp(fail, zfail, zpass);
+}
+
+void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass)
+{
+ ensureContext(m_contextObj);
+ ::glStencilOpSeparate(face, fail, zfail, zpass);
+}
+
+void GraphicsContext3D::texParameterf(unsigned target, unsigned pname, float value)
+{
+ ensureContext(m_contextObj);
+ ::glTexParameterf(target, pname, static_cast<float>(value));
+}
+
+void GraphicsContext3D::texParameteri(unsigned target, unsigned pname, int value)
+{
+ ensureContext(m_contextObj);
+ ::glTexParameteri(target, pname, static_cast<float>(value));
+}
+
+void GraphicsContext3D::uniform1f(long location, float v0)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1f(location, v0);
+}
+
+void GraphicsContext3D::uniform1fv(long location, float* array, int size)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2f(long location, float v0, float v1)
+{
+ ensureContext(m_contextObj);
+ ::glUniform2f(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 2
+ ensureContext(m_contextObj);
+ ::glUniform2fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2)
+{
+ ensureContext(m_contextObj);
+ ::glUniform3f(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 3
+ ensureContext(m_contextObj);
+ ::glUniform3fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3)
+{
+ ensureContext(m_contextObj);
+ ::glUniform4f(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4fv(long location, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniform4fv(location, size, array);
+}
+
+void GraphicsContext3D::uniform1i(long location, int v0)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1i(location, v0);
+}
+
+void GraphicsContext3D::uniform1iv(long location, int* array, int size)
+{
+ ensureContext(m_contextObj);
+ ::glUniform1iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform2i(long location, int v0, int v1)
+{
+ ensureContext(m_contextObj);
+ ::glUniform2i(location, v0, v1);
+}
+
+void GraphicsContext3D::uniform2iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 2
+ ensureContext(m_contextObj);
+ ::glUniform2iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2)
+{
+ ensureContext(m_contextObj);
+ ::glUniform3i(location, v0, v1, v2);
+}
+
+void GraphicsContext3D::uniform3iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 3
+ ensureContext(m_contextObj);
+ ::glUniform3iv(location, size, array);
+}
+
+void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3)
+{
+ ensureContext(m_contextObj);
+ ::glUniform4i(location, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::uniform4iv(long location, int* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniform4iv(location, size, array);
+}
+
+void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 4
+ ensureContext(m_contextObj);
+ ::glUniformMatrix2fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 9
+ ensureContext(m_contextObj);
+ ::glUniformMatrix3fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size)
+{
+ // FIXME: length needs to be a multiple of 16
+ ensureContext(m_contextObj);
+ ::glUniformMatrix4fv(location, size, transpose, array);
+}
+
+void GraphicsContext3D::useProgram(CanvasProgram* program)
+{
+ if (!program)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glUseProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::validateProgram(CanvasProgram* program)
+{
+ if (!program)
+ return;
+
+ ensureContext(m_contextObj);
+ ::glValidateProgram((GLuint) program->object());
+}
+
+void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib1f(indx, v0);
+}
+
+void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib1fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib2f(indx, v0, v1);
+}
+
+void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib2fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib3f(indx, v0, v1, v2);
+}
+
+void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib3fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib4f(indx, v0, v1, v2, v3);
+}
+
+void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttrib4fv(indx, array);
+}
+
+void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset)
+{
+ ensureContext(m_contextObj);
+ ::glVertexAttribPointer(indx, size, type, normalized, stride, reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
+}
+
+void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height)
+{
+ ensureContext(m_contextObj);
+ ::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)
+{
+ 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;
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getFloatv(unsigned long pname)
+{
+ 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;
+}
+
+int GraphicsContext3D::getInteger(unsigned long pname)
+{
+ 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;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getIntegerv(unsigned long pname)
+{
+ 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;
+}
+
+int GraphicsContext3D::getBufferParameteri(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getFramebufferAttachmentParameteri(unsigned long target, unsigned long attachment, unsigned long pname)
+{
+ 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();
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetProgramiv((GLuint) program->object(), GL_INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) malloc(length);
+ ::glGetProgramInfoLog((GLuint) program->object(), length, &size, info);
+ String s(info);
+ free(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)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasIntArray> array = CanvasIntArray::create(1);
+ GLint data;
+ ::glGetBufferParameteriv(target, pname, &data);
+ array->set(0, static_cast<int>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getShaderi(CanvasShader* shader, unsigned long pname)
+{
+ 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;
+
+ 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;
+}
+
+String GraphicsContext3D::getShaderInfoLog(CanvasShader* shader)
+{
+ if (!shader)
+ return String();
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetShaderiv((GLuint) shader->object(), GL_INFO_LOG_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) malloc(length);
+ ::glGetShaderInfoLog((GLuint) shader->object(), length, &size, info);
+ String s(info);
+ free(info);
+ return s;
+}
+
+String GraphicsContext3D::getShaderSource(CanvasShader* shader)
+{
+ if (!shader)
+ return String();
+
+ ensureContext(m_contextObj);
+ GLint length;
+ ::glGetShaderiv((GLuint) shader->object(), GL_SHADER_SOURCE_LENGTH, &length);
+
+ GLsizei size;
+ GLchar* info = (GLchar*) malloc(length);
+ ::glGetShaderSource((GLuint) shader->object(), length, &size, info);
+ String s(info);
+ free(info);
+ return s;
+}
+
+
+float GraphicsContext3D::getTexParameterf(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLfloat data;
+ ::glGetTexParameterfv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ RefPtr<CanvasFloatArray> array = CanvasFloatArray::create(1);
+ GLfloat data;
+ ::glGetTexParameterfv(target, pname, &data);
+ array->set(0, static_cast<float>(data));
+
+ return array;
+}
+
+int GraphicsContext3D::getTexParameteri(unsigned long target, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+ GLint data;
+ ::glGetTexParameteriv(target, pname, &data);
+ return data;
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long pname)
+{
+ 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;
+}
+
+PassRefPtr<CanvasFloatArray> GraphicsContext3D::getUniformfv(CanvasProgram* program, long location)
+{
+ // 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;
+
+ 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)
+{
+ ensureContext(m_contextObj);
+ GLint buf[4];
+ ::glGetVertexAttribiv(index, pname, buf);
+ return buf[0];
+}
+
+PassRefPtr<CanvasIntArray> GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long pname)
+{
+ 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;
+}
+
+long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long pname)
+{
+ ensureContext(m_contextObj);
+
+ void* pointer;
+ ::glGetVertexAttribPointerv(index, pname, &pointer);
+ return reinterpret_cast<long>(pointer);
+}
+
+// Assumes the texture you want to go into is bound
+static void imageToTexture(Image* image, unsigned target, unsigned level)
+{
+ if (!image)
+ return;
+
+ CGImageRef textureImage = image->getCGImageRef();
+ if (!textureImage)
+ return;
+
+ size_t textureWidth = CGImageGetWidth(textureImage);
+ size_t textureHeight = CGImageGetHeight(textureImage);
+
+ GLubyte* textureData = (GLubyte*) malloc(textureWidth * textureHeight * 4);
+ CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth, textureHeight, 8, textureWidth * 4,
+ CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast);
+
+ 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);
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, CanvasArray* pixels)
+{
+ // FIXME: Need to do bounds checking on the buffer here.
+ ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels->baseAddress());
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, ImageData* pixels)
+{
+ // FIXME: need to implement this form
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(internalformat);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(border);
+ UNUSED_PARAM(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLImageElement* image, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+
+ if (!image)
+ return -1;
+
+ 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);
+ return 0;
+}
+
+int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha)
+{
+ // FIXME: need to implement this form
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(video);
+
+ // 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, unsigned format, unsigned type, CanvasArray* pixels)
+{
+ // 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(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, ImageData* pixels)
+{
+ // 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(format);
+ UNUSED_PARAM(type);
+ UNUSED_PARAM(pixels);
+ return -1;
+}
+
+int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLImageElement* 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);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(image);
+
+ // 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, 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
+ UNUSED_PARAM(target);
+ UNUSED_PARAM(level);
+ UNUSED_PARAM(xoff);
+ UNUSED_PARAM(yoff);
+ UNUSED_PARAM(width);
+ UNUSED_PARAM(height);
+ UNUSED_PARAM(video);
+
+ // FIXME: need to support flipY and premultiplyAlpha
+ UNUSED_PARAM(flipY);
+ UNUSED_PARAM(premultiplyAlpha);
+ return -1;
+}
+
+unsigned GraphicsContext3D::createBuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenBuffers(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createFramebuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenFramebuffersEXT(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createProgram()
+{
+ ensureContext(m_contextObj);
+ return glCreateProgram();
+}
+
+unsigned GraphicsContext3D::createRenderbuffer()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenRenderbuffersEXT(1, &o);
+ return o;
+}
+
+unsigned GraphicsContext3D::createShader(ShaderType type)
+{
+ ensureContext(m_contextObj);
+ return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
+}
+
+unsigned GraphicsContext3D::createTexture()
+{
+ ensureContext(m_contextObj);
+ GLuint o;
+ glGenTextures(1, &o);
+ return o;
+}
+
+void GraphicsContext3D::deleteBuffer(unsigned buffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteBuffers(1, &buffer);
+}
+
+void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteFramebuffersEXT(1, &framebuffer);
+}
+
+void GraphicsContext3D::deleteProgram(unsigned program)
+{
+ ensureContext(m_contextObj);
+ glDeleteProgram(program);
+}
+
+void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer)
+{
+ ensureContext(m_contextObj);
+ glDeleteRenderbuffersEXT(1, &renderbuffer);
+}
+
+void GraphicsContext3D::deleteShader(unsigned shader)
+{
+ ensureContext(m_contextObj);
+ glDeleteShader(shader);
+}
+
+void GraphicsContext3D::deleteTexture(unsigned texture)
+{
+ ensureContext(m_contextObj);
+ glDeleteTextures(1, &texture);
+}
+
+int GraphicsContext3D::sizeInBytes(int type)
+{
+ switch (type) {
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ default:
+ return 0;
+ }
+}
+
+}
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 2404319..6c9b872 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -50,27 +50,26 @@ void GraphicsContext::drawFocusRing(const Color& color)
int radius = (focusRingWidth() - 1) / 2;
int offset = radius + focusRingOffset();
- CGColorRef colorRef = color.isValid() ? createCGColor(color) : 0;
+ RetainPtr<CGColorRef> colorRef;
+ if (color.isValid())
+ colorRef.adoptCF(createCGColor(color));
- CGMutablePathRef focusRingPath = CGPathCreateMutable();
+ RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
for (unsigned i = 0; i < rectCount; i++)
- CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset));
+ CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
CGContextRef context = platformContext();
#ifdef BUILDING_ON_TIGER
CGContextBeginTransparencyLayer(context, NULL);
#endif
CGContextBeginPath(context);
- CGContextAddPath(context, focusRingPath);
- wkDrawFocusRing(context, colorRef, radius);
+ CGContextAddPath(context, focusRingPath.get());
+ wkDrawFocusRing(context, colorRef.get(), radius);
#ifdef BUILDING_ON_TIGER
CGContextEndTransparencyLayer(context);
#endif
- CGColorRelease(colorRef);
-
- CGPathRelease(focusRingPath);
}
#ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp.
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index ebdc6ac..d0e1108 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -62,6 +62,8 @@ public:
virtual void removeFromParent();
+ virtual void setMaskLayer(GraphicsLayer*);
+
virtual void setPosition(const FloatPoint&);
virtual void setAnchorPoint(const FloatPoint3D&);
virtual void setSize(const FloatSize&);
@@ -86,6 +88,10 @@ public:
virtual void setNeedsDisplay();
virtual void setNeedsDisplayInRect(const FloatRect&);
+#if ENABLE(3D_CANVAS)
+ virtual void setGraphicsContext3DNeedsDisplay();
+#endif
+
virtual void setContentsRect(const IntRect&);
virtual void suspendAnimations(double time);
@@ -98,6 +104,9 @@ public:
virtual void setContentsToImage(Image*);
virtual void setContentsToVideo(PlatformLayer*);
+#if ENABLE(3D_CANVAS)
+ virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*);
+#endif
virtual PlatformLayer* platformLayer() const;
@@ -170,8 +179,12 @@ private:
void updateContentsImage();
void updateContentsVideo();
+#if ENABLE(3D_CANVAS)
+ void updateContentsGraphicsContext3D();
+#endif
void updateContentsRect();
void updateGeometryOrientation();
+ void updateMaskLayer();
void updateLayerAnimations();
@@ -199,8 +212,12 @@ private:
DirtyRectsChanged = 1 << 16,
ContentsImageChanged = 1 << 17,
ContentsVideoChanged = 1 << 18,
- ContentsRectChanged = 1 << 19,
- GeometryOrientationChanged = 1 << 20
+#if ENABLE(3D_CANVAS)
+ ContentsGraphicsContext3DChanged = 1 << 19,
+#endif
+ ContentsRectChanged = 1 << 20,
+ GeometryOrientationChanged = 1 << 21,
+ MaskLayerChanged = 1 << 22
};
typedef unsigned LayerChangeFlags;
void noteLayerPropertyChanged(LayerChangeFlags flags);
@@ -215,6 +232,9 @@ private:
NoContentsLayer = 0,
ContentsLayerForImage,
ContentsLayerForVideo
+#if ENABLE(3D_CANVAS)
+ ,ContentsLayerForGraphicsLayer3D
+#endif
};
ContentsLayerPurpose m_contentsLayerPurpose;
@@ -260,6 +280,11 @@ private:
Vector<FloatRect> m_dirtyRects;
LayerChangeFlags m_uncommittedChanges;
+
+#if ENABLE(3D_CANVAS)
+ PlatformGraphicsContext3D m_platformGraphicsContext3D;
+ Platform3DObject m_platformTexture;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index e5b9035..e9960f1 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -31,6 +31,9 @@
#import "Animation.h"
#import "BlockExceptions.h"
+#if ENABLE(3D_CANVAS)
+#import "Canvas3DLayer.h"
+#endif
#import "CString.h"
#import "FloatConversion.h"
#import "FloatRect.h"
@@ -145,11 +148,11 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
case TransformOperation::ROTATE_Y:
return [NSNumber numberWithDouble:transformOp ? deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle()) : 0];
case TransformOperation::SCALE_X:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1];
case TransformOperation::SCALE_Y:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1];
case TransformOperation::SCALE_Z:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 0];
+ return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1];
case TransformOperation::TRANSLATE_X:
return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0];
case TransformOperation::TRANSLATE_Y:
@@ -157,13 +160,23 @@ static NSValue* getTransformFunctionValue(const TransformOperation* transformOp,
case TransformOperation::TRANSLATE_Z:
return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0];
case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1],
+ nil];
case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0],
+ [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0],
+ nil];
case TransformOperation::SKEW_X:
case TransformOperation::SKEW_Y:
case TransformOperation::SKEW:
case TransformOperation::MATRIX:
- case TransformOperation::SCALE_3D:
- case TransformOperation::TRANSLATE_3D:
case TransformOperation::ROTATE_3D:
case TransformOperation::MATRIX_3D:
case TransformOperation::PERSPECTIVE:
@@ -204,6 +217,12 @@ static NSString* getValueFunctionNameForTransformOperation(TransformOperation::O
return @"translateY"; // kCAValueFunctionTranslateY;
case TransformOperation::TRANSLATE_Z:
return @"translateZ"; // kCAValueFunctionTranslateZ;
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return @"scale"; // kCAValueFunctionScale;
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return @"translate"; // kCAValueFunctionTranslate;
default:
return nil;
}
@@ -331,7 +350,7 @@ static NSDictionary* nullActionsDictionary()
return actions;
}
-GraphicsLayer* GraphicsLayer::createGraphicsLayer(GraphicsLayerClient* client)
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
{
return new GraphicsLayerCA(client);
}
@@ -341,6 +360,10 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
, m_contentsLayerPurpose(NoContentsLayer)
, m_contentsLayerHasBackgroundColor(false)
, m_uncommittedChanges(NoChange)
+#if ENABLE(3D_CANVAS)
+, m_platformGraphicsContext3D(NullPlatformGraphicsContext3D)
+, m_platformTexture(NullPlatform3DObject)
+#endif
{
BEGIN_BLOCK_OBJC_EXCEPTIONS
m_layer.adoptNS([[WebLayer alloc] init]);
@@ -432,6 +455,15 @@ void GraphicsLayerCA::removeFromParent()
GraphicsLayer::removeFromParent();
}
+void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+ noteLayerPropertyChanged(MaskLayerChanged);
+}
+
void GraphicsLayerCA::setPosition(const FloatPoint& point)
{
if (point == m_position)
@@ -672,10 +704,10 @@ void GraphicsLayerCA::setContentsToImage(Image* image)
CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
- if (CFEqual(colorSpace, deviceRGB)) {
- // CoreGraphics renders images tagged with DeviceRGB using GenericRGB. When we hand such
+ if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
+ // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
// images to CA we need to tag them similarly so CA rendering matches CG rendering.
- static CGColorSpaceRef genericRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
}
m_contentsLayerPurpose = ContentsLayerForImage;
@@ -733,6 +765,9 @@ void GraphicsLayerCA::recursiveCommitChanges()
{
commitLayerChanges();
+ if (m_maskLayer)
+ static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChanges();
+
const Vector<GraphicsLayer*>& childLayers = children();
size_t numChildren = childLayers.size();
for (size_t i = 0; i < numChildren; ++i) {
@@ -763,7 +798,12 @@ void GraphicsLayerCA::commitLayerChanges()
if (m_uncommittedChanges & ContentsVideoChanged) // Needs to happen before ChildrenChanged
updateContentsVideo();
-
+
+#if ENABLE(3D_CANVAS)
+ if (m_uncommittedChanges & ContentsGraphicsContext3DChanged) // Needs to happen before ChildrenChanged
+ updateContentsGraphicsContext3D();
+#endif
+
if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
updateLayerBackgroundColor();
@@ -812,6 +852,9 @@ void GraphicsLayerCA::commitLayerChanges()
if (m_uncommittedChanges & GeometryOrientationChanged)
updateGeometryOrientation();
+ if (m_uncommittedChanges & MaskLayerChanged)
+ updateMaskLayer();
+
m_uncommittedChanges = NoChange;
END_BLOCK_OBJC_EXCEPTIONS
}
@@ -821,10 +864,12 @@ void GraphicsLayerCA::updateSublayerList()
NSMutableArray* newSublayers = nil;
if (m_transformLayer) {
- // FIXME: add the primary layer in the correct order with negative z-order children.
+ // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
newSublayers = [[NSMutableArray alloc] initWithObjects:m_layer.get(), nil];
} 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 = [[NSMutableArray alloc] initWithObjects:m_contentsLayer.get(), nil];
}
@@ -1061,6 +1106,18 @@ void GraphicsLayerCA::updateContentsVideo()
}
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::updateContentsGraphicsContext3D()
+{
+ // Canvas3D layer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ [m_contentsLayer.get() setNeedsDisplay];
+ updateContentsRect();
+ }
+}
+#endif
+
void GraphicsLayerCA::updateContentsRect()
{
if (!m_contentsLayer)
@@ -1094,6 +1151,12 @@ void GraphicsLayerCA::updateGeometryOrientation()
#endif
}
+void GraphicsLayerCA::updateMaskLayer()
+{
+ CALayer* maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
+ [m_layer.get() setMask:maskCALayer];
+}
+
void GraphicsLayerCA::updateLayerAnimations()
{
if (m_transitionPropertiesToRemove.size()) {
@@ -1247,6 +1310,40 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, int ind
[layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation.
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* graphicsContext3D)
+{
+ PlatformGraphicsContext3D context = graphicsContext3D->platformGraphicsContext3D();
+ Platform3DObject texture = graphicsContext3D->platformTexture();
+
+ if (context == m_platformGraphicsContext3D && texture == m_platformTexture)
+ return;
+
+ m_platformGraphicsContext3D = context;
+ m_platformTexture = texture;
+
+ noteLayerPropertyChanged(ChildrenChanged);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+
+ if (m_platformGraphicsContext3D != NullPlatformGraphicsContext3D && m_platformTexture != NullPlatform3DObject) {
+ // create the inner 3d layer
+ m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:static_cast<CGLContextObj>(m_platformGraphicsContext3D) texture:static_cast<GLuint>(m_platformTexture)]);
+#ifndef NDEBUG
+ [m_contentsLayer.get() setName:@"3D Layer"];
+#endif
+ } else {
+ // remove the inner layer
+ m_contentsLayer = 0;
+ }
+
+ END_BLOCK_OBJC_EXCEPTIONS
+
+ noteLayerPropertyChanged(ContentsGraphicsContext3DChanged);
+ m_contentsLayerPurpose = m_contentsLayer ? ContentsLayerForGraphicsLayer3D : NoContentsLayer;
+}
+#endif
+
void GraphicsLayerCA::repaintLayerDirtyRects()
{
if (!m_dirtyRects.size())
@@ -1765,6 +1862,14 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
m_uncommittedChanges |= flags;
}
+#if ENABLE(3D_CANVAS)
+void GraphicsLayerCA::setGraphicsContext3DNeedsDisplay()
+{
+ if (m_contentsLayerPurpose == ContentsLayerForGraphicsLayer3D)
+ [m_contentsLayer.get() setNeedsDisplay];
+}
+#endif
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm
index a0d257b..672c3c8 100644
--- a/WebCore/platform/graphics/mac/ImageMac.mm
+++ b/WebCore/platform/graphics/mac/ImageMac.mm
@@ -94,16 +94,15 @@ CFDataRef BitmapImage::getTIFFRepresentation()
RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(0, 0));
// FIXME: Use type kCGImageTypeIdentifierTIFF constant once is becomes available in the API
- CGImageDestinationRef destination = CGImageDestinationCreateWithData(data.get(), CFSTR("public.tiff"), numValidFrames, 0);
-
+ RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), CFSTR("public.tiff"), numValidFrames, 0));
+
if (!destination)
return 0;
for (unsigned i = 0; i < numValidFrames; ++i)
- CGImageDestinationAddImage(destination, images[i], 0);
+ CGImageDestinationAddImage(destination.get(), images[i], 0);
- CGImageDestinationFinalize(destination);
- CFRelease(destination);
+ CGImageDestinationFinalize(destination.get());
m_tiffRep = data;
return m_tiffRep.get();
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 54eea00..0a63626 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -77,8 +77,12 @@ private:
static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
static bool isAvailable();
+ PlatformMedia platformMedia() const;
+
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
+ bool supportsFullscreen() const;
void load(const String& url);
void cancelLoad();
@@ -104,7 +108,7 @@ private:
MediaPlayer::NetworkState networkState() const { return m_networkState; }
MediaPlayer::ReadyState readyState() const { return m_readyState; }
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index c1d7fcb..30d0c82 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -39,6 +39,7 @@
#import "KURL.h"
#import "MIMETypeRegistry.h"
#import "SoftLinking.h"
+#import "TimeRanges.h"
#import "WebCoreSystemInterface.h"
#import <QTKit/QTKit.h>
#import <objc/objc-runtime.h>
@@ -84,6 +85,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieHasAudioAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
@@ -119,6 +121,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()
#define QTMovieDidEndNotification getQTMovieDidEndNotification()
#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()
+#define QTMovieHasAudioAttribute getQTMovieHasAudioAttribute()
#define QTMovieIsActiveAttribute getQTMovieIsActiveAttribute()
#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
@@ -230,7 +233,7 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
void MediaPlayerPrivate::createQTMovie(const String& url)
{
- NSURL *cocoaURL = KURL(url);
+ NSURL *cocoaURL = KURL(ParsedURLString, url);
NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
cocoaURL, QTMovieURLAttribute,
[NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute,
@@ -562,6 +565,12 @@ void MediaPlayerPrivate::load(const String& url)
[m_objcObserver.get() setDelayCallbacks:NO];
}
+PlatformMedia MediaPlayerPrivate::platformMedia() const
+{
+ PlatformMedia plaftformMedia = { m_qtMovie.get() };
+ return plaftformMedia;
+}
+
void MediaPlayerPrivate::play()
{
if (!metaDataAvailable())
@@ -719,18 +728,28 @@ bool MediaPlayerPrivate::hasVideo() const
return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue];
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ if (!m_qtMovie)
+ return false;
+ return [[m_qtMovie.get() attributeForKey:QTMovieHasAudioAttribute] boolValue];
+}
+
+bool MediaPlayerPrivate::supportsFullscreen() const
+{
+ return true;
+}
+
void MediaPlayerPrivate::setVolume(float volume)
{
- if (!metaDataAvailable())
- return;
- [m_qtMovie.get() setVolume:volume];
+ if (m_qtMovie)
+ [m_qtMovie.get() setVolume:volume];
}
void MediaPlayerPrivate::setRate(float rate)
{
- if (!metaDataAvailable())
- return;
- [m_qtMovie.get() setRate:rate];
+ if (m_qtMovie)
+ [m_qtMovie.get() setRate:rate];
}
void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch)
@@ -758,10 +777,13 @@ int MediaPlayerPrivate::dataRate() const
return wkQTMovieDataRate(m_qtMovie.get());
}
-
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
- return maxTimeLoaded();
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
+ if (loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index cdde7cf..97a7251 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -50,6 +50,8 @@
- (BOOL)_isFakeFixedPitch;
@end
+using namespace std;
+
namespace WebCore {
const float smallCapsFontSizeMultiplier = 0.7f;
@@ -269,7 +271,7 @@ void SimpleFontData::platformInit()
// and web pages that foolishly use this metric for width will be laid out
// poorly if we return an accurate height. Classic case is Times 13 point,
// which has an "x" that is 7x6 pixels.
- m_xHeight = MAX(NSMaxX(xBox), NSMaxY(xBox));
+ m_xHeight = max(NSMaxX(xBox), NSMaxY(xBox));
} else
m_xHeight = [m_platformData.font() xHeight];
}
@@ -443,13 +445,13 @@ CTFontRef SimpleFontData::getCTFont() const
return m_CTFont.get();
}
-CFDictionaryRef SimpleFontData::getCFStringAttributes() const
+CFDictionaryRef SimpleFontData::getCFStringAttributes(TextRenderingMode textMode) const
{
if (m_CFStringAttributes)
return m_CFStringAttributes.get();
- static const float kerningAdjustmentValue = 0;
- static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
+ bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+ bool allowLigatures = platformData().allowsLigatures() || allowKerning;
static const int ligaturesNotAllowedValue = 0;
static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue);
@@ -457,10 +459,23 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes() const
static const int ligaturesAllowedValue = 1;
static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue);
- static const void* attributeKeys[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
- const void* attributeValues[] = { getCTFont(), kerningAdjustment, platformData().allowsLigatures() ? ligaturesAllowed : ligaturesNotAllowed };
-
- m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, attributeKeys, attributeValues, sizeof(attributeKeys) / sizeof(*attributeKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ if (!allowKerning) {
+ static const float kerningAdjustmentValue = 0;
+ static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue);
+ static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName };
+ const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures
+ ? ligaturesAllowed : ligaturesNotAllowed };
+ m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled,
+ sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled),
+ &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ } else {
+ // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning.
+ static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName };
+ const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed };
+ m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled,
+ sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled),
+ &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ }
return m_CFStringAttributes.get();
}
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
index 895887f..b2e3d92 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -339,7 +340,10 @@ bool getEOTHeader(SharedBuffer* fontData, EOTHeader& eotHeader, size_t& overlayD
return true;
}
-HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
+// code shared by renameFont and renameAndActivateFont
+// adds fontName to the font table in fontData, and writes the new font table to rewrittenFontTable
+// returns the size of the name table (which is used by renameAndActivateFont), or 0 on early abort
+static size_t renameFontInternal(SharedBuffer* fontData, const String& fontName, Vector<char> &rewrittenFontData)
{
size_t originalDataSize = fontData->size();
const sfntHeader* sfnt = reinterpret_cast<const sfntHeader*>(fontData->data());
@@ -357,7 +361,7 @@ HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
// Rounded up to a multiple of 4 to simplify the checksum calculation.
size_t nameTableSize = ((offsetof(nameTable, nameRecords) + nameRecordCount * sizeof(nameRecord) + fontName.length() * sizeof(UChar)) & ~3) + 4;
- Vector<char> rewrittenFontData(fontData->size() + nameTableSize);
+ rewrittenFontData.resize(fontData->size() + nameTableSize);
char* data = rewrittenFontData.data();
memcpy(data, fontData->data(), originalDataSize);
@@ -394,8 +398,42 @@ HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
for (unsigned i = 0; i * sizeof(BigEndianULong) < nameTableSize; ++i)
rewrittenSfnt->tables[t].checkSum = rewrittenSfnt->tables[t].checkSum + reinterpret_cast<BigEndianULong*>(name)[i];
+ return nameTableSize;
+}
+
+#if PLATFORM(WINCE)
+// AddFontMemResourceEx does not exist on WinCE, so we must handle the font data manually
+// This function just renames the font and overwrites the old font data with the new
+bool renameFont(SharedBuffer* fontData, const String& fontName)
+{
+ // abort if the data is too small to be a font header with a "tables" entry
+ if (fontData->size() < offsetof(sfntHeader, tables))
+ return false;
+
+ // abort if the data is too small to hold all the tables specified in the header
+ const sfntHeader* header = reinterpret_cast<const sfntHeader*>(fontData->data());
+ if (fontData->size() < offsetof(sfntHeader, tables) + header->numTables * sizeof(TableDirectoryEntry))
+ return false;
+
+ Vector<char> rewrittenFontData;
+ if (!renameFontInternal(fontData, fontName, rewrittenFontData))
+ return false;
+
+ fontData->clear();
+ fontData->append(rewrittenFontData.data(), rewrittenFontData.size());
+ return true;
+}
+#else
+// Rename the font and install the new font data into the system
+HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
+{
+ Vector<char> rewrittenFontData;
+ size_t nameTableSize = renameFontInternal(fontData, fontName, rewrittenFontData);
+ if (!nameTableSize)
+ return 0;
+
DWORD numFonts = 0;
- HANDLE fontHandle = AddFontMemResourceEx(data, originalDataSize + nameTableSize, 0, &numFonts);
+ HANDLE fontHandle = AddFontMemResourceEx(rewrittenFontData.data(), fontData->size() + nameTableSize, 0, &numFonts);
if (fontHandle && numFonts != 1) {
RemoveFontMemResourceEx(fontHandle);
@@ -404,5 +442,6 @@ HANDLE renameAndActivateFont(SharedBuffer* fontData, const String& fontName)
return fontHandle;
}
+#endif
}
diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
index 13dad6f..4c75314 100644
--- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
+++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,6 +36,10 @@ struct BigEndianUShort;
struct EOTPrefix;
class SharedBuffer;
+#if PLATFORM(WINCE)
+typedef unsigned __int8 UInt8;
+#endif
+
struct EOTHeader {
EOTHeader();
diff --git a/WebCore/platform/graphics/qt/ColorQt.cpp b/WebCore/platform/graphics/qt/ColorQt.cpp
index 5d16740..151766a 100644
--- a/WebCore/platform/graphics/qt/ColorQt.cpp
+++ b/WebCore/platform/graphics/qt/ColorQt.cpp
@@ -40,7 +40,10 @@ Color::Color(const QColor& c)
Color::operator QColor() const
{
- return QColor(red(), green(), blue(), alpha());
+ if (m_valid)
+ return QColor(red(), green(), blue(), alpha());
+ else
+ return QColor();
}
}
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
index 5d29389..1113eae 100644
--- a/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -48,7 +48,7 @@ FontCache::FontCache()
{
}
-void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
+void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&)
{
}
@@ -58,8 +58,8 @@ class FontPlatformDataCacheKey {
public:
FontPlatformDataCacheKey(const FontDescription& description)
: m_familyName()
- , m_bold(false)
, m_size(description.computedPixelSize())
+ , m_bold(false)
, m_italic(description.italic())
, m_smallCaps(description.smallCaps())
, m_hash(0)
@@ -177,7 +177,7 @@ typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCac
// 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& family, bool checkingAlternateName)
+FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& description, const AtomicString&, bool)
{
if (!gFontPlatformDataCache)
gFontPlatformDataCache = new FontPlatformDataCache;
diff --git a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
index c29fd56..8e1e4f6 100644
--- a/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
+++ b/WebCore/platform/graphics/qt/FontFallbackListQt.cpp
@@ -130,7 +130,7 @@ const FontData* FontFallbackList::fontDataForCharacters(const WebCore::Font* fon
return primaryFontData(font);
}
-void FontFallbackList::setPlatformFont(const WebCore::FontPlatformData& platformData)
+void FontFallbackList::setPlatformFont(const WebCore::FontPlatformData&)
{
m_familyIndex = cAllFamiliesScanned;
}
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index e8eb923..c5960ac 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -197,7 +197,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
return w + run.padding();
}
-int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const
+int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const
{
const QString string = fixSpacing(qstring(run));
QTextLayout layout(string, font());
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index e259a4e..fa7b070 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -34,29 +34,29 @@
*/
#include "config.h"
+#include "GraphicsContext.h"
#ifdef Q_WS_WIN
#include <windows.h>
#endif
-#include "TransformationMatrix.h"
#include "Color.h"
#include "FloatConversion.h"
#include "Font.h"
-#include "GraphicsContext.h"
#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
+#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
#include "Pen.h"
-#include "NotImplemented.h"
+#include "TransformationMatrix.h"
#include <QBrush>
#include <QDebug>
#include <QGradient>
-#include <QPainter>
#include <QPaintDevice>
#include <QPaintEngine>
+#include <QPainter>
#include <QPainterPath>
#include <QPixmap>
#include <QPolygonF>
@@ -72,35 +72,35 @@ namespace WebCore {
static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op)
{
switch (op) {
- case CompositeClear:
- return QPainter::CompositionMode_Clear;
- case CompositeCopy:
- return QPainter::CompositionMode_Source;
- case CompositeSourceOver:
- return QPainter::CompositionMode_SourceOver;
- case CompositeSourceIn:
- return QPainter::CompositionMode_SourceIn;
- case CompositeSourceOut:
- return QPainter::CompositionMode_SourceOut;
- case CompositeSourceAtop:
- return QPainter::CompositionMode_SourceAtop;
- case CompositeDestinationOver:
- return QPainter::CompositionMode_DestinationOver;
- case CompositeDestinationIn:
- return QPainter::CompositionMode_DestinationIn;
- case CompositeDestinationOut:
- return QPainter::CompositionMode_DestinationOut;
- case CompositeDestinationAtop:
- return QPainter::CompositionMode_DestinationAtop;
- case CompositeXOR:
- return QPainter::CompositionMode_Xor;
- case CompositePlusDarker:
- // there is no exact match, but this is the closest
- return QPainter::CompositionMode_Darken;
- case CompositeHighlight:
- return QPainter::CompositionMode_SourceOver;
- case CompositePlusLighter:
- return QPainter::CompositionMode_Plus;
+ case CompositeClear:
+ return QPainter::CompositionMode_Clear;
+ case CompositeCopy:
+ return QPainter::CompositionMode_Source;
+ case CompositeSourceOver:
+ return QPainter::CompositionMode_SourceOver;
+ case CompositeSourceIn:
+ return QPainter::CompositionMode_SourceIn;
+ case CompositeSourceOut:
+ return QPainter::CompositionMode_SourceOut;
+ case CompositeSourceAtop:
+ return QPainter::CompositionMode_SourceAtop;
+ case CompositeDestinationOver:
+ return QPainter::CompositionMode_DestinationOver;
+ case CompositeDestinationIn:
+ return QPainter::CompositionMode_DestinationIn;
+ case CompositeDestinationOut:
+ return QPainter::CompositionMode_DestinationOut;
+ case CompositeDestinationAtop:
+ return QPainter::CompositionMode_DestinationAtop;
+ case CompositeXOR:
+ return QPainter::CompositionMode_Xor;
+ case CompositePlusDarker:
+ // there is no exact match, but this is the closest
+ return QPainter::CompositionMode_Darken;
+ case CompositeHighlight:
+ return QPainter::CompositionMode_SourceOver;
+ case CompositePlusLighter:
+ return QPainter::CompositionMode_Plus;
}
return QPainter::CompositionMode_SourceOver;
@@ -109,12 +109,12 @@ static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op
static inline Qt::PenCapStyle toQtLineCap(LineCap lc)
{
switch (lc) {
- case ButtCap:
- return Qt::FlatCap;
- case RoundCap:
- return Qt::RoundCap;
- case SquareCap:
- return Qt::SquareCap;
+ case ButtCap:
+ return Qt::FlatCap;
+ case RoundCap:
+ return Qt::RoundCap;
+ case SquareCap:
+ return Qt::SquareCap;
}
return Qt::FlatCap;
@@ -123,12 +123,12 @@ static inline Qt::PenCapStyle toQtLineCap(LineCap lc)
static inline Qt::PenJoinStyle toQtLineJoin(LineJoin lj)
{
switch (lj) {
- case MiterJoin:
- return Qt::SvgMiterJoin;
- case RoundJoin:
- return Qt::RoundJoin;
- case BevelJoin:
- return Qt::BevelJoin;
+ case MiterJoin:
+ return Qt::SvgMiterJoin;
+ case RoundJoin:
+ return Qt::RoundJoin;
+ case BevelJoin:
+ return Qt::BevelJoin;
}
return Qt::MiterJoin;
@@ -210,8 +210,8 @@ public:
return redirect;
return painter;
- } else
- return &layers.top()->painter;
+ }
+ return &layers.top()->painter;
}
bool antiAliasingForRectsAndLines;
@@ -411,46 +411,25 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ IntRect shadowRect = rect;
+ shadowRect.move(shadowSize.width(), shadowSize.height());
+ shadowRect.inflate(static_cast<int>(p->pen().widthF()));
+ p->fillRect(shadowRect, QColor(shadowColor));
+ }
+
p->drawRect(rect);
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
-// FIXME: Now that this is refactored, it should be shared by all contexts.
-static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth,
- const StrokeStyle& penStyle)
-{
- // For odd widths, we add in 0.5 to the appropriate x/y so that the float arithmetic
- // works out. For example, with a border width of 3, KHTML will pass us (y1+y2)/2, e.g.,
- // (50+53)/2 = 103/2 = 51 when we want 51.5. It is always true that an even width gave
- // us a perfect position, but an odd width gave us a position that is off by exactly 0.5.
- if (penStyle == DottedStroke || penStyle == DashedStroke) {
- if (p1.x() == p2.x()) {
- p1.setY(p1.y() + strokeWidth);
- p2.setY(p2.y() - strokeWidth);
- } else {
- p1.setX(p1.x() + strokeWidth);
- p2.setX(p2.x() - strokeWidth);
- }
- }
-
- if (((int) strokeWidth) % 2) {
- if (p1.x() == p2.x()) {
- // We're a vertical line. Adjust our x.
- p1.setX(p1.x() + 0.5);
- p2.setX(p2.x() + 0.5);
- } else {
- // We're a horizontal line. Adjust our y.
- p1.setY(p1.y() + 0.5);
- p2.setY(p2.y() + 0.5);
- }
- }
-}
-
// This is only used to draw borders.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
@@ -468,7 +447,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
FloatPoint p2 = point2;
bool isVerticalLine = (p1.x() == p2.x());
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
adjustLineToPixelBoundaries(p1, p2, width, style);
@@ -479,22 +458,22 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) {
p->save();
p->translate(shadowSize.width(), shadowSize.height());
- p->setPen(QColor(shadowColor));
+ p->setPen(shadowColor);
p->drawLine(p1, p2);
p->restore();
}
int patWidth = 0;
switch (style) {
- case NoStroke:
- case SolidStroke:
- break;
- case DottedStroke:
- patWidth = (int)width;
- break;
- case DashedStroke:
- patWidth = 3 * (int)width;
- break;
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = static_cast<int>(width);
+ break;
+ case DashedStroke:
+ patWidth = 3 * static_cast<int>(width);
+ break;
}
if (patWidth) {
@@ -523,7 +502,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -571,11 +550,25 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, true);
- p->drawArc(rect, startAngle * 16, angleSpan * 16);
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ startAngle *= 16;
+ angleSpan *= 16;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->save();
+ p->translate(shadowSize.width(), shadowSize.height());
+ QPen pen(p->pen());
+ pen.setColor(shadowColor);
+ p->setPen(pen);
+ p->drawArc(rect, startAngle, angleSpan);
+ p->restore();
+ }
+ p->drawArc(rect, startAngle, angleSpan);
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
@@ -593,9 +586,25 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
for (size_t i = 0; i < npoints; i++)
polygon[i] = points[i];
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
p->save();
p->setRenderHint(QPainter::Antialiasing, shouldAntialias);
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->save();
+ p->translate(shadowSize.width(), shadowSize.height());
+ if (p->brush().style() != Qt::NoBrush)
+ p->setBrush(QBrush(shadowColor));
+ QPen pen(p->pen());
+ if (pen.style() != Qt::NoPen) {
+ pen.setColor(shadowColor);
+ p->setPen(pen);
+ }
+ p->drawConvexPolygon(polygon);
+ p->restore();
+ }
p->drawConvexPolygon(polygon);
p->restore();
}
@@ -605,34 +614,50 @@ QPen GraphicsContext::pen()
if (paintingDisabled())
return QPen();
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
return p->pen();
}
+static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath *path)
+{
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->translate(shadowSize.width(), shadowSize.height());
+ p->fillPath(*path, QBrush(shadowColor));
+ p->translate(-shadowSize.width(), -shadowSize.height());
+ }
+}
+
void GraphicsContext::fillPath()
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPainterPath path = m_data->currentPath;
path.setFillRule(toQtFillRule(fillRule()));
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- if (fillColor().alpha())
- p->fillPath(path, p->brush());
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- break;
- }
- case GradientColorSpace:
- QBrush brush(*m_common->state.fillGradient->platformGradient());
- brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- p->fillPath(path, brush);
- break;
+ if ((m_common->state.fillColorSpace != SolidColorSpace)
+ || (fillColor().alpha())) {
+ drawFilledShadowPath(this, p, &path);
+ switch (m_common->state.fillColorSpace) {
+ case SolidColorSpace:
+ if (fillColor().alpha())
+ p->fillPath(path, p->brush());
+ break;
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
+ break;
+ }
+ case GradientColorSpace:
+ QBrush brush(*m_common->state.fillGradient->platformGradient());
+ brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
+ p->fillPath(path, brush);
+ break;
+ }
}
m_data->currentPath = QPainterPath();
}
@@ -642,59 +667,88 @@ void GraphicsContext::strokePath()
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QPen pen = p->pen();
+ QPainter* p = m_data->p();
+ QPen pen(p->pen());
QPainterPath path = m_data->currentPath;
path.setFillRule(toQtFillRule(fillRule()));
- switch (m_common->state.strokeColorSpace) {
- case SolidColorSpace:
- if (strokeColor().alpha())
+ if ((m_common->state.strokeColorSpace != SolidColorSpace)
+ || (strokeColor().alpha())) {
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ QTransform t(p->worldTransform());
+ p->translate(shadowSize.width(), shadowSize.height());
+ QPen shadowPen(pen);
+ shadowPen.setColor(shadowColor);
+ p->strokePath(path, shadowPen);
+ p->setWorldTransform(t);
+ }
+ switch (m_common->state.strokeColorSpace) {
+ case SolidColorSpace:
+ if (strokeColor().alpha())
+ p->strokePath(path, pen);
+ break;
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
+ p->setPen(pen);
p->strokePath(path, pen);
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
- p->setPen(pen);
- p->strokePath(path, pen);
- break;
- }
- case GradientColorSpace: {
- 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;
- }
+ break;
+ }
+ case GradientColorSpace: {
+ 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;
+ }
+ }
}
m_data->currentPath = QPainterPath();
}
+static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* p, const FloatRect& rect)
+{
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
+ FloatRect shadowRect(rect);
+ shadowRect.move(shadowSize.width(), shadowSize.height());
+ p->fillRect(shadowRect, QColor(shadowColor));
+ }
+}
+
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
- switch (m_common->state.fillColorSpace) {
- case SolidColorSpace:
- if (fillColor().alpha())
- p->fillRect(rect, p->brush());
- break;
- case PatternColorSpace: {
- TransformationMatrix affine;
- p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- break;
- }
- case GradientColorSpace:
- QBrush brush(*m_common->state.fillGradient->platformGradient());
- brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- p->fillRect(rect, brush);
- break;
+ if ((m_common->state.fillColorSpace != SolidColorSpace)
+ || (fillColor().alpha())) {
+ drawBorderlessRectShadow(this, p, rect);
+ switch (m_common->state.fillColorSpace) {
+ case SolidColorSpace:
+ if (fillColor().alpha())
+ p->fillRect(rect, p->brush());
+ break;
+ case PatternColorSpace: {
+ TransformationMatrix affine;
+ p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
+ break;
+ }
+ case GradientColorSpace:
+ QBrush brush(*m_common->state.fillGradient->platformGradient());
+ brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
+ p->fillRect(rect, brush);
+ break;
+ }
}
- m_data->currentPath = QPainterPath();
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
@@ -702,8 +756,10 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
if (paintingDisabled())
return;
- m_data->solidColor.setColor(QColor(c));
- m_data->p()->fillRect(rect, m_data->solidColor);
+ m_data->solidColor.setColor(c);
+ QPainter* p = m_data->p();
+ drawBorderlessRectShadow(this, p, rect);
+ 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)
@@ -712,7 +768,9 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
return;
Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight);
- m_data->p()->fillPath(*path.platformPath(), QColor(color));
+ QPainter* p = m_data->p();
+ drawFilledShadowPath(this, p, path.platformPath());
+ p->fillPath(*path.platformPath(), QColor(color));
}
void GraphicsContext::beginPath()
@@ -750,7 +808,7 @@ void GraphicsContext::clipPath(WindRule clipRule)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPainterPath newPath = m_data->currentPath;
newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
p->setClipPath(newPath);
@@ -769,10 +827,10 @@ void GraphicsContext::drawFocusRing(const Color& color)
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
- if (rects.size() == 0)
+ if (!rects.size())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
@@ -793,7 +851,7 @@ void GraphicsContext::drawFocusRing(const Color& color)
QPainterPath newPath = stroker.createStroke(path);
p->strokePath(newPath, nPen);
#else
- for (int i = 0; i < rectCount; ++i)
+ for (unsigned i = 0; i < rectCount; ++i)
p->drawRect(QRectF(rects[i]));
#endif
p->setPen(oldPen);
@@ -802,7 +860,7 @@ void GraphicsContext::drawFocusRing(const Color& color)
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
-void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
+void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool)
{
if (paintingDisabled())
return;
@@ -811,8 +869,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr
drawLine(origin, endPoint);
}
-void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&,
- int width, bool grammar)
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int, bool)
{
if (paintingDisabled())
return;
@@ -829,10 +886,16 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
return FloatRect(QRectF(result));
}
-void GraphicsContext::setPlatformShadow(const IntSize& pos, int blur, const Color &color)
+void GraphicsContext::setPlatformShadow(const IntSize& size, int, const Color&)
{
// Qt 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::clearPlatformShadow()
@@ -848,8 +911,8 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
int x, y, w, h;
x = y = 0;
- QPainter *p = m_data->p();
- const QPaintDevice *device = p->device();
+ QPainter* p = m_data->p();
+ const QPaintDevice* device = p->device();
w = device->width();
h = device->height();
@@ -871,10 +934,10 @@ void GraphicsContext::endTransparencyLayer()
if (paintingDisabled())
return;
- TransparencyLayer *layer = m_data->layers.pop();
+ TransparencyLayer* layer = m_data->layers.pop();
layer->painter.end();
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
p->save();
p->resetTransform();
p->setOpacity(layer->opacity);
@@ -889,7 +952,7 @@ void GraphicsContext::clearRect(const FloatRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPainter::CompositionMode currentCompositionMode = p->compositionMode();
if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
p->setCompositionMode(QPainter::CompositionMode_Source);
@@ -916,7 +979,7 @@ void GraphicsContext::setLineCap(LineCap lc)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen nPen = p->pen();
nPen.setCapStyle(toQtLineCap(lc));
p->setPen(nPen);
@@ -948,7 +1011,7 @@ void GraphicsContext::setLineJoin(LineJoin lj)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen nPen = p->pen();
nPen.setJoinStyle(toQtLineJoin(lj));
p->setPen(nPen);
@@ -959,7 +1022,7 @@ void GraphicsContext::setMiterLimit(float limit)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen nPen = p->pen();
nPen.setMiterLimit(limit);
p->setPen(nPen);
@@ -969,7 +1032,7 @@ void GraphicsContext::setAlpha(float opacity)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
p->setOpacity(opacity);
}
@@ -995,15 +1058,19 @@ void GraphicsContext::clipOut(const Path& path)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QRectF clipBounds = p->clipPath().boundingRect();
+ QPainter* p = m_data->p();
QPainterPath clippedOut = *path.platformPath();
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
- newClip.addRect(clipBounds);
- newClip.addPath(clippedOut);
-
- p->setClipPath(newClip, Qt::IntersectClip);
+ if (p->hasClipping()) {
+ newClip.addRect(p->clipPath().boundingRect());
+ newClip.addPath(clippedOut);
+ p->setClipPath(newClip, Qt::IntersectClip);
+ } else {
+ newClip.addRect(p->window());
+ newClip.addPath(clippedOut & newClip);
+ p->setClipPath(newClip);
+ }
}
void GraphicsContext::translate(float x, float y)
@@ -1061,14 +1128,21 @@ void GraphicsContext::clipOut(const IntRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QRectF clipBounds = p->clipPath().boundingRect();
+ QPainter* p = m_data->p();
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
- newClip.addRect(clipBounds);
- newClip.addRect(QRect(rect));
-
- p->setClipPath(newClip, Qt::IntersectClip);
+ if (p->hasClipping()) {
+ newClip.addRect(p->clipPath().boundingRect());
+ newClip.addRect(QRect(rect));
+ p->setClipPath(newClip, Qt::IntersectClip);
+ } else {
+ QRect clipOutRect(rect);
+ QRect window(p->window());
+ clipOutRect &= window;
+ newClip.addRect(window);
+ newClip.addRect(clipOutRect);
+ p->setClipPath(newClip);
+ }
}
void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
@@ -1076,14 +1150,21 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
- QRectF clipBounds = p->clipPath().boundingRect();
+ QPainter* p = m_data->p();
QPainterPath newClip;
newClip.setFillRule(Qt::OddEvenFill);
- newClip.addRect(clipBounds);
- newClip.addEllipse(QRect(rect));
-
- p->setClipPath(newClip, Qt::IntersectClip);
+ if (p->hasClipping()) {
+ newClip.addRect(p->clipPath().boundingRect());
+ newClip.addEllipse(QRect(rect));
+ p->setClipPath(newClip, Qt::IntersectClip);
+ } else {
+ QRect clipOutRect(rect);
+ QRect window(p->window());
+ clipOutRect &= window;
+ newClip.addRect(window);
+ newClip.addEllipse(clipOutRect);
+ p->setClipPath(newClip);
+ }
}
void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
@@ -1109,7 +1190,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
path.setFillRule(Qt::OddEvenFill);
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, true);
@@ -1134,7 +1215,7 @@ void GraphicsContext::concatCTM(const TransformationMatrix& transform)
}
}
-void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
{
notImplemented();
}
@@ -1143,7 +1224,7 @@ void GraphicsContext::setPlatformStrokeColor(const Color& color)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen newPen(p->pen());
newPen.setColor(color);
p->setPen(newPen);
@@ -1153,7 +1234,7 @@ void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen newPen(p->pen());
newPen.setStyle(toQPenStyle(strokeStyle));
p->setPen(newPen);
@@ -1163,7 +1244,7 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness)
{
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
+ QPainter* p = m_data->p();
QPen newPen(p->pen());
newPen.setWidthF(thickness);
p->setPen(newPen);
@@ -1184,7 +1265,6 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
}
#ifdef Q_WS_WIN
-#include <windows.h>
HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
{
diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp
index 34c3c47..98f4606 100644
--- a/WebCore/platform/graphics/qt/IconQt.cpp
+++ b/WebCore/platform/graphics/qt/IconQt.cpp
@@ -47,7 +47,7 @@ PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
return i.release();
}
-PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
{
//FIXME: Implement this
return 0;
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 22a5a43..5255428 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -68,7 +68,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace, bool& success)
: m_data(size)
, m_size(size)
{
@@ -125,12 +125,13 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
m_data.m_painter->begin(&m_data.m_pixmap);
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
{
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
unsigned char* data = result->data()->data()->data();
- if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originx = rect.x();
@@ -140,8 +141,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -151,11 +152,16 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage image = imageData.m_pixmap.toImage();
+ if (multiplied == Unmultiplied)
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ else
+ image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
ASSERT(!image.isNull());
unsigned destBytesPerRow = 4 * rect.width();
@@ -176,7 +182,18 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -184,49 +201,65 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= size.width());
int numColumns = endx - destx;
int originy = sourceRect.y();
int desty = destPoint.y() + sourceRect.y();
ASSERT(desty >= 0);
- ASSERT(desty < m_size.height());
+ ASSERT(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- bool isPainting = m_data.m_painter->isActive();
+ bool isPainting = data.m_painter->isActive();
if (isPainting)
- m_data.m_painter->end();
+ data.m_painter->end();
- QImage image = m_data.m_pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage image = data.m_pixmap.toImage();
+ if (multiplied == Unmultiplied)
+ image = image.convertToFormat(QImage::Format_ARGB32);
+ else
+ image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
for (int y = 0; y < numRows; ++y) {
quint32* scanLine = reinterpret_cast<quint32*>(image.scanLine(y + desty));
for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- scanLine[x + destx] = reinterpret_cast<quint32*>(srcRows + basex)[0];
+ // ImageData stores the pixels in RGBA while QImage is ARGB
+ quint32 pixel = reinterpret_cast<quint32*>(srcRows + 4 * x)[0];
+ pixel = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00);
+ scanLine[x + destx] = pixel;
}
srcRows += srcBytesPerRow;
}
- m_data.m_pixmap = QPixmap::fromImage(image);
+ data.m_pixmap = QPixmap::fromImage(image);
if (isPainting)
- m_data.m_painter->begin(&m_data.m_pixmap);
+ data.m_painter->begin(&data.m_pixmap);
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
}
// We get a mimeType here but QImageWriter does not support mimetypes but
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 7bbdcc0..3a27fe3 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -35,150 +35,9 @@
#include <QtGui/QImageReader>
#include <qdebug.h>
-namespace {
- const QImage::Format DesiredFormat = QImage::Format_ARGB32;
- const bool debugImageDecoderQt = false;
-}
-
namespace WebCore {
-ImageDecoderQt::ImageData::ImageData(const QImage& image, ImageState imageState, int duration) :
- m_image(image), m_imageState(imageState), m_duration(duration)
-{
-}
-
-// Context, maintains IODevice on a data buffer.
-class ImageDecoderQt::ReadContext {
-public:
-
- enum LoadMode {
- // Load images incrementally. This is still experimental and
- // will cause the image plugins to report errors.
- // Also note that as of Qt 4.2.2, the JPEG loader does not return error codes
- // on "preliminary end of data".
- LoadIncrementally,
- // Load images only if all data have been received
- LoadComplete };
-
- ReadContext(const IncomingData & data, LoadMode loadMode, ImageList &target);
-
- enum ReadResult { ReadEOF, ReadFailed, ReadPartial, ReadComplete };
-
- // Append data and read out all images. Returns the result
- // of the last read operation, so, even if ReadPartial is returned,
- // a few images might have been read.
- ReadResult read(bool allDataReceived);
-
- QImageReader *reader() { return &m_reader; }
-private:
- enum IncrementalReadResult { IncrementalReadFailed, IncrementalReadPartial, IncrementalReadComplete };
- // Incrementally read an image
- IncrementalReadResult readImageLines(ImageData &);
-
- const LoadMode m_loadMode;
-
- QByteArray m_data;
- QBuffer m_buffer;
- QImageReader m_reader;
-
- ImageList &m_target;
-
- // Detected data format of the stream
- enum QImage::Format m_dataFormat;
- QSize m_size;
-
-};
-
-ImageDecoderQt::ReadContext::ReadContext(const IncomingData & data, LoadMode loadMode, ImageList &target)
- : m_loadMode(loadMode)
- , m_data(data.data(), data.size())
- , m_buffer(&m_data)
- , m_reader(&m_buffer)
- , m_target(target)
- , m_dataFormat(QImage::Format_Invalid)
-{
- m_buffer.open(QIODevice::ReadOnly);
-}
-
-
-ImageDecoderQt::ReadContext::ReadResult
- ImageDecoderQt::ReadContext::read(bool allDataReceived)
-{
- // Complete mode: Read only all all data received
- if (m_loadMode == LoadComplete && !allDataReceived)
- return ReadPartial;
-
- // Attempt to read out all images
- while (true) {
- if (m_target.empty() || m_target.back().m_imageState == ImageComplete) {
- // Start a new image.
- if (!m_reader.canRead())
- return ReadEOF;
-
- // Attempt to construct an empty image of the matching size and format
- // for efficient reading
- QImage newImage = m_dataFormat != QImage::Format_Invalid ?
- QImage(m_size, m_dataFormat) : QImage();
- m_target.push_back(ImageData(newImage));
- }
-
- // read chunks
- switch (readImageLines(m_target.back())) {
- case IncrementalReadFailed:
- m_target.pop_back();
- return ReadFailed;
- case IncrementalReadPartial:
- return ReadPartial;
- case IncrementalReadComplete:
- m_target.back().m_imageState = ImageComplete;
- //store for next
- m_dataFormat = m_target.back().m_image.format();
- m_size = m_target.back().m_image.size();
- const bool supportsAnimation = m_reader.supportsAnimation();
-
- if (debugImageDecoderQt)
- qDebug() << "readImage(): #" << m_target.size() << " complete, " << m_size
- << " format " << m_dataFormat << " supportsAnimation=" << supportsAnimation;
- // No point in readinfg further
- if (!supportsAnimation)
- return ReadComplete;
-
- break;
- }
- }
- return ReadComplete;
-}
-
-
-
-ImageDecoderQt::ReadContext::IncrementalReadResult
- ImageDecoderQt::ReadContext::readImageLines(ImageData &imageData)
-{
- // TODO: Implement incremental reading here,
- // set state to reflect complete header, etc.
- // For now, we read the whole image.
-
- const qint64 startPos = m_buffer.pos();
- // Oops, failed. Rewind.
- if (!m_reader.read(&imageData.m_image)) {
- m_buffer.seek(startPos);
- const bool gotHeader = imageData.m_image.size().width();
-
- if (debugImageDecoderQt)
- qDebug() << "readImageLines(): read() failed: " << m_reader.errorString()
- << " got header=" << gotHeader;
- // [Experimental] Did we manage to read the header?
- if (gotHeader) {
- imageData.m_imageState = ImageHeaderValid;
- return IncrementalReadPartial;
- }
- return IncrementalReadFailed;
- }
- imageData.m_duration = m_reader.nextImageDelay();
- return IncrementalReadComplete;
-}
-
-ImageDecoderQt* ImageDecoderQt::create(const SharedBuffer& data)
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
{
// We need at least 4 bytes to figure out what kind of image we're dealing with.
if (data.size() < 4)
@@ -189,149 +48,196 @@ ImageDecoderQt* ImageDecoderQt::create(const SharedBuffer& data)
if (!buffer.open(QBuffer::ReadOnly))
return 0;
- QString imageFormat = QString::fromLatin1(QImageReader::imageFormat(&buffer).toLower());
+ QByteArray imageFormat = QImageReader::imageFormat(&buffer);
if (imageFormat.isEmpty())
return 0; // Image format not supported
return new ImageDecoderQt(imageFormat);
}
-ImageDecoderQt::ImageDecoderQt(const QString &imageFormat)
- : m_hasAlphaChannel(false)
- , m_imageFormat(imageFormat)
+ImageDecoderQt::ImageDecoderQt(const QByteArray& imageFormat)
+ : m_buffer(0)
+ , m_reader(0)
+ , m_repetitionCount(-1)
{
}
ImageDecoderQt::~ImageDecoderQt()
{
+ delete m_reader;
+ delete m_buffer;
}
-bool ImageDecoderQt::hasFirstImageHeader() const
+void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
{
- return !m_imageList.empty() && m_imageList[0].m_imageState >= ImageHeaderValid;
-}
+ if (m_failed)
+ return;
-void ImageDecoderQt::reset()
-{
- m_hasAlphaChannel = false;
- m_failed = false;
- m_imageList.clear();
- m_pixmapCache.clear();
- m_loopCount = cAnimationNone;
-}
+ // Cache our own new data.
+ ImageDecoder::setData(data, allDataReceived);
-void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived)
-{
- reset();
- ReadContext readContext(data, ReadContext::LoadComplete, m_imageList);
-
- if (debugImageDecoderQt)
- qDebug() << " setData " << data.size() << " image bytes, complete=" << allDataReceived;
-
- const ReadContext::ReadResult readResult = readContext.read(allDataReceived);
-
- if (hasFirstImageHeader())
- m_hasAlphaChannel = m_imageList[0].m_image.hasAlphaChannel();
-
- if (debugImageDecoderQt)
- qDebug() << " read returns " << readResult;
-
- switch (readResult) {
- case ReadContext::ReadFailed:
- m_failed = true;
- break;
- case ReadContext::ReadEOF:
- case ReadContext::ReadPartial:
- case ReadContext::ReadComplete:
- // Did we read anything - try to set the size.
- if (hasFirstImageHeader()) {
- QSize imgSize = m_imageList[0].m_image.size();
- setSize(imgSize.width(), imgSize.height());
-
- if (readContext.reader()->supportsAnimation()) {
- if (readContext.reader()->loopCount() != -1)
- m_loopCount = readContext.reader()->loopCount();
- else
- m_loopCount = 0; //loop forever
- }
- }
- break;
- }
-}
+ // No progressive loading possible
+ if (!allDataReceived)
+ return;
+
+ // We expect to be only called once with allDataReceived
+ ASSERT(!m_buffer);
+ ASSERT(!m_reader);
+ // Attempt to load the data
+ QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size());
+ m_buffer = new QBuffer;
+ m_buffer->setData(imageData);
+ m_buffer->open(QBuffer::ReadOnly);
+ m_reader = new QImageReader(m_buffer);
+
+ if (!m_reader->canRead())
+ failRead();
+}
bool ImageDecoderQt::isSizeAvailable()
{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::isSizeAvailable() returns" << ImageDecoder::isSizeAvailable();
+ if (!m_failed && !ImageDecoder::isSizeAvailable() && m_reader)
+ internalDecodeSize();
+
return ImageDecoder::isSizeAvailable();
}
-size_t ImageDecoderQt::frameCount() const
+size_t ImageDecoderQt::frameCount()
{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::frameCount() returns" << m_imageList.size();
- return m_imageList.size();
+ if (m_frameBufferCache.isEmpty() && m_reader) {
+ if (m_reader->supportsAnimation()) {
+ int imageCount = m_reader->imageCount();
+
+ // Fixup for Qt decoders... imageCount() is wrong
+ // and jumpToNextImage does not work either... so
+ // we will have to parse everything...
+ if (imageCount == 0)
+ forceLoadEverything();
+ else
+ m_frameBufferCache.resize(imageCount);
+ } else {
+ m_frameBufferCache.resize(1);
+ }
+ }
+
+ return m_frameBufferCache.size();
}
int ImageDecoderQt::repetitionCount() const
{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::repetitionCount() returns" << m_loopCount;
- return m_loopCount;
+ if (m_reader && m_reader->supportsAnimation())
+ m_repetitionCount = qMax(0, m_reader->loopCount());
+
+ return m_repetitionCount;
}
-bool ImageDecoderQt::supportsAlpha() const
+String ImageDecoderQt::filenameExtension() const
{
- return m_hasAlphaChannel;
-}
+ return m_format;
+};
-int ImageDecoderQt::duration(size_t index) const
+RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
{
- if (index >= m_imageList.size())
+ // this information might not have been set
+ int count = m_frameBufferCache.size();
+ if (count == 0) {
+ internalDecodeSize();
+ count = frameCount();
+ }
+
+ if (index >= static_cast<size_t>(count))
return 0;
- return m_imageList[index].m_duration;
+
+ RGBA32Buffer& frame = m_frameBufferCache[index];
+ if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+ internalReadImage(index);
+ return &frame;
}
-String ImageDecoderQt::filenameExtension() const
+void ImageDecoderQt::clearFrameBufferCache(size_t index)
{
- if (debugImageDecoderQt)
- qDebug() << " ImageDecoderQt::filenameExtension() returns" << m_imageFormat;
- return m_imageFormat;
-};
+ // 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;
-RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
+ for (size_t i = 0; i < index; ++index)
+ m_frameBufferCache[index].clear();
+}
+
+void ImageDecoderQt::internalDecodeSize()
{
- Q_ASSERT("use imageAtIndex instead");
- return 0;
+ ASSERT(m_reader);
+
+ QSize size = m_reader->size();
+ setSize(size.width(), size.height());
}
-QPixmap* ImageDecoderQt::imageAtIndex(size_t index) const
+void ImageDecoderQt::internalReadImage(size_t frameIndex)
{
- if (debugImageDecoderQt)
- qDebug() << "ImageDecoderQt::imageAtIndex(" << index << ')';
+ ASSERT(m_reader);
- if (index >= m_imageList.size())
- return 0;
+ if (m_reader->supportsAnimation())
+ m_reader->jumpToImage(frameIndex);
+ else if (frameIndex != 0)
+ return failRead();
- if (!m_pixmapCache.contains(index)) {
- m_pixmapCache.insert(index,
- QPixmap::fromImage(m_imageList[index].m_image));
+ internalHandleCurrentImage(frameIndex);
- // store null image since the converted pixmap is already in pixmap cache
- Q_ASSERT(m_imageList[index].m_imageState == ImageComplete);
- m_imageList[index].m_image = QImage();
- }
- return &m_pixmapCache[index];
+ // Attempt to return some memory
+ for (int i = 0; i < m_frameBufferCache.size(); ++i)
+ if (m_frameBufferCache[i].status() != RGBA32Buffer::FrameComplete)
+ return;
+
+ delete m_reader;
+ delete m_buffer;
+ m_buffer = 0;
+ m_reader = 0;
}
-void ImageDecoderQt::clearFrame(size_t index)
+void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
{
- if (m_imageList.size() < (int)index)
- m_imageList[index].m_image = QImage();
- m_pixmapCache.take(index);
+ // Now get the QImage from Qt and place it in the RGBA32Buffer
+ QImage img;
+ if (!m_reader->read(&img))
+ return failRead();
+
+ // now into the RGBA32Buffer - even if the image is not
+ QSize imageSize = img.size();
+ RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
+ buffer->setRect(m_reader->currentImageRect());
+ buffer->setStatus(RGBA32Buffer::FrameComplete);
+ buffer->setDuration(m_reader->nextImageDelay());
+ buffer->setDecodedImage(img);
}
+// We will parse everything and we have no idea how
+// many images we have... We will have to find out the
+// hard way.
+void ImageDecoderQt::forceLoadEverything()
+{
+ int imageCount = 0;
+
+ do {
+ m_frameBufferCache.resize(++imageCount);
+ internalHandleCurrentImage(imageCount - 1);
+ } while(!m_failed);
+
+ // reset the failed state and resize the vector...
+ m_frameBufferCache.resize(imageCount - 1);
+ m_failed = false;
+}
+
+void ImageDecoderQt::failRead()
+{
+ setFailed();
+ delete m_reader;
+ delete m_buffer;
+ m_reader = 0;
+ m_buffer = 0;
+}
}
// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index fc52479..7b3b686 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -28,10 +28,11 @@
#define ImageDecoderQt_h
#include "ImageDecoder.h"
-#include <QtGui/QImage>
+#include <QtGui/QImageReader>
#include <QtGui/QPixmap>
#include <QtCore/QList>
#include <QtCore/QHash>
+#include <QtCore/QBuffer>
namespace WebCore {
@@ -39,54 +40,35 @@ namespace WebCore {
class ImageDecoderQt : public ImageDecoder
{
public:
- static ImageDecoderQt* create(const SharedBuffer& data);
+ ImageDecoderQt(const QByteArray& imageFormat);
~ImageDecoderQt();
- typedef Vector<char> IncomingData;
-
- virtual void setData(const IncomingData& data, bool allDataReceived);
+ virtual void setData(SharedBuffer* data, bool allDataReceived);
virtual bool isSizeAvailable();
- virtual size_t frameCount() const;
+ virtual size_t frameCount();
virtual int repetitionCount() const;
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
- QPixmap* imageAtIndex(size_t index) const;
- virtual bool supportsAlpha() const;
- int duration(size_t index) const;
virtual String filenameExtension() const;
- void clearFrame(size_t index);
+ virtual void clearFrameBufferCache(size_t clearBeforeFrame);
private:
- ImageDecoderQt(const QString &imageFormat);
ImageDecoderQt(const ImageDecoderQt&);
ImageDecoderQt &operator=(const ImageDecoderQt&);
- class ReadContext;
- void reset();
- bool hasFirstImageHeader() const;
-
- enum ImageState {
- // Started image reading
- ImagePartial,
- // Header (size / alpha) are known
- ImageHeaderValid,
- // Image is complete
- ImageComplete };
-
- struct ImageData {
- ImageData(const QImage& image, ImageState imageState = ImagePartial, int duration=0);
- QImage m_image;
- ImageState m_imageState;
- int m_duration;
- };
-
- bool m_hasAlphaChannel;
- typedef QList<ImageData> ImageList;
- mutable ImageList m_imageList;
- mutable QHash<int, QPixmap> m_pixmapCache;
- int m_loopCount;
- QString m_imageFormat;
+private:
+ void internalDecodeSize();
+ void internalReadImage(size_t);
+ void internalHandleCurrentImage(size_t);
+ void forceLoadEverything();
+ void failRead();
+
+private:
+ String m_format;
+ QBuffer* m_buffer;
+ QImageReader* m_reader;
+ mutable int m_repetitionCount;
};
diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp
index 5d40e26..da6ddac 100644
--- a/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -76,6 +76,7 @@ bool FrameData::clear(bool clearMetadata)
m_haveMetadata = false;
if (m_frame) {
+ delete m_frame;
m_frame = 0;
return true;
}
diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
deleted file mode 100644
index 8ae449c..0000000
--- a/WebCore/platform/graphics/qt/ImageSourceQt.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- *
- * 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 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.
- */
-
-#include "config.h"
-#include "ImageSource.h"
-#include "ImageDecoderQt.h"
-#include "SharedBuffer.h"
-
-#include <QBuffer>
-#include <QImage>
-#include <QImageReader>
-
-namespace WebCore {
-
-ImageSource::ImageSource()
- : m_decoder(0)
-{
-}
-
-ImageSource::~ImageSource()
-{
- clear(true);
-}
-
-bool ImageSource::initialized() const
-{
- return m_decoder;
-}
-
-void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
-{
- // Make the decoder by sniffing the bytes.
- // This method will examine the data and instantiate an instance of the appropriate decoder plugin.
- // If insufficient bytes are available to determine the image type, no decoder plugin will be
- // made.
- if (!m_decoder)
- m_decoder = ImageDecoderQt::create(*data);
-
- if (!m_decoder)
- return;
-
- m_decoder->setData(data->buffer(), allDataReceived);
-}
-
-String ImageSource::filenameExtension() const
-{
- if (!m_decoder)
- return String();
-
- return m_decoder->filenameExtension();
-}
-
-bool ImageSource::isSizeAvailable()
-{
- if (!m_decoder)
- return false;
-
- return m_decoder->isSizeAvailable();
-}
-
-IntSize ImageSource::size() const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->size();
-}
-
-IntSize ImageSource::frameSizeAtIndex(size_t index) const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
-}
-
-int ImageSource::repetitionCount()
-{
- if (!m_decoder)
- return cAnimationNone;
-
- return m_decoder->repetitionCount();
-}
-
-size_t ImageSource::frameCount() const
-{
- if (!m_decoder)
- return 0;
-
- return m_decoder->frameCount();
-}
-
-NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- return m_decoder->imageAtIndex(index);
-}
-
-float ImageSource::frameDurationAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- // Many annoying ads specify a 0 duration to make an image flash as quickly
- // as possible. We follow WinIE's behavior and use a duration of 100 ms
- // for any frames that specify a duration of <= 50 ms. See
- // <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for
- // more.
- const float duration = m_decoder->duration(index) / 1000.0f;
- return (duration < 0.051f) ? 0.100f : duration;
-}
-
-bool ImageSource::frameHasAlphaAtIndex(size_t index)
-{
- if (!m_decoder || !m_decoder->supportsAlpha())
- return false;
-
- const QPixmap* source = m_decoder->imageAtIndex(index);
- if (!source)
- return false;
-
- return source->hasAlphaChannel();
-}
-
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
-{
- return (m_decoder && m_decoder->imageAtIndex(index));
-}
-
-void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
-{
- if (!destroyAll) {
- if (m_decoder)
- m_decoder->clearFrameBufferCache(clearBeforeFrame);
- return;
- }
-
- delete m_decoder;
- m_decoder = 0;
- if (data)
- setData(data, allDataReceived);
-}
-
-}
-
-// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index 76b1494..7078d16 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -27,6 +27,7 @@
#include "FrameView.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
+#include "TimeRanges.h"
#include "Widget.h"
#include <wtf/HashSet.h>
@@ -37,9 +38,9 @@
#include <QUrl>
#include <QEvent>
-#include <Phonon/AudioOutput>
-#include <Phonon/MediaObject>
-#include <Phonon/VideoWidget>
+#include <audiooutput.h>
+#include <mediaobject.h>
+#include <videowidget.h>
using namespace Phonon;
@@ -146,7 +147,7 @@ void MediaPlayerPrivate::getSupportedTypes(HashSet<String>&)
notImplemented();
}
-MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
+MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String&, const String&)
{
// FIXME: do the real thing
notImplemented();
@@ -160,6 +161,14 @@ bool MediaPlayerPrivate::hasVideo() const
return hasVideo;
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ // FIXME: Phonon::MediaObject does not have such a hasAudio() function
+ bool hasAudio = true;
+ LOG(Media, "MediaPlayerPrivatePhonon::hasAudio() -> %s", hasAudio ? "true" : "false");
+ return hasAudio;
+}
+
void MediaPlayerPrivate::load(const String& url)
{
LOG(Media, "MediaPlayerPrivatePhonon::load(\"%s\")", url.utf8().data());
@@ -247,15 +256,15 @@ float MediaPlayerPrivate::currentTime() const
return currentTime;
}
-void MediaPlayerPrivate::setEndTime(float endTime)
+void MediaPlayerPrivate::setEndTime(float)
{
notImplemented();
}
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
notImplemented();
- return 0.0f;
+ return TimeRanges::create();
}
float MediaPlayerPrivate::maxTimeSeekable() const
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
index 9572d61..e1193b6 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h
@@ -80,6 +80,7 @@ namespace WebCore {
IntSize naturalSize() const;
bool hasVideo() const;
+ bool hasAudio() const;
void load(const String &url);
void cancelLoad();
@@ -104,7 +105,7 @@ namespace WebCore {
MediaPlayer::NetworkState networkState() const;
MediaPlayer::ReadyState readyState() const;
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
diff --git a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index f823f84..f093d7d 100644
--- a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -33,7 +33,7 @@ void SimpleFontData::determinePitch()
m_treatAsFixedPitch = m_platformData.font().fixedPitch();
}
-bool SimpleFontData::containsCharacters(const UChar*, int length) const
+bool SimpleFontData::containsCharacters(const UChar*, int) const
{
return true;
}
diff --git a/WebCore/platform/graphics/qt/StillImageQt.h b/WebCore/platform/graphics/qt/StillImageQt.h
index 2b2c1f7..6c417b1 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.h
+++ b/WebCore/platform/graphics/qt/StillImageQt.h
@@ -41,7 +41,7 @@ namespace WebCore {
// FIXME: StillImages are underreporting decoded sizes and will be unable
// to prune because these functions are not implemented yet.
- virtual void destroyDecodedData(bool destroyAll = true) { }
+ virtual void destroyDecodedData(bool destroyAll = true) { Q_UNUSED(destroyAll); }
virtual unsigned decodedSize() const { return 0; }
virtual IntSize size() const;
diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp
index 3bdddb2..268b17e 100644
--- a/WebCore/platform/graphics/skia/GradientSkia.cpp
+++ b/WebCore/platform/graphics/skia/GradientSkia.cpp
@@ -152,19 +152,21 @@ SkShader* Gradient::platformGradient()
}
if (m_radial) {
- // FIXME: CSS radial Gradients allow an offset focal point (the
- // "start circle"), but skia doesn't seem to support that, so this just
- // ignores m_p0/m_r0 and draws the gradient centered in the "end
- // circle" (m_p1/m_r1).
- // See http://webkit.org/blog/175/introducing-css-gradients/ for a
- // description of the expected behavior.
-
- // The radius we give to Skia must be positive (and non-zero). If
- // we're given a zero radius, just ask for a very small radius so
- // Skia will still return an object.
- SkScalar radius = m_r1 > 0 ? WebCoreFloatToSkScalar(m_r1) : SK_ScalarMin;
- m_gradient = SkGradientShader::CreateRadial(m_p1,
- radius, colors, pos, static_cast<int>(countUsed), tile);
+ // Since the two-point radial gradient is slower than the plain radial,
+ // only use it if we have to.
+ if (m_p0 != m_p1) {
+ // The radii we give to Skia must be positive. If we're given a
+ // negative radius, ask for zero instead.
+ SkScalar radius0 = m_r0 >= 0.0f ? WebCoreFloatToSkScalar(m_r0) : 0;
+ SkScalar radius1 = m_r1 >= 0.0f ? WebCoreFloatToSkScalar(m_r1) : 0;
+ m_gradient = SkGradientShader::CreateTwoPointRadial(m_p0, radius0, m_p1, radius1, colors, pos, static_cast<int>(countUsed), tile);
+ } else {
+ // The radius we give to Skia must be positive (and non-zero). If
+ // we're given a zero radius, just ask for a very small radius so
+ // Skia will still return an object.
+ SkScalar radius = m_r1 > 0 ? WebCoreFloatToSkScalar(m_r1) : SK_ScalarMin;
+ m_gradient = SkGradientShader::CreateRadial(m_p1, radius, colors, pos, static_cast<int>(countUsed), tile);
+ }
} else {
SkPoint pts[2] = { m_p0, m_p1 };
m_gradient = SkGradientShader::CreateLinear(pts, colors, pos,
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index bbb42c9..c9f1349 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -31,11 +31,11 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "GraphicsContextPlatformPrivate.h"
-#include "GraphicsContextPrivate.h"
#include "Color.h"
#include "FloatRect.h"
#include "Gradient.h"
+#include "GraphicsContextPlatformPrivate.h"
+#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "IntRect.h"
#include "NativeImageSkia.h"
@@ -46,9 +46,9 @@
#include "SkBitmap.h"
#include "SkBlurDrawLooper.h"
#include "SkCornerPathEffect.h"
-#include "skia/ext/platform_canvas.h"
-#include "SkiaUtils.h"
#include "SkShader.h"
+#include "SkiaUtils.h"
+#include "skia/ext/platform_canvas.h"
#include <math.h>
#include <wtf/Assertions.h>
@@ -60,6 +60,23 @@ namespace WebCore {
namespace {
+inline int fastMod(int value, int max)
+{
+ int sign = SkExtractSign(value);
+
+ value = SkApplySign(value, sign);
+ if (value >= max)
+ value %= max;
+ return SkApplySign(value, sign);
+}
+
+inline float square(float n)
+{
+ return n * n;
+}
+
+} // namespace
+
// "Seatbelt" functions ------------------------------------------------------
//
// These functions check certain graphics primitives for being "safe".
@@ -195,23 +212,6 @@ void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int sta
path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false);
}
-inline int fastMod(int value, int max)
-{
- int sign = SkExtractSign(value);
-
- value = SkApplySign(value, sign);
- if (value >= max)
- value %= max;
- return SkApplySign(value, sign);
-}
-
-inline float square(float n)
-{
- return n * n;
-}
-
-} // namespace
-
// -----------------------------------------------------------------------------
// This may be called with a NULL pointer to create a graphics context that has
@@ -293,7 +293,7 @@ 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));
+ r.inset(SkIntToScalar(thickness), SkIntToScalar(thickness));
path.addOval(r, SkPath::kCCW_Direction);
}
platformContext()->canvas()->clipPath(path);
@@ -403,6 +403,9 @@ void GraphicsContext::clipPath(WindRule clipRule)
return;
SkPath path = platformContext()->currentPathInLocalCoordinates();
+ if (!isPathSkiaSafe(getCTM(), path))
+ return;
+
path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
platformContext()->canvas()->clipPath(path);
}
@@ -487,7 +490,7 @@ void GraphicsContext::drawFocusRing(const Color& color)
const Vector<IntRect>& rects = focusRingRects();
unsigned rectCount = rects.size();
- if (0 == rectCount)
+ if (!rectCount)
return;
SkRegion focusRingRegion;
@@ -521,26 +524,28 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
return;
SkPaint paint;
- SkPoint pts[2] = { (SkPoint)point1, (SkPoint)point2 };
- if (!isPointSkiaSafe(getCTM(), pts[0]) || !isPointSkiaSafe(getCTM(), pts[1]))
+ if (!isPointSkiaSafe(getCTM(), point1) || !isPointSkiaSafe(getCTM(), point2))
return;
+ FloatPoint p1 = point1;
+ FloatPoint p2 = point2;
+ bool isVerticalLine = (p1.x() == p2.x());
+ int width = roundf(strokeThickness());
+
// We know these are vertical or horizontal lines, so the length will just
// be the sum of the displacement component vectors give or take 1 -
// probably worth the speed up of no square root, which also won't be exact.
- SkPoint disp = pts[1] - pts[0];
- int length = SkScalarRound(disp.fX + disp.fY);
+ FloatSize disp = p2 - p1;
+ int length = SkScalarRound(disp.width() + disp.height());
platformContext()->setupPaintForStroking(&paint, 0, length);
- int width = roundf(strokeThickness());
- bool isVerticalLine = pts[0].fX == pts[1].fX;
if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {
// 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.
SkRect r1, r2;
- r1.set(pts[0].fX, pts[0].fY, pts[0].fX + width, pts[0].fY + width);
- r2.set(pts[1].fX, pts[1].fY, pts[1].fX + width, pts[1].fY + width);
+ r1.set(p1.x(), p1.y(), p1.x() + width, p1.y() + width);
+ r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + width);
if (isVerticalLine) {
r1.offset(-width / 2, 0);
@@ -553,35 +558,11 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
fillPaint.setColor(paint.getColor());
platformContext()->canvas()->drawRect(r1, fillPaint);
platformContext()->canvas()->drawRect(r2, fillPaint);
-
- // Since we've already rendered the endcaps, adjust the endpoints to
- // exclude them from the line itself.
- if (isVerticalLine) {
- pts[0].fY += width;
- pts[1].fY -= width;
- } else {
- pts[0].fX += width;
- pts[1].fX -= width;
- }
}
- // "Borrowed" this comment and idea from GraphicsContextCG.cpp
- //
- // For odd widths, we add in 0.5 to the appropriate x/y so that the float
- // arithmetic works out. For example, with a border width of 3, KHTML will
- // pass us (y1+y2)/2, e.g., (50+53)/2 = 103/2 = 51 when we want 51.5. It is
- // always true that an even width gave us a perfect position, but an odd
- // width gave us a position that is off by exactly 0.5.
+ adjustLineToPixelBoundaries(p1, p2, width, penStyle);
+ SkPoint pts[2] = { (SkPoint)p1, (SkPoint)p2 };
- if (width & 1) { // Odd.
- if (isVerticalLine) {
- pts[0].fX = pts[0].fX + SK_ScalarHalf;
- pts[1].fX = pts[0].fX;
- } else { // Horizontal line
- pts[0].fY = pts[0].fY + SK_ScalarHalf;
- pts[1].fY = pts[0].fY;
- }
- }
platformContext()->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint);
}
@@ -844,9 +825,9 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
deviceLowerRight.setY(roundf(deviceLowerRight.y()));
// Don't let the height or width round to 0 unless either was originally 0
- if (deviceOrigin.y() == deviceLowerRight.y() && rect.height() != 0)
+ if (deviceOrigin.y() == deviceLowerRight.y() && rect.height())
deviceLowerRight.move(0, 1);
- if (deviceOrigin.x() == deviceLowerRight.x() && rect.width() != 0)
+ if (deviceOrigin.x() == deviceLowerRight.x() && rect.width())
deviceLowerRight.move(1, 0);
FloatPoint roundedOrigin(deviceOrigin.x() / deviceScaleX,
@@ -919,7 +900,7 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
return;
}
- size_t count = (dashLength % 2) == 0 ? dashLength : dashLength * 2;
+ size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
SkScalar* intervals = new SkScalar[count];
for (unsigned int i = 0; i < count; i++)
@@ -990,8 +971,8 @@ void GraphicsContext::setPlatformShadow(const IntSize& size,
return;
// Detect when there's no effective shadow and clear the looper.
- if (size.width() == 0 && size.height() == 0 && blurInt == 0) {
- platformContext()->setDrawLooper(NULL);
+ if (!size.width() && !size.height() && !blurInt) {
+ platformContext()->setDrawLooper(0);
return;
}
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 7935ff1..a5c8926 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -39,6 +39,7 @@
#include "ImageData.h"
#include "PlatformContextSkia.h"
#include "PNGImageEncoder.h"
+#include "SkColorPriv.h"
#include "SkiaUtils.h"
using namespace std;
@@ -118,16 +119,16 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const SkBitmap& bitmap,
+ const IntSize& size)
{
- ASSERT(context());
-
RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
unsigned char* data = result->data()->data()->data();
if (rect.x() < 0 || rect.y() < 0 ||
- (rect.x() + rect.width()) > m_size.width() ||
- (rect.y() + rect.height()) > m_size.height())
+ (rect.x() + rect.width()) > size.width() ||
+ (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originX = rect.x();
@@ -137,8 +138,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originX = 0;
}
int endX = rect.x() + rect.width();
- if (endX > m_size.width())
- endX = m_size.width();
+ if (endX > size.width())
+ endX = size.width();
int numColumns = endX - originX;
int originY = rect.y();
@@ -148,11 +149,10 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originY = 0;
}
int endY = rect.y() + rect.height();
- if (endY > m_size.height())
- endY = m_size.height();
+ if (endY > size.height())
+ endY = size.height();
int numRows = endY - originY;
- const SkBitmap& bitmap = *context()->platformContext()->bitmap();
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
SkAutoLockPixels bitmapLock(bitmap);
@@ -162,12 +162,21 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
for (int y = 0; y < numRows; ++y) {
uint32_t* srcRow = bitmap.getAddr32(originX, originY + y);
for (int x = 0; x < numColumns; ++x) {
- SkColor color = SkPMColorToColor(srcRow[x]);
unsigned char* destPixel = &destRow[x * 4];
- destPixel[0] = SkColorGetR(color);
- destPixel[1] = SkColorGetG(color);
- destPixel[2] = SkColorGetB(color);
- destPixel[3] = SkColorGetA(color);
+ if (multiplied == Unmultiplied) {
+ SkColor color = SkPMColorToColor(srcRow[x]);
+ destPixel[0] = SkColorGetR(color);
+ destPixel[1] = SkColorGetG(color);
+ destPixel[2] = SkColorGetB(color);
+ destPixel[3] = SkColorGetA(color);
+ } else {
+ // Input and output are both pre-multiplied, we just need to re-arrange the
+ // bytes from the bitmap format to RGBA.
+ destPixel[0] = SkGetPackedR32(srcRow[x]);
+ destPixel[1] = SkGetPackedG32(srcRow[x]);
+ destPixel[2] = SkGetPackedB32(srcRow[x]);
+ destPixel[3] = SkGetPackedA32(srcRow[x]);
+ }
}
destRow += destBytesPerRow;
}
@@ -175,8 +184,19 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
- const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint,
+ const SkBitmap& bitmap, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -184,27 +204,26 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
int originX = sourceRect.x();
int destX = destPoint.x() + sourceRect.x();
ASSERT(destX >= 0);
- ASSERT(destX < m_size.width());
+ ASSERT(destX < size.width());
ASSERT(originX >= 0);
ASSERT(originX < sourceRect.right());
int endX = destPoint.x() + sourceRect.right();
- ASSERT(endX <= m_size.width());
+ ASSERT(endX <= size.width());
int numColumns = endX - destX;
int originY = sourceRect.y();
int destY = destPoint.y() + sourceRect.y();
ASSERT(destY >= 0);
- ASSERT(destY < m_size.height());
+ ASSERT(destY < size.height());
ASSERT(originY >= 0);
ASSERT(originY < sourceRect.bottom());
int endY = destPoint.y() + sourceRect.bottom();
- ASSERT(endY <= m_size.height());
+ ASSERT(endY <= size.height());
int numRows = endY - destY;
- const SkBitmap& bitmap = *context()->platformContext()->bitmap();
ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
SkAutoLockPixels bitmapLock(bitmap);
@@ -216,13 +235,27 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect,
uint32_t* destRow = bitmap.getAddr32(destX, destY + y);
for (int x = 0; x < numColumns; ++x) {
const unsigned char* srcPixel = &srcRow[x * 4];
- destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0],
- srcPixel[1], srcPixel[2]);
+ if (multiplied == Unmultiplied)
+ destRow[x] = SkPreMultiplyARGB(srcPixel[3], srcPixel[0],
+ srcPixel[1], srcPixel[2]);
+ else
+ destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0],
+ srcPixel[1], srcPixel[2]);
}
srcRow += srcBytesPerRow;
}
}
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+}
+
String ImageBuffer::toDataURL(const String&) const
{
// Encode the image into a vector.
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index 45c3dcd..ecab364 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -41,6 +41,7 @@
#include "PlatformContextSkia.h"
#include "PlatformString.h"
#include "SkiaUtils.h"
+#include "SkRect.h"
#include "SkShader.h"
#include "TransformationMatrix.h"
@@ -158,8 +159,8 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
// We will always draw in integer sizes, so round the destination rect.
SkIRect destRectRounded;
destRect.round(&destRectRounded);
- SkIRect resizedImageRect; // Represents the size of the resized image.
- resizedImageRect.set(0, 0, destRectRounded.width(), destRectRounded.height());
+ SkIRect resizedImageRect = // Represents the size of the resized image.
+ { 0, 0, destRectRounded.width(), destRectRounded.height() };
if (srcIsFull && bitmap.hasResizedBitmap(destRectRounded.width(), destRectRounded.height())) {
// Yay, this bitmap frame already has a resized version.
@@ -196,25 +197,19 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
} else {
// We should only resize the exposed part of the bitmap to do the
// minimal possible work.
- gfx::Rect destBitmapSubset(destBitmapSubsetSkI.fLeft,
- destBitmapSubsetSkI.fTop,
- destBitmapSubsetSkI.width(),
- destBitmapSubsetSkI.height());
// Resample the needed part of the image.
SkBitmap resampled = skia::ImageOperations::Resize(subset,
skia::ImageOperations::RESIZE_LANCZOS3,
destRectRounded.width(), destRectRounded.height(),
- destBitmapSubset);
+ destBitmapSubsetSkI);
// Compute where the new bitmap should be drawn. Since our new bitmap
// may be smaller than the original, we have to shift it over by the
// same amount that we cut off the top and left.
- SkRect offsetDestRect = {
- destBitmapSubset.x() + destRect.fLeft,
- destBitmapSubset.y() + destRect.fTop,
- destBitmapSubset.right() + destRect.fLeft,
- destBitmapSubset.bottom() + destRect.fTop };
+ destBitmapSubsetSkI.offset(destRect.fLeft, destRect.fTop);
+ SkRect offsetDestRect;
+ offsetDestRect.set(destBitmapSubsetSkI);
canvas.drawBitmapRect(resampled, 0, offsetDestRect, &paint);
}
diff --git a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp b/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
deleted file mode 100644
index 1647b86..0000000
--- a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2008, 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"
-#include "ImageSource.h"
-#include "SharedBuffer.h"
-
-#include "GIFImageDecoder.h"
-#include "ICOImageDecoder.h"
-#include "JPEGImageDecoder.h"
-#include "PNGImageDecoder.h"
-#include "BMPImageDecoder.h"
-#include "XBMImageDecoder.h"
-
-#include "SkBitmap.h"
-
-namespace WebCore {
-
-ImageDecoder* createDecoder(const Vector<char>& data)
-{
- // We need at least 4 bytes to figure out what kind of image we're dealing with.
- int length = data.size();
- if (length < 4)
- return 0;
-
- const unsigned char* uContents = (const unsigned char*)data.data();
- const char* contents = data.data();
-
- // GIFs begin with GIF8(7 or 9).
- if (strncmp(contents, "GIF8", 4) == 0)
- return new GIFImageDecoder();
-
- // Test for PNG.
- if (uContents[0]==0x89 &&
- uContents[1]==0x50 &&
- uContents[2]==0x4E &&
- uContents[3]==0x47)
- return new PNGImageDecoder();
-
- // JPEG
- if (uContents[0]==0xFF &&
- uContents[1]==0xD8 &&
- uContents[2]==0xFF)
- return new JPEGImageDecoder();
-
- // BMP
- if (strncmp(contents, "BM", 2) == 0)
- return new BMPImageDecoder();
-
- // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
- // CURs begin with 2-byte 0 followed by 2-byte 2.
- if (!memcmp(contents, "\000\000\001\000", 4) ||
- !memcmp(contents, "\000\000\002\000", 4))
- return new ICOImageDecoder();
-
- // XBMs require 8 bytes of info.
- if (length >= 8 && strncmp(contents, "#define ", 8) == 0)
- return new XBMImageDecoder();
-
- // Give up. We don't know what the heck this is.
- return 0;
-}
-
-ImageSource::ImageSource()
- : m_decoder(0)
-{}
-
-ImageSource::~ImageSource()
-{
- clear(true);
-}
-
-void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
-{
- if (!destroyAll) {
- if (m_decoder)
- m_decoder->clearFrameBufferCache(clearBeforeFrame);
- return;
- }
-
- delete m_decoder;
- m_decoder = 0;
- if (data)
- setData(data, allDataReceived);
-}
-
-bool ImageSource::initialized() const
-{
- return m_decoder;
-}
-
-void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
-{
- // Make the decoder by sniffing the bytes.
- // This method will examine the data and instantiate an instance of the appropriate decoder plugin.
- // If insufficient bytes are available to determine the image type, no decoder plugin will be
- // made.
- if (!m_decoder)
- m_decoder = createDecoder(data->buffer());
-
- // CreateDecoder will return NULL if the decoder could not be created. Plus,
- // we should not send more data to a decoder which has already decided it
- // has failed.
- if (!m_decoder || m_decoder->failed())
- return;
- m_decoder->setData(data, allDataReceived);
-}
-
-bool ImageSource::isSizeAvailable()
-{
- if (!m_decoder)
- return false;
-
- return m_decoder->isSizeAvailable();
-}
-
-IntSize ImageSource::size() const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->size();
-}
-
-IntSize ImageSource::frameSizeAtIndex(size_t index) const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
-}
-
-int ImageSource::repetitionCount()
-{
- if (!m_decoder)
- return cAnimationNone;
-
- return m_decoder->repetitionCount();
-}
-
-size_t ImageSource::frameCount() const
-{
- if (!m_decoder)
- return 0;
- return m_decoder->failed() ? 0 : m_decoder->frameCount();
-}
-
-NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- // Note that the buffer can have NULL bytes even when it is marked as
- // non-empty. It seems "FrameEmpty" is only set before the frame has been
- // initialized. If it is decoded and it happens to be empty, it will be
- // marked as "FrameComplete" but will still have NULL bytes.
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return 0;
-
- // Copy the bitmap. The pixel data is refcounted internally by SkBitmap, so
- // this doesn't cost much.
- return buffer->asNewNativeImage();
-}
-
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
-{
- if (!m_decoder)
- return false;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- return buffer && buffer->status() == RGBA32Buffer::FrameComplete;
-}
-
-float ImageSource::frameDurationAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return 0;
-
- // Many annoying ads specify a 0 duration to make an image flash as quickly
- // as possible. We follow WinIE's behavior and use a duration of 100 ms
- // for any frames that specify a duration of <= 50 ms. See
- // <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for
- // more.
- const float duration = buffer->duration() / 1000.0f;
- return (duration < 0.051f) ? 0.100f : duration;
-}
-
-bool ImageSource::frameHasAlphaAtIndex(size_t index)
-{
- if (!m_decoder || !m_decoder->supportsAlpha())
- return false;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return false;
-
- return buffer->hasAlpha();
-}
-
-String ImageSource::filenameExtension() const
-{
- return m_decoder ? m_decoder->filenameExtension() : String();
-}
-
-}
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index e0a292c..1fb62fc 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -46,6 +46,11 @@
#include <wtf/MathExtras.h>
+namespace WebCore
+{
+extern bool isPathSkiaSafe(const SkMatrix& transform, const SkPath& path);
+}
+
// State -----------------------------------------------------------------------
// Encapsulates the additional painting state information we store for each
@@ -278,6 +283,7 @@ void PlatformContextSkia::drawRect(SkRect rect)
SkShader* oldFillShader = m_state->m_fillShader;
oldFillShader->safeRef();
setFillColor(m_state->m_strokeColor);
+ paint.reset();
setupPaintForFilling(&paint);
SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 };
canvas()->drawRect(topBorder, paint);
@@ -295,7 +301,7 @@ void PlatformContextSkia::drawRect(SkRect rect)
void PlatformContextSkia::setupPaintCommon(SkPaint* paint) const
{
-#ifdef SK_DEBUGx
+#if defined(SK_DEBUG)
{
SkPaint defaultPaint;
SkASSERT(*paint == defaultPaint);
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index 803f5db..e2ed130 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -297,6 +297,30 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
CGContextRef cgContext = graphicsContext->platformContext();
bool shouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
+ switch(fontDescription().fontSmoothing()) {
+ case Antialiased: {
+ graphicsContext->setShouldAntialias(true);
+ shouldUseFontSmoothing = false;
+ break;
+ }
+ case SubpixelAntialiased: {
+ graphicsContext->setShouldAntialias(true);
+ shouldUseFontSmoothing = true;
+ break;
+ }
+ case NoSmoothing: {
+ graphicsContext->setShouldAntialias(false);
+ shouldUseFontSmoothing = false;
+ break;
+ }
+ case AutoSmoothing: {
+ // For the AutoSmooth case, don't do anything! Keep the default settings.
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
if (font->platformData().useGDI()) {
if (!shouldUseFontSmoothing || (graphicsContext->textDrawingMode() & cTextStroke)) {
drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp
index 887bf79..8663623 100644
--- a/WebCore/platform/graphics/win/FontCacheWin.cpp
+++ b/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -33,8 +33,9 @@
#include "SimpleFontData.h"
#include "StringHash.h"
#include "UnicodeRange.h"
-#include <windows.h>
#include <mlang.h>
+#include <windows.h>
+#include <wtf/StdLibExtras.h>
#if PLATFORM(CG)
#include <ApplicationServices/ApplicationServices.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
@@ -305,7 +306,17 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fo
// FIXME: Would be even better to somehow get the user's default font here. For now we'll pick
// the default that the user would get without changing any prefs.
static AtomicString timesStr("Times New Roman");
- return getCachedFontPlatformData(fontDescription, timesStr);
+ if (FontPlatformData* platformFont = getCachedFontPlatformData(fontDescription, timesStr))
+ return platformFont;
+
+ DEFINE_STATIC_LOCAL(String, defaultGUIFontFamily, ());
+ if (defaultGUIFontFamily.isEmpty()) {
+ HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
+ LOGFONT logFont;
+ GetObject(defaultGUIFont, sizeof(logFont), &logFont);
+ defaultGUIFontFamily = String(logFont.lfFaceName, wcsnlen(logFont.lfFaceName, LF_FACESIZE));
+ }
+ return getCachedFontPlatformData(fontDescription, defaultGUIFontFamily);
}
static LONG toGDIFontWeight(FontWeight fontWeight)
diff --git a/WebCore/platform/graphics/win/FontDatabase.cpp b/WebCore/platform/graphics/win/FontDatabase.cpp
index 1308ff0..d0773ea 100644
--- a/WebCore/platform/graphics/win/FontDatabase.cpp
+++ b/WebCore/platform/graphics/win/FontDatabase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -99,17 +99,12 @@ static RetainPtr<CFPropertyListRef> readFontPlist()
return plist;
}
-static bool populateFontDatabaseFromPlist()
+static bool populateFontDatabaseFromPlist(CFPropertyListRef plist)
{
- RetainPtr<CFPropertyListRef> plist = readFontPlist();
if (!plist)
return false;
- RetainPtr<CFDataRef> data(AdoptCF, CFPropertyListCreateXMLData(0, plist.get()));
- if (!data)
- return false;
-
- wkAddFontsFromPlistRepresentation(data.get());
+ wkAddFontsFromPlist(plist);
return true;
}
@@ -123,15 +118,69 @@ static bool populateFontDatabaseFromFileSystem()
return true;
}
-static void writeFontDatabaseToPlist()
+static CFStringRef fontFilenamesFromRegistryKey()
+{
+ static CFStringRef key = CFSTR("WebKitFontFilenamesFromRegistry");
+ return key;
+}
+
+static void writeFontDatabaseToPlist(CFPropertyListRef cgFontDBPropertyList, CFPropertyListRef filenamesFromRegistry)
{
- RetainPtr<CFDataRef> data(AdoptCF, wkCreateFontsPlistRepresentation());
+ if (!cgFontDBPropertyList)
+ return;
+
+ RetainPtr<CFDataRef> data;
+
+ if (!filenamesFromRegistry || CFGetTypeID(cgFontDBPropertyList) != CFDictionaryGetTypeID())
+ data.adoptCF(CFPropertyListCreateXMLData(kCFAllocatorDefault, cgFontDBPropertyList));
+ else {
+ RetainPtr<CFMutableDictionaryRef> dictionary(AdoptCF, CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2, static_cast<CFDictionaryRef>(cgFontDBPropertyList)));
+ CFDictionarySetValue(dictionary.get(), fontFilenamesFromRegistryKey(), filenamesFromRegistry);
+ data.adoptCF(CFPropertyListCreateXMLData(kCFAllocatorDefault, dictionary.get()));
+ }
+
if (!data)
return;
safeCreateFile(fontsPlistPath(), data.get());
}
+static RetainPtr<CFArrayRef> fontFilenamesFromRegistry()
+{
+ RetainPtr<CFMutableArrayRef> filenames(AdoptCF, CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks));
+
+ HKEY key;
+ if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), 0, KEY_READ, &key)))
+ return filenames;
+
+ DWORD valueCount;
+ DWORD maxNameLength;
+ DWORD maxValueLength;
+ if (FAILED(RegQueryInfoKey(key, 0, 0, 0, 0, 0, 0, &valueCount, &maxNameLength, &maxValueLength, 0, 0))) {
+ RegCloseKey(key);
+ return filenames;
+ }
+
+ Vector<TCHAR> name(maxNameLength + 1);
+ Vector<BYTE> value(maxValueLength + 1);
+
+ for (size_t i = 0; i < valueCount; ++i) {
+ DWORD nameLength = name.size();
+ DWORD valueLength = value.size();
+ DWORD type;
+ if (FAILED(RegEnumValue(key, i, name.data(), &nameLength, 0, &type, value.data(), &valueLength)))
+ continue;
+ if (type != REG_SZ)
+ continue;
+
+ RetainPtr<CFDataRef> filename(AdoptCF, CFDataCreate(kCFAllocatorDefault, value.data(), valueLength));
+ CFArrayAppendValue(filenames.get(), filename.get());
+ }
+
+ RegCloseKey(key);
+ return filenames;
+}
+
void populateFontDatabase()
{
static bool initialized;
@@ -139,12 +188,27 @@ void populateFontDatabase()
return;
initialized = true;
- if (!systemHasFontsNewerThanFontsPlist())
- if (populateFontDatabaseFromPlist())
+ RetainPtr<CFPropertyListRef> propertyList = readFontPlist();
+ RetainPtr<CFArrayRef> lastFilenamesFromRegistry;
+ if (propertyList && CFGetTypeID(propertyList.get()) == CFDictionaryGetTypeID()) {
+ CFDictionaryRef dictionary = static_cast<CFDictionaryRef>(propertyList.get());
+ CFArrayRef array = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, fontFilenamesFromRegistryKey()));
+ if (array && CFGetTypeID(array) == CFArrayGetTypeID())
+ lastFilenamesFromRegistry = array;
+ }
+ RetainPtr<CFArrayRef> currentFilenamesFromRegistry = fontFilenamesFromRegistry();
+ bool registryChanged = !lastFilenamesFromRegistry || !CFEqual(lastFilenamesFromRegistry.get(), currentFilenamesFromRegistry.get());
+
+ if (!registryChanged && !systemHasFontsNewerThanFontsPlist()) {
+ if (populateFontDatabaseFromPlist(propertyList.get()))
return;
+ }
- if (populateFontDatabaseFromFileSystem())
- writeFontDatabaseToPlist();
+ if (populateFontDatabaseFromFileSystem()) {
+ wkAddFontsFromRegistry();
+ RetainPtr<CFPropertyListRef> cgFontDBPropertyList(AdoptCF, wkCreateFontsPlist());
+ writeFontDatabaseToPlist(cgFontDBPropertyList.get(), currentFilenamesFromRegistry.get());
+ }
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/FontPlatformData.h b/WebCore/platform/graphics/win/FontPlatformData.h
index 0660d90..5084469 100644
--- a/WebCore/platform/graphics/win/FontPlatformData.h
+++ b/WebCore/platform/graphics/win/FontPlatformData.h
@@ -78,7 +78,6 @@ public:
#if PLATFORM(CG)
CGFontRef cgFont() const { return m_cgFont.get(); }
#elif PLATFORM(CAIRO)
- void setFont(cairo_t* ft) const;
cairo_font_face_t* fontFace() const { return m_fontFace; }
cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
#endif
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
index b56a71c..9fce68a 100644
--- a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
+++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
@@ -96,12 +96,6 @@ FontPlatformData::FontPlatformData(const FontPlatformData& source)
m_scaledFont = cairo_scaled_font_reference(source.m_scaledFont);
}
-void FontPlatformData::setFont(cairo_t* cr) const
-{
- ASSERT(m_scaledFont);
-
- cairo_set_scaled_font(cr, m_scaledFont);
-}
FontPlatformData::~FontPlatformData()
{
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 9eaf54b..1923ecc 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -65,7 +65,7 @@ GraphicsContext::GraphicsContext(HDC hdc, bool hasAlpha)
: m_common(createGraphicsContextPrivate())
, m_data(new GraphicsContextPlatformPrivate(CGContextWithHDC(hdc, hasAlpha)))
{
- CGContextRelease(m_data->m_cgContext);
+ CGContextRelease(m_data->m_cgContext.get());
m_data->m_hdc = hdc;
setPaintingDisabled(!m_data->m_cgContext);
if (m_data->m_cgContext) {
@@ -98,7 +98,7 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo
CGColorSpaceRelease(deviceRGB);
CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
- CGContextDrawImage(m_data->m_cgContext, dstRect, image);
+ CGContextDrawImage(m_data->m_cgContext.get(), dstRect, image);
// Delete all our junk.
CGImageRelease(image);
@@ -121,7 +121,7 @@ void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& po
RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(imageData.get()));
RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(image->size().width(), image->size().height(), 8, 32, image->bytesPerRow(), deviceRGB.get(),
kCGBitmapByteOrder32Little | kCGImageAlphaFirst, dataProvider.get(), 0, true, kCGRenderingIntentDefault));
- CGContextDrawImage(m_data->m_cgContext, CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());
+ CGContextDrawImage(m_data->m_cgContext.get(), CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get());
}
void GraphicsContext::drawFocusRing(const Color& color)
@@ -243,7 +243,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point,
void GraphicsContextPlatformPrivate::flush()
{
- CGContextFlush(m_cgContext);
+ CGContextFlush(m_cgContext.get());
}
}
diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp
index 8a8e943..285fb71 100644
--- a/WebCore/platform/graphics/win/ImageCGWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCGWin.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "Image.h"
#include "BitmapImage.h"
+#include "BitmapInfo.h"
#include "GraphicsContext.h"
#include <ApplicationServices/ApplicationServices.h>
@@ -34,6 +35,30 @@
namespace WebCore {
+PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+ DIBSECTION dibSection;
+ if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection))
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBitsPixel == 32);
+ if (dibSection.dsBm.bmBitsPixel != 32)
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBits);
+ if (!dibSection.dsBm.bmBits)
+ return 0;
+
+ RetainPtr<CGColorSpaceRef> deviceRGB(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGContextRef> bitmapContext(AdoptCF, CGBitmapContextCreate(dibSection.dsBm.bmBits, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight, 8,
+ dibSection.dsBm.bmWidthBytes, deviceRGB.get(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
+
+ // The BitmapImage takes ownership of this.
+ CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext.get());
+
+ return adoptRef(new BitmapImage(cgImage));
+}
+
bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
{
ASSERT(bmp);
diff --git a/WebCore/platform/graphics/win/ImageCairoWin.cpp b/WebCore/platform/graphics/win/ImageCairoWin.cpp
index 591375f..0b27438 100644
--- a/WebCore/platform/graphics/win/ImageCairoWin.cpp
+++ b/WebCore/platform/graphics/win/ImageCairoWin.cpp
@@ -28,12 +28,33 @@
#include "BitmapImage.h"
#include "GraphicsContext.h"
#include <cairo.h>
+#include <cairo-win32.h>
#include <windows.h>
#include "PlatformString.h"
namespace WebCore {
+PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
+{
+ DIBSECTION dibSection;
+ if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection))
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBitsPixel == 32);
+ if (dibSection.dsBm.bmBitsPixel != 32)
+ return 0;
+
+ ASSERT(dibSection.dsBm.bmBits);
+ if (!dibSection.dsBm.bmBits)
+ return 0;
+
+ cairo_surface_t* image = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight);
+
+ // The BitmapImage object takes over ownership of the cairo_surface_t*, so no need to destroy here.
+ return adoptRef(new BitmapImage(image));
+}
+
bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
{
ASSERT(bmp);
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
index eb7334e..15e1001 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -33,6 +33,8 @@
#include "QTMovieWin.h"
#include "ScrollView.h"
#include "StringHash.h"
+#include "TimeRanges.h"
+#include "Timer.h"
#include <wtf/HashSet.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
@@ -86,6 +88,50 @@ MediaPlayerPrivate::~MediaPlayerPrivate()
{
}
+class TaskTimer : TimerBase {
+public:
+ static void initialize();
+
+private:
+ static void setTaskTimerDelay(double);
+ static void stopTaskTimer();
+
+ void fired();
+
+ static TaskTimer* s_timer;
+};
+
+TaskTimer* TaskTimer::s_timer = 0;
+
+void TaskTimer::initialize()
+{
+ if (s_timer)
+ return;
+
+ s_timer = new TaskTimer;
+
+ QTMovieWin::setTaskTimerFuncs(setTaskTimerDelay, stopTaskTimer);
+}
+
+void TaskTimer::setTaskTimerDelay(double delayInSeconds)
+{
+ ASSERT(s_timer);
+
+ s_timer->startOneShot(delayInSeconds);
+}
+
+void TaskTimer::stopTaskTimer()
+{
+ ASSERT(s_timer);
+
+ s_timer->stop();
+}
+
+void TaskTimer::fired()
+{
+ QTMovieWin::taskTimerFired();
+}
+
void MediaPlayerPrivate::load(const String& url)
{
if (!QTMovieWin::initializeQuickTime()) {
@@ -95,6 +141,9 @@ void MediaPlayerPrivate::load(const String& url)
return;
}
+ // Initialize the task timer.
+ TaskTimer::initialize();
+
if (m_networkState != MediaPlayer::Loading) {
m_networkState = MediaPlayer::Loading;
m_player->networkStateChanged();
@@ -241,6 +290,13 @@ bool MediaPlayerPrivate::hasVideo() const
return m_qtMovie->hasVideo();
}
+bool MediaPlayerPrivate::hasAudio() const
+{
+ if (!m_qtMovie)
+ return false;
+ return m_qtMovie->hasAudio();
+}
+
void MediaPlayerPrivate::setVolume(float volume)
{
if (!m_qtMovie)
@@ -268,10 +324,14 @@ int MediaPlayerPrivate::dataRate() const
return 0;
}
-float MediaPlayerPrivate::maxTimeBuffered() const
+PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
+ RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ float loaded = maxTimeLoaded();
// rtsp streams are not buffered
- return m_isStreaming ? 0 : maxTimeLoaded();
+ if (!m_isStreaming && loaded > 0)
+ timeRanges->add(0, loaded);
+ return timeRanges.release();
}
float MediaPlayerPrivate::maxTimeSeekable() const
@@ -575,4 +635,3 @@ bool MediaPlayerPrivate::hasSingleSecurityOrigin() const
}
#endif
-
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
index f584148..4a3a28e 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -52,7 +52,8 @@ public:
IntSize naturalSize() const;
bool hasVideo() const;
-
+ bool hasAudio() const;
+
void load(const String& url);
void cancelLoad();
@@ -76,7 +77,7 @@ public:
MediaPlayer::NetworkState networkState() const { return m_networkState; }
MediaPlayer::ReadyState readyState() const { return m_readyState; }
- float maxTimeBuffered() const;
+ PassRefPtr<TimeRanges> buffered() const;
float maxTimeSeekable() const;
unsigned bytesLoaded() const;
bool totalBytesKnown() const;
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
index aaa61f1..56f3d0b 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.cpp
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -62,10 +62,13 @@ static HashSet<QTMovieWinPrivate*>* gTaskList;
static Vector<CFStringRef>* gSupportedTypes = 0;
static SInt32 quickTimeVersion = 0;
+static QTMovieWin::SetTaskTimerDelayFunc gSetTaskTimerDelay = 0;
+static QTMovieWin::StopTaskTimerFunc gStopTaskTimer = 0;
+
static void updateTaskTimer(int maxInterval = 1000)
{
if (!gTaskList->size()) {
- stopSharedTimer();
+ gStopTaskTimer();
return;
}
@@ -73,7 +76,7 @@ static void updateTaskTimer(int maxInterval = 1000)
QTGetTimeUntilNextTask(&intervalInMS, 1000);
if (intervalInMS > maxInterval)
intervalInMS = maxInterval;
- setSharedTimerFireDelay(static_cast<float>(intervalInMS) / 1000);
+ gSetTaskTimerDelay(static_cast<float>(intervalInMS) / 1000);
}
class QTMovieWinPrivate : public Noncopyable {
@@ -166,7 +169,7 @@ QTMovieWinPrivate::~QTMovieWinPrivate()
CFRelease(m_currentURL);
}
-static void taskTimerFired()
+void QTMovieWin::taskTimerFired()
{
// The hash content might change during task()
Vector<QTMovieWinPrivate*> tasks;
@@ -867,6 +870,13 @@ bool QTMovieWin::hasVideo() const
return (GetMovieIndTrackType(m_private->m_movie, 1, VisualMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
}
+bool QTMovieWin::hasAudio() const
+{
+ if (!m_private->m_movie)
+ return false;
+ return (GetMovieIndTrackType(m_private->m_movie, 1, AudioMediaCharacteristic, movieTrackCharacteristic | movieTrackEnabledOnly));
+}
+
pascal OSErr movieDrawingCompleteProc(Movie movie, long data)
{
UppParam param;
@@ -990,6 +1000,12 @@ void QTMovieWin::getSupportedType(unsigned index, const UChar*& str, unsigned& l
}
+void QTMovieWin::setTaskTimerFuncs(SetTaskTimerDelayFunc setTaskTimerDelay, StopTaskTimerFunc stopTaskTimer)
+{
+ gSetTaskTimerDelay = setTaskTimerDelay;
+ gStopTaskTimer = stopTaskTimer;
+}
+
bool QTMovieWin::initializeQuickTime()
{
static bool initialized = false;
@@ -1009,7 +1025,6 @@ bool QTMovieWin::initializeQuickTime()
return false;
}
EnterMovies();
- setSharedTimerFiredFunction(taskTimerFired);
gMovieDrawingCompleteUPP = NewMovieDrawingCompleteUPP(movieDrawingCompleteProc);
initializationSucceeded = true;
}
@@ -1020,7 +1035,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
- setSharedTimerInstanceHandle(hinstDLL);
return TRUE;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
index f46efd3..d178eb8 100644
--- a/WebCore/platform/graphics/win/QTMovieWin.h
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -59,6 +59,11 @@ class QTMOVIEWIN_API QTMovieWin {
public:
static bool initializeQuickTime();
+ typedef void (*SetTaskTimerDelayFunc)(double);
+ typedef void (*StopTaskTimerFunc)();
+ static void setTaskTimerFuncs(SetTaskTimerDelayFunc, StopTaskTimerFunc);
+ static void taskTimerFired();
+
QTMovieWin(QTMovieWinClient*);
~QTMovieWin();
@@ -91,6 +96,7 @@ public:
void setDisabled(bool);
bool hasVideo() const;
+ bool hasAudio() const;
static unsigned countSupportedTypes();
static void getSupportedType(unsigned index, const UChar*& str, unsigned& len);
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
index 0343007..26b22af 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
@@ -119,10 +119,4 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
return width * metricsMultiplier;
}
-void SimpleFontData::setFont(cairo_t* cr) const
-{
- ASSERT(cr);
- m_platformData.setFont(cr);
-}
-
}
diff --git a/WebCore/platform/graphics/wince/ColorWince.cpp b/WebCore/platform/graphics/wince/ColorWince.cpp
new file mode 100644
index 0000000..820b9d2
--- /dev/null
+++ b/WebCore/platform/graphics/wince/ColorWince.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007-2008 Torch Mobile, 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.
+ *
+ */
+
+#include "config.h"
+#include "Color.h"
+
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+Color focusRingColor()
+{
+ return Color(0, 0, 0);
+}
+
+void setFocusRingColorChangeFunction(void (*)())
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
index 7c6853c..699ff25 100644
--- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
@@ -33,6 +33,11 @@ static CustomFontCache* g_customFontCache = 0;
bool renameFont(SharedBuffer* fontData, const String& fontName);
+void setCustomFontCache(CustomFontCache* cache)
+{
+ g_customFontCache = cache;
+}
+
FontCustomPlatformData::~FontCustomPlatformData()
{
if (g_customFontCache && !m_name.isEmpty())
@@ -66,11 +71,12 @@ static String createUniqueFontName()
return fontName.replace('/', '_');
}
-FontCustomPlatformData* createFontCustomPlatformData(CachedFont* cachedFont)
+FontCustomPlatformData* createFontCustomPlatformData(const SharedBuffer* buffer)
{
- if (g_customFontCache && cachedFont->CachedResource::data()) {
+ if (g_customFontCache) {
String fontName = createUniqueFontName();
- if (renameFont(cachedFont->CachedResource::data(), fontName) && g_customFontCache->registerFont(fontName, cachedFont))
+ RefPtr<SharedBuffer> localBuffer = SharedBuffer::create(buffer->data(), buffer->size());
+ if (renameFont(localBuffer.get(), fontName) && g_customFontCache->registerFont(fontName, localBuffer.get()))
return new FontCustomPlatformData(fontName);
}
return 0;
diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.h b/WebCore/platform/graphics/wince/FontCustomPlatformData.h
index b1f64a0..89d1fdd 100644
--- a/WebCore/platform/graphics/wince/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.h
@@ -32,7 +32,7 @@ namespace WebCore {
class CustomFontCache {
public:
- virtual bool registerFont(const String& fontName, CachedFont*) = 0;
+ virtual bool registerFont(const String& fontName, const SharedBuffer*) = 0;
virtual void unregisterFont(const String& fontName) = 0;
};
@@ -48,8 +48,8 @@ namespace WebCore {
String m_name;
};
- FontCustomPlatformData* createFontCustomPlatformData(CachedFont*);
-
+ FontCustomPlatformData* createFontCustomPlatformData(const SharedBuffer*);
+ void setCustomFontCache(CustomFontCache*);
}
#endif
diff --git a/WebCore/platform/graphics/wince/GradientWince.cpp b/WebCore/platform/graphics/wince/GradientWince.cpp
new file mode 100644
index 0000000..49fa970
--- /dev/null
+++ b/WebCore/platform/graphics/wince/GradientWince.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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 "Gradient.h"
+
+#include "GraphicsContext.h"
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+}
+
+static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::ColorStop& b)
+{
+ return a.stop < b.stop;
+}
+
+const Vector<Gradient::ColorStop>& Gradient::getStops() const
+{
+ if (!m_stopsSorted) {
+ if (m_stops.size())
+ std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
+ m_stopsSorted = true;
+ }
+ return m_stops;
+}
+
+void Gradient::fill(GraphicsContext* c, const FloatRect& r)
+{
+ c->fillRect(r, this);
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/ImageBufferData.h b/WebCore/platform/graphics/wince/ImageBufferData.h
new file mode 100644
index 0000000..01b7d06
--- /dev/null
+++ b/WebCore/platform/graphics/wince/ImageBufferData.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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.
+ */
+
+#ifndef ImageBufferData_h
+#define ImageBufferData_h
+
+namespace WebCore {
+
+ class IntSize;
+ class ImageBufferData {
+ public:
+ ImageBufferData(const IntSize& size);
+ RefPtr<SharedBitmap> m_bitmap;
+ };
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
new file mode 100644
index 0000000..3417f5f
--- /dev/null
+++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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 "ImageBuffer.h"
+
+#include "Base64.h"
+#include "GraphicsContext.h"
+#include "Image.h"
+#include "ImageData.h"
+#include "JPEGEncoder.h"
+#include "PNGEncoder.h"
+#include "SharedBitmap.h"
+
+namespace WebCore {
+
+class BufferedImage: public Image {
+
+public:
+ BufferedImage(const ImageBufferData* data)
+ : m_data(data)
+ {
+ }
+
+ virtual IntSize size() const { return IntSize(m_data->m_bitmap->width(), m_data->m_bitmap->height()); }
+ virtual void destroyDecodedData(bool destroyAll = true) {}
+ virtual unsigned decodedSize() const { return 0; }
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform,
+ const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+
+ const ImageBufferData* m_data;
+};
+
+void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+{
+ IntRect intDstRect = enclosingIntRect(dstRect);
+ IntRect intSrcRect(srcRect);
+ m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, compositeOp);
+}
+
+void BufferedImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const TransformationMatrix& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ m_data->m_bitmap->drawPattern(ctxt, tileRectIn, patternTransform, phase, op, destRect, size());
+}
+
+ImageBufferData::ImageBufferData(const IntSize& size)
+: m_bitmap(SharedBitmap::createInstance(false, size.width(), size.height(), false))
+{
+ // http://www.w3.org/TR/2009/WD-html5-20090212/the-canvas-element.html#canvaspixelarray
+ // "When the canvas is initialized it must be set to fully transparent black."
+ m_bitmap->resetPixels(true);
+ m_bitmap->setHasAlpha(true);
+}
+
+ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace colorSpace, bool& success)
+ : m_data(size)
+ , m_size(size)
+{
+ // FIXME: colorSpace is not used
+ UNUSED_PARAM(colorSpace);
+
+ m_context.set(new GraphicsContext(0));
+ m_context->setBitmap(m_data.m_bitmap);
+ success = true;
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ return m_context.get();
+}
+
+Image* ImageBuffer::image() const
+{
+ if (!m_image)
+ m_image = adoptRef(new BufferedImage(&m_data));
+
+ return m_image.get();
+}
+
+template <bool premultiplied> PassRefPtr<ImageData>
+static getImageData(const IntRect& rect, const SharedBitmap* bitmap)
+{
+ PassRefPtr<ImageData> imageData = ImageData::create(rect.width(), rect.height());
+
+ const unsigned char* src = static_cast<const unsigned char*>(bitmap->bytes());
+ if (!src)
+ return imageData;
+
+ IntRect sourceRect(0, 0, bitmap->width(), bitmap->height());
+ sourceRect.intersect(rect);
+ if (sourceRect.isEmpty())
+ return imageData;
+
+ unsigned char* dst = imageData->data()->data()->data();
+ memset(dst, 0, imageData->data()->data()->length());
+ src += (sourceRect.y() * bitmap->width() + sourceRect.x()) * 4;
+ dst += ((sourceRect.y() - rect.y()) * imageData->width() + sourceRect.x() - rect.x()) * 4;
+ int bytesToCopy = sourceRect.width() * 4;
+ int srcSkip = (bitmap->width() - sourceRect.width()) * 4;
+ int dstSkip = (imageData->width() - sourceRect.width()) * 4;
+ const unsigned char* dstEnd = dst + sourceRect.height() * imageData->width() * 4;
+ while (dst < dstEnd) {
+ const unsigned char* dstRowEnd = dst + bytesToCopy;
+ while (dst < dstRowEnd) {
+ // Convert ARGB little endian to RGBA big endian
+ int blue = *src++;
+ int green = *src++;
+ int red = *src++;
+ int alpha = *src++;
+ if (premultiplied) {
+ *dst++ = static_cast<unsigned char>((red * alpha + 254) / 255);
+ *dst++ = static_cast<unsigned char>((green * alpha + 254) / 255);
+ *dst++ = static_cast<unsigned char>((blue * alpha + 254) / 255);
+ *dst++ = static_cast<unsigned char>(alpha);
+ } else {
+ *dst++ = static_cast<unsigned char>(red);
+ *dst++ = static_cast<unsigned char>(green);
+ *dst++ = static_cast<unsigned char>(blue);
+ *dst++ = static_cast<unsigned char>(alpha);
+ ++src;
+ }
+ }
+ src += srcSkip;
+ dst += dstSkip;
+ }
+
+ return imageData;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<false>(rect, m_data.m_bitmap.get());
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<true>(rect, m_data.m_bitmap.get());
+}
+
+template <bool premultiplied>
+static void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint, SharedBitmap* bitmap)
+{
+ unsigned char* dst = (unsigned char*)bitmap->bytes();
+ if (!dst)
+ return;
+
+ IntRect destRect(destPoint, sourceRect.size());
+ destRect.intersect(IntRect(0, 0, bitmap->width(), bitmap->height()));
+
+ if (destRect.isEmpty())
+ return;
+
+ const unsigned char* src = source->data()->data()->data();
+ dst += (destRect.y() * bitmap->width() + destRect.x()) * 4;
+ src += (sourceRect.y() * source->width() + sourceRect.x()) * 4;
+ int bytesToCopy = destRect.width() * 4;
+ int dstSkip = (bitmap->width() - destRect.width()) * 4;
+ int srcSkip = (source->width() - destRect.width()) * 4;
+ const unsigned char* dstEnd = dst + destRect.height() * bitmap->width() * 4;
+ while (dst < dstEnd) {
+ const unsigned char* dstRowEnd = dst + bytesToCopy;
+ while (dst < dstRowEnd) {
+ // Convert RGBA big endian to ARGB little endian
+ int red = *src++;
+ int green = *src++;
+ int blue = *src++;
+ int alpha = *src++;
+ if (premultiplied) {
+ *dst++ = static_cast<unsigned char>(blue * 255 / alpha);
+ *dst++ = static_cast<unsigned char>(green * 255 / alpha);
+ *dst++ = static_cast<unsigned char>(red * 255 / alpha);
+ *dst++ = static_cast<unsigned char>(alpha);
+ } else {
+ *dst++ = static_cast<unsigned char>(blue);
+ *dst++ = static_cast<unsigned char>(green);
+ *dst++ = static_cast<unsigned char>(red);
+ *dst++ = static_cast<unsigned char>(alpha);
+ }
+ }
+ src += srcSkip;
+ dst += dstSkip;
+ }
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<false>(source, sourceRect, destPoint, m_data.m_bitmap.get());
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get());
+}
+
+String ImageBuffer::toDataURL(const String& mimeType) const
+{
+ if (!m_data.m_bitmap->bytes())
+ return "data:,";
+
+ Vector<char> output;
+ const char* header;
+ if (mimeType.lower() == "image/png") {
+ if (!compressBitmapToPng(m_data.m_bitmap.get(), output))
+ return "data:,";
+ header = "data:image/png;base64,";
+ } else {
+ if (!compressBitmapToJpeg(m_data.m_bitmap.get(), output))
+ return "data:,";
+ header = "data:image/jpeg;base64,";
+ }
+
+ Vector<char> base64;
+ base64Encode(output, base64);
+
+ output.clear();
+
+ Vector<char> url;
+ url.append(header, strlen(header));
+ url.append(base64);
+
+ return String(url.data(), url.size());
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h
new file mode 100644
index 0000000..2d6c358
--- /dev/null
+++ b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile 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 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.
+ */
+
+#ifndef MediaPlayerPrivateWince_h
+#define MediaPlayerPrivateWince_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayerPrivate.h"
+#include "Timer.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+ class GraphicsContext;
+ class IntSize;
+ class IntRect;
+ class String;
+
+ class MediaPlayerPrivate : public MediaPlayerPrivateInterface {
+ public:
+ static void registerMediaEngine(MediaEngineRegistrar);
+
+ ~MediaPlayerPrivate();
+
+ IntSize naturalSize() const;
+ bool hasVideo() const;
+
+ void load(const String& url);
+ void cancelLoad();
+
+ void play();
+ void pause();
+
+ bool paused() const;
+ bool seeking() const;
+
+ float duration() const;
+ float currentTime() const;
+ void seek(float time);
+ void setEndTime(float);
+
+ void setRate(float);
+ void setVolume(float);
+
+ int dataRate() const;
+
+ MediaPlayer::NetworkState networkState() const { return m_networkState; }
+ MediaPlayer::ReadyState readyState() const { return m_readyState; }
+
+ PassRefPtr<TimeRanges> buffered() const;
+ float maxTimeSeekable() const;
+ unsigned bytesLoaded() const;
+ bool totalBytesKnown() const;
+ unsigned totalBytes() const;
+
+ void setVisible(bool);
+ void setSize(const IntSize&);
+
+ void loadStateChanged();
+ void didEnd();
+
+ void paint(GraphicsContext*, const IntRect&);
+
+ private:
+ MediaPlayerPrivate(MediaPlayer*);
+
+ void updateStates();
+ void doSeek();
+ void cancelSeek();
+ void seekTimerFired(Timer<MediaPlayerPrivate>*);
+ float maxTimeLoaded() const;
+ void sawUnsupportedTracks();
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ void setMediaPlayerProxy(WebMediaPlayerProxy*);
+ void setPoster(const String& url);
+ void deliverNotification(MediaPlayerProxyNotificationType);
+#endif
+
+ // engine support
+ static MediaPlayerPrivateInterface* create(MediaPlayer*);
+ static void getSupportedTypes(HashSet<String>& types);
+ static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs);
+ static bool isAvailable();
+
+ MediaPlayer* m_player;
+ float m_seekTo;
+ float m_endTime;
+ Timer<MediaPlayerPrivate> m_seekTimer;
+ MediaPlayer::NetworkState m_networkState;
+ MediaPlayer::ReadyState m_readyState;
+ unsigned m_enabledTrackCount;
+ unsigned m_totalTrackCount;
+ bool m_hasUnsupportedTracks;
+ bool m_startedPlaying;
+ bool m_isStreaming;
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ WebMediaPlayerProxy* m_proxy;
+#endif
+ };
+
+}
+
+#endif
+
+#endif
diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp
new file mode 100644
index 0000000..9673d18
--- /dev/null
+++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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.
+ */
+
+#if ENABLE(VIDEO)
+
+#include "config.h"
+#include "MediaPlayerProxy.h"
+
+#include "c_class.h"
+#include "c_instance.h"
+#include "c_runtime.h"
+#include "DocumentLoader.h"
+#include "HTMLPlugInElement.h"
+#include "HTMLVideoElement.h"
+#include "JSDOMBinding.h"
+#include "JSPluginElementFunctions.h"
+#include "MediaPlayer.h"
+#include "Node.h"
+#include "npruntime_impl.h"
+#include "PlatformString.h"
+#include "PluginView.h"
+#include "RenderPartObject.h"
+#include "RenderWidget.h"
+#include "runtime.h"
+#include <runtime/Identifier.h>
+#include "Widget.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+using namespace Bindings;
+using namespace HTMLNames;
+
+WebMediaPlayerProxy::WebMediaPlayerProxy(MediaPlayer* player)
+ : m_mediaPlayer(player)
+ , m_init(false)
+ , m_hasSentResponseToPlugin(false)
+{
+ if (!m_init)
+ initEngine();
+}
+
+WebMediaPlayerProxy::~WebMediaPlayerProxy()
+{
+ m_instance.release();
+}
+
+ScriptInstance WebMediaPlayerProxy::pluginInstance()
+{
+ if (!m_instance) {
+ RenderObject* r = element()->renderer();
+ if (!r || !r->isWidget())
+ return 0;
+
+ Frame* frame = element()->document()->frame();
+
+ RenderWidget* renderWidget = static_cast<RenderWidget*>(element()->renderer());
+ if (renderWidget && renderWidget->widget())
+ m_instance = frame->script()->createScriptInstanceForWidget(renderWidget->widget());
+ }
+
+ return m_instance;
+}
+
+void WebMediaPlayerProxy::load(const String& url)
+{
+ if (!m_init)
+ initEngine();
+ if (m_init)
+ invokeMethod("play");
+}
+
+void WebMediaPlayerProxy::initEngine()
+{
+ HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient());
+ String url = element->initialURL();
+
+ if (url.isEmpty())
+ return;
+
+ Frame* frame = element->document()->frame();
+ Vector<String> paramNames;
+ Vector<String> paramValues;
+ String serviceType;
+
+ // add all attributes set on the embed object
+ if (NamedNodeMap* attributes = element->attributes()) {
+ for (unsigned i = 0; i < attributes->length(); ++i) {
+ Attribute* it = attributes->attributeItem(i);
+ paramNames.append(it->name().localName().string());
+ paramValues.append(it->value().string());
+ }
+ }
+ serviceType = "application/x-mplayer2";
+ frame->loader()->requestObject(static_cast<RenderPartObject*>(element->renderer()), url, nullAtom, serviceType, paramNames, paramValues);
+ m_init = true;
+
+}
+
+HTMLMediaElement* WebMediaPlayerProxy::element()
+{
+ return static_cast<HTMLMediaElement*>(m_mediaPlayer->mediaPlayerClient());
+
+}
+
+void WebMediaPlayerProxy::invokeMethod(const String& methodName)
+{
+ Frame* frame = element()->document()->frame();
+ RootObject *root = frame->script()->bindingRootObject();
+ if (!root)
+ return;
+ ExecState *exec = root->globalObject()->globalExec();
+ Instance* instance = pluginInstance().get();
+ if (!instance)
+ return;
+
+ instance->begin();
+ Class *aClass = instance->getClass();
+ Identifier iden(exec, methodName);
+ MethodList methodList = aClass->methodsNamed(iden, instance);
+ ArgList args;
+ instance->invokeMethod(exec, methodList , args);
+ instance->end();
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.h b/WebCore/platform/graphics/wince/MediaPlayerProxy.h
new file mode 100644
index 0000000..05f9b21
--- /dev/null
+++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Torch Mobile, 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.
+ */
+
+
+#ifndef MediaPlayerProxy_h
+#define MediaPlayerProxy_h
+
+#if ENABLE(VIDEO)
+
+#include "ScriptInstance.h"
+
+namespace WebCore {
+
+ class IntRect;
+ class IntSize;
+ class String;
+ class MediaPlayer;
+ class PluginView;
+ class HTMLMediaElement;
+
+ enum MediaPlayerProxyNotificationType {
+ MediaPlayerNotificationPlayPauseButtonPressed,
+ Idle,
+ Loading,
+ Loaded,
+ FormatError,
+ NetworkError,
+ DecodeError
+ };
+
+ class WebMediaPlayerProxy {
+ public:
+ WebMediaPlayerProxy(MediaPlayer* player);
+ ~WebMediaPlayerProxy();
+
+ MediaPlayer* mediaPlayer() {return m_mediaPlayer;}
+ void initEngine();
+ void load(const String& url);
+ HTMLMediaElement* element();
+ void invokeMethod(const String& methodName);
+ ScriptInstance pluginInstance();
+
+ private:
+ MediaPlayer* m_mediaPlayer;
+ bool m_init;
+ WebCore::PluginView* m_pluginView;
+ bool m_hasSentResponseToPlugin;
+ ScriptInstance m_instance;
+ };
+
+}
+#endif // ENABLE(VIDEO)
+
+#endif
diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWince.cpp
new file mode 100644
index 0000000..7589ccb
--- /dev/null
+++ b/WebCore/platform/graphics/wince/PathWince.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, 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.
+ */
+
+#include "config.h"
+#include "Path.h"
+
+#include "FloatRect.h"
+#include "NotImplemented.h"
+#include "PlatformPathWince.h"
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(new PlatformPath())
+{
+}
+
+Path::Path(const Path& other)
+ : m_path(new PlatformPath(*other.m_path))
+{
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path& Path::operator=(const Path& other)
+{
+ if (&other != this) {
+ delete m_path;
+ m_path = new PlatformPath(*other.m_path);
+ }
+ return *this;
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ return m_path->contains(point, rule);
+}
+
+void Path::translate(const FloatSize& size)
+{
+ m_path->translate(size);
+}
+
+FloatRect Path::boundingRect() const
+{
+ return m_path->boundingRect();
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ m_path->moveTo(point);
+}
+
+void Path::addLineTo(const FloatPoint& point)
+{
+ m_path->addLineTo(point);
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ m_path->addQuadCurveTo(cp, p);
+}
+
+void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ m_path->addBezierCurveTo(cp1, cp2, p);
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ m_path->addArcTo(p1, p2, radius);
+}
+
+void Path::closeSubpath()
+{
+ m_path->closeSubpath();
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
+{
+ m_path->addEllipse(p, r, r, sar, ear, anticlockwise);
+}
+
+void Path::addRect(const FloatRect& r)
+{
+ m_path->addRect(r);
+}
+
+void Path::addEllipse(const FloatRect& r)
+{
+ m_path->addEllipse(r);
+}
+
+void Path::clear()
+{
+ m_path->clear();
+}
+
+bool Path::isEmpty() const
+{
+ return m_path->isEmpty();
+}
+
+String Path::debugString() const
+{
+ return m_path->debugString();
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ m_path->apply(info, function);
+}
+
+void Path::transform(const TransformationMatrix& t)
+{
+ m_path->transform(t);
+}
+
+FloatRect Path::strokeBoundingRect(StrokeStyleApplier *)
+{
+ notImplemented();
+ return FloatRect();
+}
+
+bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const
+{
+ notImplemented();
+ return false;
+}
+
+bool Path::hasCurrentPoint() const
+{
+ // Not sure if this is correct. At the meantime, we do what other ports
+ // do.
+ // See https://bugs.webkit.org/show_bug.cgi?id=27266,
+ // https://bugs.webkit.org/show_bug.cgi?id=27187, and
+ // http://trac.webkit.org/changeset/45873
+ return !isEmpty();
+}
+
+}
diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.cpp b/WebCore/platform/graphics/wince/PlatformPathWince.cpp
new file mode 100644
index 0000000..66fad50
--- /dev/null
+++ b/WebCore/platform/graphics/wince/PlatformPathWince.cpp
@@ -0,0 +1,810 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, 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.
+ */
+
+#include "config.h"
+#include "PlatformPathWince.h"
+
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "Path.h"
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+#include "WinceGraphicsExtras.h"
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+
+#include <windows.h>
+
+namespace WebCore {
+
+// Implemented in GraphicsContextWince.cpp
+void getEllipsePointByAngle(double angle, double a, double b, float& x, float& y);
+
+static void quadCurve(int segments, Vector<PathPoint>& pts, const PathPoint* control)
+{
+ const float step = 1.0 / segments;
+ register float tA = 0.0;
+ register float tB = 1.0;
+
+ float c1x = control[0].x();
+ float c1y = control[0].y();
+ float c2x = control[1].x();
+ float c2y = control[1].y();
+ float c3x = control[2].x();
+ float c3y = control[2].y();
+
+ const int offset = pts.size();
+ pts.resize(offset + segments);
+ PathPoint pp;
+ pp.m_x = c1x;
+ pp.m_y = c1y;
+
+ for (int i = 1; i < segments; ++i) {
+ tA += step;
+ tB -= step;
+
+ const float a = tB * tB;
+ const float b = 2.0 * tA * tB;
+ const float c = tA * tA;
+
+ pp.m_x = c1x * a + c2x * b + c3x * c;
+ pp.m_y = c1y * a + c2y * b + c3y * c;
+
+ pts[offset + i - 1] = pp;
+ }
+
+ pp.m_x = c3x;
+ pp.m_y = c3y;
+ pts[offset + segments - 1] = pp;
+}
+
+static inline void bezier(int segments, Vector<PathPoint>& pts, const PathPoint* control)
+{
+ const float step = 1.0 / segments;
+ register float tA = 0.0;
+ register float tB = 1.0;
+
+ float c1x = control[0].x();
+ float c1y = control[0].y();
+ float c2x = control[1].x();
+ float c2y = control[1].y();
+ float c3x = control[2].x();
+ float c3y = control[2].y();
+ float c4x = control[3].x();
+ float c4y = control[3].y();
+
+ const int offset = pts.size();
+ pts.resize(offset + segments);
+ PathPoint pp;
+ pp.m_x = c1x;
+ pp.m_y = c1y;
+
+ for (int i = 1; i < segments; ++i) {
+ tA += step;
+ tB -= step;
+ const float tAsq = tA * tA;
+ const float tBsq = tB * tB;
+
+ const float a = tBsq * tB;
+ const float b = 3.0 * tA * tBsq;
+ const float c = 3.0 * tB * tAsq;
+ const float d = tAsq * tA;
+
+ pp.m_x = c1x * a + c2x * b + c3x * c + c4x * d;
+ pp.m_y = c1y * a + c2y * b + c3y * c + c4y * d;
+
+ pts[offset + i - 1] = pp;
+ }
+
+ pp.m_x = c4x;
+ pp.m_y = c4y;
+ pts[offset + segments - 1] = pp;
+}
+
+static bool containsPoint(const FloatRect& r, const FloatPoint& p)
+{
+ return p.x() >= r.x() && p.y() >= r.y() && p.x() < r.right() && p.y() < r.bottom();
+}
+
+static void normalizeAngle(float& angle)
+{
+ angle = fmod(angle, 2 * piFloat);
+ if (angle < 0)
+ angle += 2 * piFloat;
+ if (angle < 0.00001f)
+ angle = 0;
+}
+
+static void transformArcPoint(float& x, float& y, const FloatPoint& c)
+{
+ x += c.x();
+ y += c.y();
+}
+
+static void inflateRectToContainPoint(FloatRect& r, float x, float y)
+{
+ if (r.isEmpty()) {
+ r.setX(x);
+ r.setY(y);
+ r.setSize(FloatSize(1, 1));
+ return;
+ }
+ if (x < r.x()) {
+ r.setWidth(r.right() - x);
+ r.setX(x);
+ } else {
+ float w = x - r.x() + 1;
+ if (w > r.width())
+ r.setWidth(w);
+ }
+ if (y < r.y()) {
+ r.setHeight(r.bottom() - y);
+ r.setY(y);
+ } else {
+ float h = y - r.y() + 1;
+ if (h > r.height())
+ r.setHeight(h);
+ }
+}
+
+// return 0-based value: 0 - first Quadrant ( 0 - 90 degree)
+static inline int quadrant(const PathPoint& point, const PathPoint& origin)
+{
+ return point.m_x < origin.m_x ?
+ (point.m_y < origin.m_y ? 2 : 1)
+ : (point.m_y < origin.m_y ? 3 : 0);
+}
+
+static inline bool isQuadrantOnLeft(int q) { return q == 1 || q == 2; }
+static inline bool isQuadrantOnRight(int q) { return q == 0 || q == 3; }
+static inline bool isQuadrantOnTop(int q) { return q == 2 || q == 3; }
+static inline bool isQuadrantOnBottom(int q) { return q == 0 || q == 1; }
+
+static inline int nextQuadrant(int q) { return q == 3 ? 0 : q + 1; }
+static inline int quadrantDiff(int q1, int q2)
+{
+ int d = q1 - q2;
+ while (d < 0)
+ d += 4;
+ return d;
+}
+
+struct PathVector {
+ float m_x;
+ float m_y;
+
+ PathVector() : m_x(0), m_y(0) {}
+ PathVector(float x, float y) : m_x(x), m_y(y) {}
+ double angle() const { return atan2(m_y, m_x); }
+ operator double () const { return angle(); }
+ double length() const { return _hypot(m_x, m_y); }
+};
+
+PathVector operator-(const PathPoint& p1, const PathPoint& p2)
+{
+ return PathVector(p1.m_x - p2.m_x, p1.m_y - p2.m_y);
+}
+
+static void addArcPoint(PathPolygon& poly, const PathPoint& center, const PathPoint& radius, double angle)
+{
+ PathPoint p;
+ getEllipsePointByAngle(angle, radius.m_x, radius.m_y, p.m_x, p.m_y);
+ transformArcPoint(p.m_x, p.m_y, center);
+ if (poly.isEmpty() || poly.last() != p)
+ poly.append(p);
+}
+
+static void addArcPoints(PathPolygon& poly, const PlatformPathElement::ArcTo& data)
+{
+ const PathPoint& startPoint = poly.last();
+ double curAngle = startPoint - data.m_center;
+ double endAngle = data.m_end - data.m_center;
+ double angleStep = 2. / std::max(data.m_radius.m_x, data.m_radius.m_y);
+ if (data.m_clockwise) {
+ if (endAngle <= curAngle || startPoint == data.m_end)
+ endAngle += 2 * piDouble;
+ } else {
+ angleStep = -angleStep;
+ if (endAngle >= curAngle || startPoint == data.m_end)
+ endAngle -= 2 * piDouble;
+ }
+
+ for (curAngle += angleStep; data.m_clockwise ? curAngle < endAngle : curAngle > endAngle; curAngle += angleStep)
+ addArcPoint(poly, data.m_center, data.m_radius, curAngle);
+
+ if (poly.isEmpty() || poly.last() != data.m_end)
+ poly.append(data.m_end);
+}
+
+static void drawPolygons(HDC dc, const Vector<PathPolygon>& polygons, bool fill, const TransformationMatrix* transformation)
+{
+ MemoryAllocationCanFail canFail;
+ for (Vector<PathPolygon>::const_iterator i = polygons.begin(); i != polygons.end(); ++i) {
+ int npoints = i->size();
+ if (!npoints)
+ continue;
+
+ POINT* winPoints = 0;
+ if (fill) {
+ if (npoints > 2)
+ winPoints = new POINT[npoints + 1];
+ } else
+ winPoints = new POINT[npoints];
+
+ if (winPoints) {
+ if (transformation) {
+ for (int i2 = 0; i2 < npoints; ++i2) {
+ FloatPoint trPoint = transformation->mapPoint(i->at(i2));
+ winPoints[i2].x = stableRound(trPoint.x());
+ winPoints[i2].y = stableRound(trPoint.y());
+ }
+ } else {
+ for (int i2 = 0; i2 < npoints; ++i2) {
+ winPoints[i2].x = stableRound(i->at(i2).x());
+ winPoints[i2].y = stableRound(i->at(i2).y());
+ }
+ }
+
+ if (fill && winPoints[npoints - 1] != winPoints[0]) {
+ winPoints[npoints].x = winPoints[0].x;
+ winPoints[npoints].y = winPoints[0].y;
+ ++npoints;
+ }
+
+ if (fill)
+ ::Polygon(dc, winPoints, npoints);
+ else
+ ::Polyline(dc, winPoints, npoints);
+ delete[] winPoints;
+ }
+ }
+}
+
+
+int PlatformPathElement::numControlPoints() const
+{
+ switch (m_type) {
+ case PathMoveTo:
+ case PathLineTo:
+ return 1;
+ case PathQuadCurveTo:
+ case PathArcTo:
+ return 2;
+ case PathBezierCurveTo:
+ return 3;
+ default:
+ ASSERT(m_type == PathCloseSubpath);
+ return 0;
+ }
+}
+
+int PlatformPathElement::numPoints() const
+{
+ switch (m_type) {
+ case PathMoveTo:
+ case PathLineTo:
+ case PathArcTo:
+ return 1;
+ case PathQuadCurveTo:
+ return 2;
+ case PathBezierCurveTo:
+ return 3;
+ default:
+ ASSERT(m_type == PathCloseSubpath);
+ return 0;
+ }
+}
+
+void PathPolygon::move(const FloatSize& offset)
+{
+ for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i)
+ i->move(offset);
+}
+
+void PathPolygon::transform(const TransformationMatrix& t)
+{
+ for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i)
+ *i = t.mapPoint(*i);
+}
+
+bool PathPolygon::contains(const FloatPoint& point) const
+{
+ if (size() < 3)
+ return false;
+
+ // Test intersections between the polygon and the vertical line: x = point.x()
+
+ int intersected = 0;
+ const PathPoint* point1 = &last();
+ Vector<PathPoint>::const_iterator last = end();
+ // wasNegative: -1 means unknown, 0 means false, 1 means true.
+ int wasNegative = -1;
+ for (Vector<PathPoint>::const_iterator i = begin(); i != last; ++i) {
+ const PathPoint& point2 = *i;
+ if (point1->x() != point.x()) {
+ if (point2.x() == point.x()) {
+ // We are getting on the vertical line
+ wasNegative = point1->x() < point.x() ? 1 : 0;
+ } else if (point2.x() < point.x() != point1->x() < point.x()) {
+ float y = (point2.y() - point1->y()) / (point2.x() - point1->x()) * (point.x() - point1->x()) + point1->y();
+ if (y >= point.y())
+ ++intersected;
+ }
+ } else {
+ // We were on the vertical line
+
+ // handle special case
+ if (point1->y() == point.y())
+ return true;
+
+ if (point1->y() > point.y()) {
+ if (point2.x() == point.x()) {
+ // see if the point is on this segment
+ if (point2.y() <= point.y())
+ return true;
+
+ // We are still on the line
+ } else {
+ // We are leaving the line now.
+ // We have to get back to see which side we come from. If we come from
+ // the same side we are leaving, no intersection should be counted
+ if (wasNegative < 0) {
+ Vector<PathPoint>::const_iterator jLast = i;
+ Vector<PathPoint>::const_iterator j = i;
+ do {
+ if (j == begin())
+ j = last;
+ else
+ --j;
+ if (j->x() != point.x()) {
+ if (j->x() > point.x())
+ wasNegative = 0;
+ else
+ wasNegative = 1;
+ break;
+ }
+ } while (j != jLast);
+
+ if (wasNegative < 0)
+ return false;
+ }
+ if (wasNegative ? point2.x() > point.x() : point2.x() < point.x())
+ ++intersected;
+ }
+ } else if (point2.x() == point.x() && point2.y() >= point.y())
+ return true;
+ }
+ point1 = &point2;
+ }
+
+ return intersected & 1;
+}
+
+void PlatformPathElement::move(const FloatSize& offset)
+{
+ int n = numControlPoints();
+ for (int i = 0; i < n; ++i)
+ m_data.m_points[i].move(offset);
+}
+
+void PlatformPathElement::transform(const TransformationMatrix& t)
+{
+ int n = numControlPoints();
+ for (int i = 0; i < n; ++i) {
+ FloatPoint p = t.mapPoint(m_data.m_points[i]);
+ m_data.m_points[i].set(p.x(), p.y());
+ }
+}
+
+void PlatformPathElement::inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const
+{
+ if (m_type == PathArcTo) {
+ const ArcTo& data = m_data.m_arcToData;
+ PathPoint startPoint;
+ startPoint = lastPoint;
+ PathPoint endPoint = data.m_end;
+ if (!data.m_clockwise)
+ std::swap(startPoint, endPoint);
+
+ int q0 = quadrant(startPoint, data.m_center);
+ int q1 = quadrant(endPoint, data.m_center);
+ bool containsExtremes[4] = { false }; // bottom, left, top, right
+ static const PathPoint extremeVectors[4] = { { 0, 1 }, { -1, 0 }, { 0, -1 }, { 1, 0 } };
+ if (q0 == q1) {
+ if (startPoint.m_x == endPoint.m_x || isQuadrantOnBottom(q0) != startPoint.m_x > endPoint.m_x) {
+ for (int i = 0; i < 4; ++i)
+ containsExtremes[i] = true;
+ }
+ } else {
+ int extreme = q0;
+ int diff = quadrantDiff(q1, q0);
+ for (int i = 0; i < diff; ++i) {
+ containsExtremes[extreme] = true;
+ extreme = nextQuadrant(extreme);
+ }
+ }
+
+ inflateRectToContainPoint(r, startPoint.m_x, startPoint.m_y);
+ inflateRectToContainPoint(r, endPoint.m_x, endPoint.m_y);
+ for (int i = 0; i < 4; ++i) {
+ if (containsExtremes[i])
+ inflateRectToContainPoint(r, data.m_center.m_x + data.m_radius.m_x * extremeVectors[i].m_x, data.m_center.m_y + data.m_radius.m_y * extremeVectors[i].m_y);
+ }
+ } else {
+ int n = numPoints();
+ for (int i = 0; i < n; ++i)
+ inflateRectToContainPoint(r, m_data.m_points[i].m_x, m_data.m_points[i].m_y);
+ }
+}
+
+PathElementType PlatformPathElement::type() const
+{
+ switch (m_type) {
+ case PathMoveTo:
+ return PathElementMoveToPoint;
+ case PathLineTo:
+ return PathElementAddLineToPoint;
+ case PathArcTo:
+ // FIXME: there's no arcTo type for PathElement
+ return PathElementAddLineToPoint;
+ // return PathElementAddQuadCurveToPoint;
+ case PathQuadCurveTo:
+ return PathElementAddQuadCurveToPoint;
+ case PathBezierCurveTo:
+ return PathElementAddCurveToPoint;
+ default:
+ ASSERT(m_type == PathCloseSubpath);
+ return PathElementCloseSubpath;
+ }
+}
+
+PlatformPath::PlatformPath()
+ : m_penLifted(true)
+{
+ m_currentPoint.clear();
+}
+
+void PlatformPath::ensureSubpath()
+{
+ if (m_penLifted) {
+ m_penLifted = false;
+ m_subpaths.append(PathPolygon());
+ m_subpaths.last().append(m_currentPoint);
+ } else
+ ASSERT(!m_subpaths.isEmpty());
+}
+
+void PlatformPath::addToSubpath(const PlatformPathElement& e)
+{
+ if (e.platformType() == PlatformPathElement::PathMoveTo) {
+ m_penLifted = true;
+ m_currentPoint = e.pointAt(0);
+ } else if (e.platformType() == PlatformPathElement::PathCloseSubpath) {
+ m_penLifted = true;
+ if (!m_subpaths.isEmpty()) {
+ if (m_currentPoint != m_subpaths.last()[0]) {
+ // According to W3C, we have to draw a line from current point to the initial point
+ m_subpaths.last().append(m_subpaths.last()[0]);
+ m_currentPoint = m_subpaths.last()[0];
+ }
+ } else
+ m_currentPoint.clear();
+ } else {
+ ensureSubpath();
+ switch (e.platformType()) {
+ case PlatformPathElement::PathLineTo:
+ m_subpaths.last().append(e.pointAt(0));
+ break;
+ case PlatformPathElement::PathArcTo:
+ addArcPoints(m_subpaths.last(), e.arcTo());
+ break;
+ case PlatformPathElement::PathQuadCurveTo:
+ {
+ PathPoint control[] = {
+ m_currentPoint,
+ e.pointAt(0),
+ e.pointAt(1),
+ };
+ // FIXME: magic number?
+ quadCurve(50, m_subpaths.last(), control);
+ }
+ break;
+ case PlatformPathElement::PathBezierCurveTo:
+ {
+ PathPoint control[] = {
+ m_currentPoint,
+ e.pointAt(0),
+ e.pointAt(1),
+ e.pointAt(2),
+ };
+ // FIXME: magic number?
+ bezier(100, m_subpaths.last(), control);
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ m_currentPoint = m_subpaths.last().last();
+ }
+}
+
+void PlatformPath::append(const PlatformPathElement& e)
+{
+ e.inflateRectToContainMe(m_boundingRect, lastPoint());
+ addToSubpath(e);
+ m_elements.append(e);
+}
+
+void PlatformPath::append(const PlatformPath& p)
+{
+ const PlatformPathElements& e = p.elements();
+ for (PlatformPathElements::const_iterator it(e.begin()); it != e.end(); ++it) {
+ addToSubpath(*it);
+ it->inflateRectToContainMe(m_boundingRect, lastPoint());
+ m_elements.append(*it);
+ }
+}
+
+void PlatformPath::clear()
+{
+ m_elements.clear();
+ m_boundingRect = FloatRect();
+ m_subpaths.clear();
+ m_currentPoint.clear();
+ m_penLifted = true;
+}
+
+void PlatformPath::strokePath(HDC dc, const TransformationMatrix* transformation) const
+{
+ drawPolygons(dc, m_subpaths, false, transformation);
+}
+
+void PlatformPath::fillPath(HDC dc, const TransformationMatrix* transformation) const
+{
+ HGDIOBJ oldPen = SelectObject(dc, GetStockObject(NULL_PEN));
+ drawPolygons(dc, m_subpaths, true, transformation);
+ SelectObject(dc, oldPen);
+}
+
+void PlatformPath::translate(const FloatSize& size)
+{
+ for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it)
+ it->move(size);
+
+ m_boundingRect.move(size);
+ for (Vector<PathPolygon>::iterator it = m_subpaths.begin(); it != m_subpaths.end(); ++it)
+ it->move(size);
+}
+
+void PlatformPath::transform(const TransformationMatrix& t)
+{
+ for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it)
+ it->transform(t);
+
+ m_boundingRect = t.mapRect(m_boundingRect);
+ for (Vector<PathPolygon>::iterator it = m_subpaths.begin(); it != m_subpaths.end(); ++it)
+ it->transform(t);
+}
+
+bool PlatformPath::contains(const FloatPoint& point, WindRule rule) const
+{
+ // optimization: check the bounding rect first
+ if (!containsPoint(m_boundingRect, point))
+ return false;
+
+ for (Vector<PathPolygon>::const_iterator i = m_subpaths.begin(); i != m_subpaths.end(); ++i) {
+ if (i->contains(point))
+ return true;
+ }
+
+ return false;
+}
+
+void PlatformPath::moveTo(const FloatPoint& point)
+{
+ PlatformPathElement::MoveTo data = { { point.x(), point.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addLineTo(const FloatPoint& point)
+{
+ PlatformPathElement::LineTo data = { { point.x(), point.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ PlatformPathElement::QuadCurveTo data = { { cp.x(), cp.y() }, { p.x(), p.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ PlatformPathElement::BezierCurveTo data = { { cp1.x(), cp1.y() }, { cp2.x(), cp2.y() }, { p.x(), p.y() } };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::addArcTo(const FloatPoint& fp1, const FloatPoint& fp2, float radius)
+{
+ const PathPoint& p0 = m_currentPoint;
+ PathPoint p1;
+ p1 = fp1;
+ PathPoint p2;
+ p2 = fp2;
+ if (!radius || p0 == p1 || p1 == p2) {
+ addLineTo(p1);
+ return;
+ }
+
+ PathVector v01 = p0 - p1;
+ PathVector v21 = p2 - p1;
+
+ // sin(A - B) = sin(A) * cos(B) - sin(B) * cos(A)
+ double cross = v01.m_x * v21.m_y - v01.m_y * v21.m_x;
+
+ if (fabs(cross) < 1E-10) {
+ // on one line
+ addLineTo(p1);
+ return;
+ }
+
+ double d01 = v01.length();
+ double d21 = v21.length();
+ double angle = (piDouble - abs(asin(cross / (d01 * d21)))) * 0.5;
+ double span = radius * tan(angle);
+ double rate = span / d01;
+ PathPoint startPoint;
+ startPoint.m_x = p1.m_x + v01.m_x * rate;
+ startPoint.m_y = p1.m_y + v01.m_y * rate;
+
+ addLineTo(startPoint);
+
+ PathPoint endPoint;
+ rate = span / d21;
+ endPoint.m_x = p1.m_x + v21.m_x * rate;
+ endPoint.m_y = p1.m_y + v21.m_y * rate;
+
+ PathPoint midPoint;
+ midPoint.m_x = (startPoint.m_x + endPoint.m_x) * 0.5;
+ midPoint.m_y = (startPoint.m_y + endPoint.m_y) * 0.5;
+
+ PathVector vm1 = midPoint - p1;
+ double dm1 = vm1.length();
+ double d = _hypot(radius, span);
+
+ PathPoint centerPoint;
+ rate = d / dm1;
+ centerPoint.m_x = p1.m_x + vm1.m_x * rate;
+ centerPoint.m_y = p1.m_y + vm1.m_y * rate;
+
+ PlatformPathElement::ArcTo data = {
+ endPoint,
+ centerPoint,
+ { radius, radius },
+ cross < 0
+ };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+void PlatformPath::closeSubpath()
+{
+ PlatformPathElement pe;
+ append(pe);
+}
+
+// add a circular arc centred at p with radius r from start angle sar (radians) to end angle ear
+void PlatformPath::addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise)
+{
+ float startX, startY, endX, endY;
+
+ normalizeAngle(sar);
+ normalizeAngle(ear);
+
+ getEllipsePointByAngle(sar, a, b, startX, startY);
+ getEllipsePointByAngle(ear, a, b, endX, endY);
+
+ transformArcPoint(startX, startY, p);
+ transformArcPoint(endX, endY, p);
+
+ FloatPoint start(startX, startY);
+ moveTo(start);
+
+ PlatformPathElement::ArcTo data = { { endX, endY }, { p.x(), p.y() }, { a, b }, !anticlockwise };
+ PlatformPathElement pe(data);
+ append(pe);
+}
+
+
+void PlatformPath::addRect(const FloatRect& r)
+{
+ moveTo(r.location());
+
+ float right = r.right() - 1;
+ float bottom = r.bottom() - 1;
+ addLineTo(FloatPoint(right, r.y()));
+ addLineTo(FloatPoint(right, bottom));
+ addLineTo(FloatPoint(r.x(), bottom));
+ addLineTo(r.location());
+}
+
+void PlatformPath::addEllipse(const FloatRect& r)
+{
+ FloatSize radius(r.width() * 0.5, r.height() * 0.5);
+ addEllipse(r.location() + radius, radius.width(), radius.height(), 0, 0, true);
+}
+
+String PlatformPath::debugString() const
+{
+ String ret;
+ for (PlatformPathElements::const_iterator i(m_elements.begin()); i != m_elements.end(); ++i) {
+ switch (i->platformType()) {
+ case PlatformPathElement::PathMoveTo:
+ case PlatformPathElement::PathLineTo:
+ ret += String::format("M %f %f\n", i->pointAt(0).m_x, i->pointAt(0).m_y);
+ break;
+ case PlatformPathElement::PathArcTo:
+ ret += String::format("A %f %f %f %f %f %f %c\n"
+ , i->arcTo().m_end.m_x, i->arcTo().m_end.m_y
+ , i->arcTo().m_center.m_x, i->arcTo().m_center.m_y
+ , i->arcTo().m_radius.m_x, i->arcTo().m_radius.m_y
+ , i->arcTo().m_clockwise? 'Y' : 'N');
+ break;
+ case PlatformPathElement::PathQuadCurveTo:
+ ret += String::format("Q %f %f %f %f\n"
+ , i->pointAt(0).m_x, i->pointAt(0).m_y
+ , i->pointAt(1).m_x, i->pointAt(1).m_y);
+ break;
+ case PlatformPathElement::PathBezierCurveTo:
+ ret += String::format("B %f %f %f %f %f %f\n"
+ , i->pointAt(0).m_x, i->pointAt(0).m_y
+ , i->pointAt(1).m_x, i->pointAt(1).m_y
+ , i->pointAt(2).m_x, i->pointAt(2).m_y);
+ break;
+ default:
+ ASSERT(i->platformType() == PlatformPathElement::PathCloseSubpath);
+ ret += "S\n";
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void PlatformPath::apply(void* info, PathApplierFunction function) const
+{
+ PathElement pelement;
+ FloatPoint points[3];
+ pelement.points = points;
+
+ for (PlatformPathElements::const_iterator it(m_elements.begin()); it != m_elements.end(); ++it) {
+ pelement.type = it->type();
+ int n = it->numPoints();
+ for (int i = 0; i < n; ++i)
+ points[i] = it->pointAt(i);
+ function(info, &pelement);
+ }
+}
+
+} // namespace Webcore
diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWince.h
new file mode 100644
index 0000000..fca00a7
--- /dev/null
+++ b/WebCore/platform/graphics/wince/PlatformPathWince.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, 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.
+ */
+
+#ifndef PlatformPathWince_h
+#define PlatformPathWince_h
+
+namespace WebCore {
+
+ class GraphicsContext;
+
+ struct PathPoint {
+ float m_x;
+ float m_y;
+ const float& x() const { return m_x; }
+ const float& y() const { return m_y; }
+ void set(float x, float y)
+ {
+ m_x = x;
+ m_y = y;
+ };
+ operator FloatPoint() const { return FloatPoint(m_x, m_y); }
+ void move(const FloatSize& offset)
+ {
+ m_x += offset.width();
+ m_y += offset.height();
+ }
+ PathPoint& operator=(const FloatPoint& p)
+ {
+ m_x = p.x();
+ m_y = p.y();
+ return *this;
+ }
+ void clear() { m_x = m_y = 0; }
+ };
+
+ struct PathPolygon: public Vector<PathPoint> {
+ void move(const FloatSize& offset);
+ void transform(const TransformationMatrix& t);
+ bool contains(const FloatPoint& point) const;
+ };
+
+ class PlatformPathElement {
+ public:
+ enum PlaformPathElementType {
+ PathMoveTo,
+ PathLineTo,
+ PathArcTo,
+ PathQuadCurveTo,
+ PathBezierCurveTo,
+ PathCloseSubpath,
+ };
+
+ struct MoveTo {
+ PathPoint m_end;
+ };
+
+ struct LineTo {
+ PathPoint m_end;
+ };
+
+ struct ArcTo {
+ PathPoint m_end;
+ PathPoint m_center;
+ PathPoint m_radius;
+ bool m_clockwise;
+ };
+
+ struct QuadCurveTo {
+ PathPoint m_point0;
+ PathPoint m_point1;
+ };
+
+ struct BezierCurveTo {
+ PathPoint m_point0;
+ PathPoint m_point1;
+ PathPoint m_point2;
+ };
+
+ PlatformPathElement(): m_type(PathCloseSubpath) { m_data.m_points[0].set(0, 0); }
+ PlatformPathElement(const MoveTo& data): m_type(PathMoveTo) { m_data.m_moveToData = data; }
+ PlatformPathElement(const LineTo& data): m_type(PathLineTo) { m_data.m_lineToData = data; }
+ PlatformPathElement(const ArcTo& data): m_type(PathArcTo) { m_data.m_arcToData = data; }
+ PlatformPathElement(const QuadCurveTo& data): m_type(PathQuadCurveTo) { m_data.m_quadCurveToData = data; }
+ PlatformPathElement(const BezierCurveTo& data): m_type(PathBezierCurveTo) { m_data.m_bezierCurveToData = data; }
+
+ const MoveTo& moveTo() const { return m_data.m_moveToData; }
+ const LineTo& lineTo() const { return m_data.m_lineToData; }
+ const ArcTo& arcTo() const { return m_data.m_arcToData; }
+ const QuadCurveTo& quadCurveTo() const { return m_data.m_quadCurveToData; }
+ const BezierCurveTo& bezierCurveTo() const { return m_data.m_bezierCurveToData; }
+ const PathPoint& lastPoint() const
+ {
+ int n = numPoints();
+ return n > 1 ? m_data.m_points[n - 1] : m_data.m_points[0];
+ }
+ const PathPoint& pointAt(int index) const { return m_data.m_points[index]; }
+ int numPoints() const;
+ int numControlPoints() const;
+ void move(const FloatSize& offset);
+ void transform(const TransformationMatrix& t);
+ PathElementType type() const;
+ PlaformPathElementType platformType() const { return m_type; }
+ void inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const;
+
+ private:
+ PlaformPathElementType m_type;
+ union {
+ MoveTo m_moveToData;
+ LineTo m_lineToData;
+ ArcTo m_arcToData;
+ QuadCurveTo m_quadCurveToData;
+ BezierCurveTo m_bezierCurveToData;
+ PathPoint m_points[4];
+ } m_data;
+ };
+
+ typedef Vector<PlatformPathElement> PlatformPathElements;
+
+ class PlatformPath {
+ public:
+ PlatformPath();
+ const PlatformPathElements& elements() const { return m_elements; }
+ void append(const PlatformPathElement& e);
+ void append(const PlatformPath& p);
+ void clear();
+ bool isEmpty() const { return m_elements.isEmpty(); }
+
+ void strokePath(HDC, const TransformationMatrix* tr) const;
+ void fillPath(HDC, const TransformationMatrix* tr) const;
+ FloatPoint lastPoint() const { return m_elements.isEmpty() ? FloatPoint(0, 0) : m_elements.last().lastPoint(); }
+
+ const FloatRect& boundingRect() const { return m_boundingRect; }
+ bool contains(const FloatPoint& point, WindRule rule) const;
+ void translate(const FloatSize& size);
+ void transform(const TransformationMatrix& t);
+
+ void moveTo(const FloatPoint&);
+ void addLineTo(const FloatPoint&);
+ void addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& point);
+ void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint&);
+ void addArcTo(const FloatPoint&, const FloatPoint&, float radius);
+ void closeSubpath();
+ void addEllipse(const FloatPoint& p, float a, float b, float sar, float ear, bool anticlockwise);
+ void addRect(const FloatRect& r);
+ void addEllipse(const FloatRect& r);
+ String debugString() const;
+ void apply(void* info, PathApplierFunction function) const;
+
+ private:
+ void ensureSubpath();
+ void addToSubpath(const PlatformPathElement& e);
+
+ PlatformPathElements m_elements;
+ FloatRect m_boundingRect;
+ Vector<PathPolygon> m_subpaths;
+ PathPoint m_currentPoint;
+ bool m_penLifted;
+ };
+
+}
+
+#endif // PlatformPathWince_h
diff --git a/WebCore/platform/graphics/wince/WinceGraphicsExtras.h b/WebCore/platform/graphics/wince/WinceGraphicsExtras.h
new file mode 100644
index 0000000..2a6fae1
--- /dev/null
+++ b/WebCore/platform/graphics/wince/WinceGraphicsExtras.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile, 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.
+ */
+
+#ifndef WinceGraphicsExtras_h
+#define WinceGraphicsExtras_h
+
+// This file is used to contain small utilities used by WINCE graphics code.
+
+namespace WebCore {
+ // Always round to same direction. 0.5 is rounded to 1,
+ // and -0.5 (0.5 - 1) is rounded to 0 (1 - 1), so that it
+ // is consistent when transformation shifts.
+ static inline int stableRound(double d)
+ {
+ if (d > 0)
+ return static_cast<int>(d + 0.5);
+
+ int i = static_cast<int>(d);
+ return i - d > 0.5 ? i - 1 : i;
+ }
+}
+
+#endif WinceGraphicsExtras_h
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 59e388e..686fb07 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -506,4 +506,59 @@ void GraphicsContext::fillRect(const FloatRect& rect)
return;
}
+void GraphicsContext::setPlatformShadow(IntSize const&,int,Color const&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+ notImplemented();
+}
+
+void GraphicsContext::beginTransparencyLayer(float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ notImplemented();
+}
+
+void GraphicsContext::clearRect(const FloatRect&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::strokeRect(const FloatRect&, float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setLineCap(LineCap)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setLineJoin(LineJoin)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setMiterLimit(float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setAlpha(float)
+{
+ notImplemented();
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ notImplemented();
+}
+
}
diff --git a/WebCore/platform/graphics/wx/IconWx.cpp b/WebCore/platform/graphics/wx/IconWx.cpp
new file mode 100644
index 0000000..e82091e
--- /dev/null
+++ b/WebCore/platform/graphics/wx/IconWx.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 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 "Icon.h"
+
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+Icon::~Icon()
+{
+}
+
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
+{
+ notImplemented();
+ return 0;
+}
+
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
+{
+ notImplemented();
+ return 0;
+}
+
+void Icon::paint(GraphicsContext* ctx, const IntRect& rect)
+{
+ notImplemented();
+}
+
+}
+
diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index e71dbde..49f3f3b 100644
--- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -53,13 +53,24 @@ GraphicsContext* ImageBuffer::context() const
return 0;
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
notImplemented();
return 0;
}
-void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&)
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ notImplemented();
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
{
notImplemented();
}
diff --git a/WebCore/platform/graphics/wx/ImageSourceWx.cpp b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
deleted file mode 100644
index 06c165d..0000000
--- a/WebCore/platform/graphics/wx/ImageSourceWx.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Computer, Kevin Ollivier. 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 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.
- */
-
-#include "config.h"
-#include "ImageSource.h"
-
-#include "BMPImageDecoder.h"
-#include "GIFImageDecoder.h"
-#include "ICOImageDecoder.h"
-#include "JPEGImageDecoder.h"
-#include "NotImplemented.h"
-#include "PNGImageDecoder.h"
-#include "SharedBuffer.h"
-#include "XBMImageDecoder.h"
-
-#include <wx/defs.h>
-#include <wx/bitmap.h>
-#if USE(WXGC)
-#include <wx/graphics.h>
-#endif
-#include <wx/image.h>
-#include <wx/rawbmp.h>
-
-namespace WebCore {
-
-ImageDecoder* createDecoder(const SharedBuffer& data)
-{
- // We need at least 4 bytes to figure out what kind of image we're dealing with.
- int length = data.size();
- if (length < 4)
- return 0;
-
- const unsigned char* uContents = (const unsigned char*)data.data();
- const char* contents = data.data();
-
- // GIFs begin with GIF8(7 or 9).
- if (strncmp(contents, "GIF8", 4) == 0)
- return new GIFImageDecoder();
-
- // Test for PNG.
- if (uContents[0]==0x89 &&
- uContents[1]==0x50 &&
- uContents[2]==0x4E &&
- uContents[3]==0x47)
- return new PNGImageDecoder();
-
- // JPEG
- if (uContents[0]==0xFF &&
- uContents[1]==0xD8 &&
- uContents[2]==0xFF)
- return new JPEGImageDecoder();
-
- // BMP
- if (strncmp(contents, "BM", 2) == 0)
- return new BMPImageDecoder();
-
- // ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
- // CURs begin with 2-byte 0 followed by 2-byte 2.
- if (!memcmp(contents, "\000\000\001\000", 4) ||
- !memcmp(contents, "\000\000\002\000", 4))
- return new ICOImageDecoder();
-
- // XBMs require 8 bytes of info.
- if (length >= 8 && strncmp(contents, "#define ", 8) == 0)
- return new XBMImageDecoder();
-
- // Give up. We don't know what the heck this is.
- return 0;
-}
-
-ImageSource::ImageSource()
- : m_decoder(0)
-{}
-
-ImageSource::~ImageSource()
-{
- clear(true);
-}
-
-bool ImageSource::initialized() const
-{
- return m_decoder;
-}
-
-void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
-{
- // Make the decoder by sniffing the bytes.
- // This method will examine the data and instantiate an instance of the appropriate decoder plugin.
- // If insufficient bytes are available to determine the image type, no decoder plugin will be
- // made.
- if (m_decoder)
- delete m_decoder;
- m_decoder = createDecoder(*data);
- if (!m_decoder)
- return;
- m_decoder->setData(data, allDataReceived);
-}
-
-bool ImageSource::isSizeAvailable()
-{
- if (!m_decoder)
- return false;
-
- return m_decoder->isSizeAvailable();
-}
-
-IntSize ImageSource::size() const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->size();
-}
-
-IntSize ImageSource::frameSizeAtIndex(size_t index) const
-{
- if (!m_decoder)
- return IntSize();
-
- return m_decoder->frameSizeAtIndex(index);
-}
-
-int ImageSource::repetitionCount()
-{
- if (!m_decoder)
- return cAnimationNone;
-
- return m_decoder->repetitionCount();
-}
-
-String ImageSource::filenameExtension() const
-{
- notImplemented();
- return String();
-}
-
-size_t ImageSource::frameCount() const
-{
- return m_decoder ? m_decoder->frameCount() : 0;
-}
-
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
-{
- // FIXME: should we be testing the RGBA32Buffer's status as well?
- return (m_decoder && m_decoder->frameBufferAtIndex(index) != 0);
-}
-
-void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
-{
- if (!destroyAll) {
- if (m_decoder)
- m_decoder->clearFrameBufferCache(clearBeforeFrame);
- return;
- }
-
- delete m_decoder;
- m_decoder = 0;
- if (data)
- setData(data, allDataReceived);
-}
-
-NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return 0;
-
- return buffer->asNewNativeImage();
-}
-
-float ImageSource::frameDurationAtIndex(size_t index)
-{
- if (!m_decoder)
- return 0;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return 0;
-
- float duration = buffer->duration() / 1000.0f;
-
- // Follow other ports (and WinIE's) behavior to slow annoying ads that
- // specify a 0 duration.
- if (duration < 0.051f)
- return 0.100f;
- return duration;
-}
-
-bool ImageSource::frameHasAlphaAtIndex(size_t index)
-{
- if (!m_decoder || !m_decoder->supportsAlpha())
- return false;
-
- RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index);
- if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
- return false;
-
- return buffer->hasAlpha();
-}
-
-}
diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp
index b0a993e..bd129cf 100644
--- a/WebCore/platform/graphics/wx/ImageWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -31,6 +31,7 @@
#include "FloatRect.h"
#include "GraphicsContext.h"
#include "ImageObserver.h"
+#include "NotImplemented.h"
#include "TransformationMatrix.h"
#include <math.h>
@@ -45,9 +46,6 @@
#include <wx/image.h>
#include <wx/thread.h>
-// This function loads resources from WebKit
-Vector<char> loadResourceIntoArray(const char*);
-
namespace WebCore {
// this is in GraphicsContextWx.cpp
@@ -72,7 +70,9 @@ bool FrameData::clear(bool clearMetadata)
PassRefPtr<Image> Image::loadPlatformResource(const char *name)
{
- Vector<char> arr = loadResourceIntoArray(name);
+ // FIXME: We need to have some 'placeholder' graphics for things like missing
+ // plugins or broken images.
+ Vector<char> arr;
RefPtr<Image> img = BitmapImage::create();
RefPtr<SharedBuffer> buffer = SharedBuffer::create(arr.data(), arr.size());
img->setData(buffer, true);
@@ -261,4 +261,9 @@ void BitmapImage::invalidatePlatformData()
}
+void Image::drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& destRect)
+{
+ notImplemented();
+}
+
}
diff --git a/WebCore/platform/graphics/wx/IntSizeWx.cpp b/WebCore/platform/graphics/wx/IntSizeWx.cpp
new file mode 100644
index 0000000..8c82854
--- /dev/null
+++ b/WebCore/platform/graphics/wx/IntSizeWx.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 Kevin Watters. 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 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.
+ */
+
+#include "config.h"
+#include "IntSize.h"
+
+#include <wx/defs.h>
+#include <wx/gdicmn.h>
+
+namespace WebCore {
+
+IntSize::IntSize(const wxSize& s)
+ : m_width(s.x)
+ , m_height(s.y)
+{
+}
+
+IntSize::operator wxSize() const
+{
+ return wxSize(m_width, m_height);
+}
+
+}