summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics
diff options
context:
space:
mode:
authorUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
committerUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
commitd8543bb6618c17b12da906afa77d216f58cf4058 (patch)
treec58dc05ed86825bd0ef8d305d58c8205106b540f /WebCore/platform/graphics
downloadexternal_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.zip
external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.gz
external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.bz2
external/webkit r30707
Diffstat (limited to 'WebCore/platform/graphics')
-rw-r--r--WebCore/platform/graphics/AffineTransform.cpp103
-rw-r--r--WebCore/platform/graphics/AffineTransform.h137
-rw-r--r--WebCore/platform/graphics/BitmapImage.cpp282
-rw-r--r--WebCore/platform/graphics/BitmapImage.h207
-rw-r--r--WebCore/platform/graphics/Color.cpp288
-rw-r--r--WebCore/platform/graphics/Color.h145
-rw-r--r--WebCore/platform/graphics/FloatPoint.cpp52
-rw-r--r--WebCore/platform/graphics/FloatPoint.h139
-rw-r--r--WebCore/platform/graphics/FloatPoint3D.cpp85
-rw-r--r--WebCore/platform/graphics/FloatPoint3D.h55
-rw-r--r--WebCore/platform/graphics/FloatRect.cpp125
-rw-r--r--WebCore/platform/graphics/FloatRect.h173
-rw-r--r--WebCore/platform/graphics/FloatSize.cpp44
-rw-r--r--WebCore/platform/graphics/FloatSize.h125
-rw-r--r--WebCore/platform/graphics/Font.cpp809
-rw-r--r--WebCore/platform/graphics/Font.h291
-rw-r--r--WebCore/platform/graphics/FontCache.cpp273
-rw-r--r--WebCore/platform/graphics/FontCache.h81
-rw-r--r--WebCore/platform/graphics/FontData.cpp35
-rw-r--r--WebCore/platform/graphics/FontData.h49
-rw-r--r--WebCore/platform/graphics/FontDescription.h119
-rw-r--r--WebCore/platform/graphics/FontFallbackList.cpp116
-rw-r--r--WebCore/platform/graphics/FontFallbackList.h72
-rw-r--r--WebCore/platform/graphics/FontFamily.cpp55
-rw-r--r--WebCore/platform/graphics/FontFamily.h61
-rw-r--r--WebCore/platform/graphics/FontSelector.h46
-rw-r--r--WebCore/platform/graphics/GlyphBuffer.h167
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.cpp301
-rw-r--r--WebCore/platform/graphics/GlyphPageTreeNode.h171
-rw-r--r--WebCore/platform/graphics/GlyphWidthMap.cpp79
-rw-r--r--WebCore/platform/graphics/GlyphWidthMap.h74
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp446
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h269
-rw-r--r--WebCore/platform/graphics/GraphicsTypes.cpp119
-rw-r--r--WebCore/platform/graphics/GraphicsTypes.h70
-rw-r--r--WebCore/platform/graphics/Icon.h78
-rw-r--r--WebCore/platform/graphics/Image.cpp197
-rw-r--r--WebCore/platform/graphics/Image.h168
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h95
-rw-r--r--WebCore/platform/graphics/ImageObserver.h48
-rw-r--r--WebCore/platform/graphics/ImageSource.h101
-rw-r--r--WebCore/platform/graphics/IntPoint.h150
-rw-r--r--WebCore/platform/graphics/IntRect.cpp107
-rw-r--r--WebCore/platform/graphics/IntRect.h197
-rw-r--r--WebCore/platform/graphics/IntSize.h154
-rw-r--r--WebCore/platform/graphics/IntSizeHash.h47
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp258
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h137
-rw-r--r--WebCore/platform/graphics/Path.cpp276
-rw-r--r--WebCore/platform/graphics/Path.h130
-rw-r--r--WebCore/platform/graphics/PathTraversalState.cpp207
-rw-r--r--WebCore/platform/graphics/PathTraversalState.h72
-rw-r--r--WebCore/platform/graphics/Pen.cpp77
-rw-r--r--WebCore/platform/graphics/Pen.h72
-rw-r--r--WebCore/platform/graphics/SegmentedFontData.cpp79
-rw-r--r--WebCore/platform/graphics/SegmentedFontData.h75
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp149
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h184
-rw-r--r--WebCore/platform/graphics/StringTruncator.cpp199
-rw-r--r--WebCore/platform/graphics/StringTruncator.h46
-rw-r--r--WebCore/platform/graphics/cairo/AffineTransformCairo.cpp281
-rw-r--r--WebCore/platform/graphics/cairo/CairoPath.h45
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp65
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp930
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h101
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp88
-rw-r--r--WebCore/platform/graphics/cairo/ImageCairo.cpp155
-rw-r--r--WebCore/platform/graphics/cairo/ImageSourceCairo.cpp221
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp280
-rw-r--r--WebCore/platform/graphics/cairo/rgb24-hacks.txt32
-rw-r--r--WebCore/platform/graphics/cairo/scale-removal.txt13
-rw-r--r--WebCore/platform/graphics/cg/AffineTransformCG.cpp216
-rw-r--r--WebCore/platform/graphics/cg/ColorCG.cpp96
-rw-r--r--WebCore/platform/graphics/cg/FloatPointCG.cpp47
-rw-r--r--WebCore/platform/graphics/cg/FloatRectCG.cpp47
-rw-r--r--WebCore/platform/graphics/cg/FloatSizeCG.cpp47
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp976
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h85
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp212
-rw-r--r--WebCore/platform/graphics/cg/ImageCG.cpp283
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp212
-rw-r--r--WebCore/platform/graphics/cg/IntPointCG.cpp46
-rw-r--r--WebCore/platform/graphics/cg/IntRectCG.cpp51
-rw-r--r--WebCore/platform/graphics/cg/IntSizeCG.cpp46
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.cpp179
-rw-r--r--WebCore/platform/graphics/cg/PDFDocumentImage.h64
-rw-r--r--WebCore/platform/graphics/cg/PathCG.cpp289
-rw-r--r--WebCore/platform/graphics/gtk/ColorGtk.cpp35
-rw-r--r--WebCore/platform/graphics/gtk/FontCacheGtk.cpp75
-rw-r--r--WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp73
-rw-r--r--WebCore/platform/graphics/gtk/FontCustomPlatformData.h49
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp245
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformData.h80
-rw-r--r--WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp200
-rw-r--r--WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp65
-rw-r--r--WebCore/platform/graphics/gtk/IconGtk.cpp116
-rw-r--r--WebCore/platform/graphics/gtk/ImageGtk.cpp53
-rw-r--r--WebCore/platform/graphics/gtk/IntPointGtk.cpp41
-rw-r--r--WebCore/platform/graphics/gtk/IntRectGtk.cpp41
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp625
-rw-r--r--WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h135
-rw-r--r--WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp135
-rw-r--r--WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp314
-rw-r--r--WebCore/platform/graphics/gtk/VideoSinkGStreamer.h83
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.h50
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.mm183
-rw-r--r--WebCore/platform/graphics/mac/FloatPointMac.mm45
-rw-r--r--WebCore/platform/graphics/mac/FloatRectMac.mm45
-rw-r--r--WebCore/platform/graphics/mac/FloatSizeMac.mm45
-rw-r--r--WebCore/platform/graphics/mac/FontCacheMac.mm262
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.cpp84
-rw-r--r--WebCore/platform/graphics/mac/FontCustomPlatformData.h52
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm659
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformData.h102
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformDataMac.mm70
-rw-r--r--WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp76
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm165
-rw-r--r--WebCore/platform/graphics/mac/IconMac.mm74
-rw-r--r--WebCore/platform/graphics/mac/ImageMac.mm122
-rw-r--r--WebCore/platform/graphics/mac/IntPointMac.mm44
-rw-r--r--WebCore/platform/graphics/mac/IntRectMac.mm49
-rw-r--r--WebCore/platform/graphics/mac/IntSizeMac.mm44
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h132
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm843
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm376
-rw-r--r--WebCore/platform/graphics/qt/AffineTransformQt.cpp202
-rw-r--r--WebCore/platform/graphics/qt/ColorQt.cpp48
-rw-r--r--WebCore/platform/graphics/qt/FloatPointQt.cpp48
-rw-r--r--WebCore/platform/graphics/qt/FloatRectQt.cpp49
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp54
-rw-r--r--WebCore/platform/graphics/qt/FontCustomPlatformData.cpp56
-rw-r--r--WebCore/platform/graphics/qt/FontCustomPlatformData.h44
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformData.h37
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp651
-rw-r--r--WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp31
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp943
-rw-r--r--WebCore/platform/graphics/qt/IconQt.cpp63
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp85
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp308
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h99
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp210
-rw-r--r--WebCore/platform/graphics/qt/ImageSourceQt.cpp203
-rw-r--r--WebCore/platform/graphics/qt/IntPointQt.cpp48
-rw-r--r--WebCore/platform/graphics/qt/IntRectQt.cpp48
-rw-r--r--WebCore/platform/graphics/qt/IntSizeQt.cpp49
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp278
-rw-r--r--WebCore/platform/graphics/qt/SimpleFontDataQt.cpp51
-rw-r--r--WebCore/platform/graphics/win/ColorSafari.cpp76
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp127
-rw-r--r--WebCore/platform/graphics/win/FontCacheWin.cpp441
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformData.cpp76
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformData.h49
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp61
-rw-r--r--WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h49
-rw-r--r--WebCore/platform/graphics/win/FontDatabase.cpp150
-rw-r--r--WebCore/platform/graphics/win/FontDatabase.h38
-rw-r--r--WebCore/platform/graphics/win/FontPlatformData.h137
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp134
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp89
-rw-r--r--WebCore/platform/graphics/win/FontPlatformDataWin.cpp144
-rw-r--r--WebCore/platform/graphics/win/FontWin.cpp101
-rw-r--r--WebCore/platform/graphics/win/GlyphPageTreeNodeCGWin.cpp59
-rw-r--r--WebCore/platform/graphics/win/GlyphPageTreeNodeCairoWin.cpp72
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp305
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp114
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextWin.cpp126
-rw-r--r--WebCore/platform/graphics/win/IconWin.cpp74
-rw-r--r--WebCore/platform/graphics/win/ImageCGWin.cpp85
-rw-r--r--WebCore/platform/graphics/win/ImageCairoWin.cpp89
-rw-r--r--WebCore/platform/graphics/win/ImageWin.cpp58
-rw-r--r--WebCore/platform/graphics/win/IntPointWin.cpp56
-rw-r--r--WebCore/platform/graphics/win/IntRectWin.cpp43
-rw-r--r--WebCore/platform/graphics/win/IntSizeWin.cpp44
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp425
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h119
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.cpp711
-rw-r--r--WebCore/platform/graphics/win/QTMovieWin.h97
-rw-r--r--WebCore/platform/graphics/win/QTMovieWinTimer.cpp141
-rw-r--r--WebCore/platform/graphics/win/QTMovieWinTimer.h39
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp144
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp130
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataWin.cpp206
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.cpp448
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.h82
-rw-r--r--WebCore/platform/graphics/wx/AffineTransformWx.cpp157
-rw-r--r--WebCore/platform/graphics/wx/ColorWx.cpp44
-rw-r--r--WebCore/platform/graphics/wx/FloatRectWx.cpp47
-rwxr-xr-xWebCore/platform/graphics/wx/FontCacheWx.cpp73
-rw-r--r--WebCore/platform/graphics/wx/FontPlatformData.h104
-rwxr-xr-xWebCore/platform/graphics/wx/FontPlatformDataWx.cpp107
-rw-r--r--WebCore/platform/graphics/wx/FontWx.cpp78
-rwxr-xr-xWebCore/platform/graphics/wx/GlyphMapWx.cpp59
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp491
-rw-r--r--WebCore/platform/graphics/wx/ImageBufferWx.cpp60
-rw-r--r--WebCore/platform/graphics/wx/ImageSourceWx.cpp233
-rw-r--r--WebCore/platform/graphics/wx/ImageWx.cpp186
-rw-r--r--WebCore/platform/graphics/wx/IntPointWx.cpp45
-rw-r--r--WebCore/platform/graphics/wx/IntRectWx.cpp45
-rw-r--r--WebCore/platform/graphics/wx/PathWx.cpp180
-rw-r--r--WebCore/platform/graphics/wx/PenWx.cpp77
-rwxr-xr-xWebCore/platform/graphics/wx/SimpleFontDataWx.cpp96
201 files changed, 30986 insertions, 0 deletions
diff --git a/WebCore/platform/graphics/AffineTransform.cpp b/WebCore/platform/graphics/AffineTransform.cpp
new file mode 100644
index 0000000..664bf28
--- /dev/null
+++ b/WebCore/platform/graphics/AffineTransform.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, 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"
+#include "AffineTransform.h"
+
+#include "FloatRect.h"
+#include "IntRect.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+bool AffineTransform::isInvertible() const
+{
+ return det() != 0.0;
+}
+
+AffineTransform& AffineTransform::multiply(const AffineTransform& other)
+{
+ return (*this) *= other;
+}
+
+AffineTransform& AffineTransform::scale(double s)
+{
+ return scale(s, s);
+}
+
+AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
+{
+ return scale(sx, sy);
+}
+
+AffineTransform& AffineTransform::rotateFromVector(double x, double y)
+{
+ return rotate(rad2deg(atan2(y, x)));
+}
+
+AffineTransform& AffineTransform::flipX()
+{
+ return scale(-1.0f, 1.0f);
+}
+
+AffineTransform& AffineTransform::flipY()
+{
+ return scale(1.0f, -1.0f);
+}
+
+AffineTransform& AffineTransform::skew(double angleX, double angleY)
+{
+ return shear(tan(deg2rad(angleX)), tan(deg2rad(angleY)));
+}
+
+AffineTransform& AffineTransform::skewX(double angle)
+{
+ return shear(tan(deg2rad(angle)), 0.0f);
+}
+
+AffineTransform& AffineTransform::skewY(double angle)
+{
+ return shear(0.0f, tan(deg2rad(angle)));
+}
+
+IntPoint AffineTransform::mapPoint(const IntPoint& point) const
+{
+ double x2, y2;
+ map(point.x(), point.y(), &x2, &y2);
+
+ // Round the point.
+ return IntPoint(lround(x2), lround(y2));
+}
+
+FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const
+{
+ double x2, y2;
+ map(point.x(), point.y(), &x2, &y2);
+
+ return FloatPoint(static_cast<float>(x2), static_cast<float>(y2));
+}
+
+}
diff --git a/WebCore/platform/graphics/AffineTransform.h b/WebCore/platform/graphics/AffineTransform.h
new file mode 100644
index 0000000..2ba4ce7
--- /dev/null
+++ b/WebCore/platform/graphics/AffineTransform.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, 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 AffineTransform_h
+#define AffineTransform_h
+
+#if PLATFORM(CG)
+#include <CoreGraphics/CGAffineTransform.h>
+#elif PLATFORM(QT)
+#include <QMatrix>
+#elif PLATFORM(CAIRO)
+#include <cairo.h>
+#elif PLATFORM(WX) && USE(WXGC)
+#include <wx/defs.h>
+#include <wx/graphics.h>
+#endif
+
+namespace WebCore {
+
+class IntPoint;
+class IntRect;
+class FloatPoint;
+class FloatRect;
+
+class AffineTransform {
+public:
+ AffineTransform();
+ AffineTransform(double a, double b, double c, double d, double e, double f);
+#if PLATFORM(CG)
+ AffineTransform(CGAffineTransform transform);
+#elif PLATFORM(QT)
+ AffineTransform(const QMatrix &matrix);
+#elif PLATFORM(CAIRO)
+ AffineTransform(const cairo_matrix_t &matrix);
+#elif PLATFORM(WX) && USE(WXGC)
+ AffineTransform(const wxGraphicsMatrix &matrix);
+#endif
+
+ void setMatrix(double a, double b, double c, double d, double e, double f);
+ void map(double x, double y, double *x2, double *y2) const;
+ IntPoint mapPoint(const IntPoint&) const;
+ FloatPoint mapPoint(const FloatPoint&) const;
+ IntRect mapRect(const IntRect&) const;
+ FloatRect mapRect(const FloatRect&) const;
+
+ bool isIdentity() const;
+
+ double a() const;
+ void setA(double a);
+
+ double b() const;
+ void setB(double b);
+
+ double c() const;
+ void setC(double c);
+
+ double d() const;
+ void setD(double d);
+
+ double e() const;
+ void setE(double e);
+
+ double f() const;
+ void setF(double f);
+
+ void reset();
+
+ AffineTransform& multiply(const AffineTransform&);
+ AffineTransform& scale(double);
+ AffineTransform& scale(double sx, double sy);
+ AffineTransform& scaleNonUniform(double sx, double sy);
+ AffineTransform& rotate(double d);
+ AffineTransform& rotateFromVector(double x, double y);
+ AffineTransform& translate(double tx, double ty);
+ AffineTransform& shear(double sx, double sy);
+ AffineTransform& flipX();
+ AffineTransform& flipY();
+ AffineTransform& skew(double angleX, double angleY);
+ AffineTransform& skewX(double angle);
+ AffineTransform& skewY(double angle);
+
+ double det() const;
+ bool isInvertible() const;
+ AffineTransform inverse() const;
+
+#if PLATFORM(CG)
+ operator CGAffineTransform() const;
+#elif PLATFORM(QT)
+ operator QMatrix() const;
+#elif PLATFORM(CAIRO)
+ operator cairo_matrix_t() const;
+#elif PLATFORM(WX) && USE(WXGC)
+ operator wxGraphicsMatrix() const;
+#endif
+
+ bool operator==(const AffineTransform&) const;
+ bool operator!=(const AffineTransform& other) const { return !(*this == other); }
+ AffineTransform& operator*=(const AffineTransform&);
+ AffineTransform operator*(const AffineTransform&);
+
+private:
+#if PLATFORM(CG)
+ CGAffineTransform m_transform;
+#elif PLATFORM(QT)
+ QMatrix m_transform;
+#elif PLATFORM(CAIRO)
+ cairo_matrix_t m_transform;
+#elif PLATFORM(WX) && USE(WXGC)
+ wxGraphicsMatrix m_transform;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // AffineTransform_h
diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp
new file mode 100644
index 0000000..9ef1d6a
--- /dev/null
+++ b/WebCore/platform/graphics/BitmapImage.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "BitmapImage.h"
+
+#include "FloatRect.h"
+#include "ImageObserver.h"
+#include "IntRect.h"
+#include "PlatformString.h"
+#include "Timer.h"
+#include <wtf/Vector.h>
+#include "MIMETypeRegistry.h"
+
+namespace WebCore {
+
+// Animated images >5MB are considered large enough that we'll only hang on to
+// one frame at a time.
+const unsigned cLargeAnimationCutoff = 5242880;
+
+BitmapImage::BitmapImage(ImageObserver* observer)
+ : Image(observer)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(0)
+ , m_repetitionsComplete(0)
+ , m_isSolidColor(false)
+ , m_animatingImageType(true)
+ , m_animationFinished(false)
+ , m_allDataReceived(false)
+ , m_haveSize(false)
+ , m_sizeAvailable(false)
+ , m_decodedSize(0)
+{
+ initPlatformData();
+}
+
+BitmapImage::~BitmapImage()
+{
+ invalidatePlatformData();
+ stopAnimation();
+}
+
+void BitmapImage::destroyDecodedData(bool incremental)
+{
+ // Destroy the cached images and release them.
+ if (m_frames.size()) {
+ int sizeChange = 0;
+ int frameSize = m_size.width() * m_size.height() * 4;
+ for (unsigned i = incremental ? m_frames.size() - 1 : 0; i < m_frames.size(); i++) {
+ if (m_frames[i].m_frame) {
+ sizeChange -= frameSize;
+ m_frames[i].clear();
+ }
+ }
+
+ // We just always invalidate our platform data, even in the incremental case.
+ // This could be better, but it's not a big deal.
+ m_isSolidColor = false;
+ invalidatePlatformData();
+
+ if (sizeChange) {
+ m_decodedSize += sizeChange;
+ if (imageObserver())
+ imageObserver()->decodedSizeChanged(this, sizeChange);
+ }
+
+ if (!incremental) {
+ // Reset the image source, since Image I/O has an underlying cache that it uses
+ // while animating that it seems to never clear.
+ m_source.clear();
+ m_source.setData(m_data.get(), m_allDataReceived);
+ }
+ }
+}
+
+void BitmapImage::cacheFrame(size_t index)
+{
+ size_t numFrames = frameCount();
+ ASSERT(m_decodedSize == 0 || numFrames > 1);
+
+ if (!m_frames.size() && shouldAnimate()) {
+ // Snag the repetition count.
+ m_repetitionCount = m_source.repetitionCount();
+ if (m_repetitionCount == cAnimationNone)
+ m_animatingImageType = false;
+ }
+
+ if (m_frames.size() < numFrames)
+ m_frames.grow(numFrames);
+
+ m_frames[index].m_frame = m_source.createFrameAtIndex(index);
+ if (numFrames == 1 && m_frames[index].m_frame)
+ checkForSolidColor();
+
+ if (shouldAnimate())
+ m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
+ m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
+
+ int sizeChange = m_frames[index].m_frame ? m_size.width() * m_size.height() * 4 : 0;
+ if (sizeChange) {
+ m_decodedSize += sizeChange;
+ if (imageObserver())
+ imageObserver()->decodedSizeChanged(this, sizeChange);
+ }
+}
+
+IntSize BitmapImage::size() const
+{
+ if (m_sizeAvailable && !m_haveSize) {
+ m_size = m_source.size();
+ m_haveSize = true;
+ }
+ return m_size;
+}
+
+bool BitmapImage::dataChanged(bool allDataReceived)
+{
+ destroyDecodedData(true);
+
+ // Feed all the data we've seen so far to the image decoder.
+ m_allDataReceived = allDataReceived;
+ m_source.setData(m_data.get(), allDataReceived);
+
+ // Image properties will not be available until the first frame of the file
+ // reaches kCGImageStatusIncomplete.
+ return isSizeAvailable();
+}
+
+size_t BitmapImage::frameCount()
+{
+ return m_source.frameCount();
+}
+
+bool BitmapImage::isSizeAvailable()
+{
+ if (m_sizeAvailable)
+ return true;
+
+ m_sizeAvailable = m_source.isSizeAvailable();
+
+ return m_sizeAvailable;
+}
+
+NativeImagePtr BitmapImage::frameAtIndex(size_t index)
+{
+ if (index >= frameCount())
+ return 0;
+
+ if (index >= m_frames.size() || !m_frames[index].m_frame)
+ cacheFrame(index);
+
+ return m_frames[index].m_frame;
+}
+
+float BitmapImage::frameDurationAtIndex(size_t index)
+{
+ if (index >= frameCount())
+ return 0;
+
+ if (index >= m_frames.size() || !m_frames[index].m_frame)
+ cacheFrame(index);
+
+ return m_frames[index].m_duration;
+}
+
+bool BitmapImage::frameHasAlphaAtIndex(size_t index)
+{
+ if (index >= frameCount())
+ return 0;
+
+ if (index >= m_frames.size() || !m_frames[index].m_frame)
+ cacheFrame(index);
+
+ return m_frames[index].m_hasAlpha;
+}
+
+bool BitmapImage::shouldAnimate()
+{
+ return (m_animatingImageType && !m_animationFinished && imageObserver());
+}
+
+void BitmapImage::startAnimation()
+{
+ if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
+ return;
+
+ // Don't advance the animation until the current frame has completely loaded.
+ if (!m_source.frameIsCompleteAtIndex(m_currentFrame))
+ return;
+
+ m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);
+ m_frameTimer->startOneShot(frameDurationAtIndex(m_currentFrame));
+}
+
+void BitmapImage::stopAnimation()
+{
+ // This timer is used to animate all occurrences of this image. Don't invalidate
+ // the timer unless all renderers have stopped drawing.
+ delete m_frameTimer;
+ m_frameTimer = 0;
+}
+
+void BitmapImage::resetAnimation()
+{
+ stopAnimation();
+ m_currentFrame = 0;
+ m_repetitionsComplete = 0;
+ m_animationFinished = false;
+ int frameSize = m_size.width() * m_size.height() * 4;
+
+ // For extremely large animations, when the animation is reset, we just throw everything away.
+ if (frameCount() * frameSize > cLargeAnimationCutoff)
+ destroyDecodedData();
+}
+
+void BitmapImage::advanceAnimation(Timer<BitmapImage>* timer)
+{
+ // Stop the animation.
+ stopAnimation();
+
+ // See if anyone is still paying attention to this animation. If not, we don't
+ // advance and will remain suspended at the current frame until the animation is resumed.
+ if (imageObserver()->shouldPauseAnimation(this))
+ return;
+
+ m_currentFrame++;
+ if (m_currentFrame >= frameCount()) {
+ m_repetitionsComplete += 1;
+ if (m_repetitionCount && m_repetitionsComplete >= m_repetitionCount) {
+ m_animationFinished = true;
+ m_currentFrame--;
+ return;
+ }
+ m_currentFrame = 0;
+ }
+
+ // Notify our observer that the animation has advanced.
+ imageObserver()->animationAdvanced(this);
+
+ // For large animated images, go ahead and throw away frames as we go to save
+ // footprint.
+ int frameSize = m_size.width() * m_size.height() * 4;
+ if (frameCount() * frameSize > cLargeAnimationCutoff) {
+ // Destroy all of our frames and just redecode every time.
+ destroyDecodedData();
+
+ // Go ahead and decode the next frame.
+ frameAtIndex(m_currentFrame);
+ }
+
+ // We do not advance the animation explicitly. We rely on a subsequent draw of the image
+ // to force a request for the next frame via startAnimation(). This allows images that move offscreen while
+ // scrolling to stop animating (thus saving memory from additional decoded frames and
+ // CPU time spent doing the decoding).
+}
+
+}
diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h
new file mode 100644
index 0000000..0185027
--- /dev/null
+++ b/WebCore/platform/graphics/BitmapImage.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 BitmapImage_h
+#define BitmapImage_h
+
+#include "Image.h"
+#include "Color.h"
+#include "IntSize.h"
+
+#if PLATFORM(MAC)
+#include <wtf/RetainPtr.h>
+#ifdef __OBJC__
+@class NSImage;
+#else
+class NSImage;
+#endif
+#endif
+
+#if PLATFORM(WIN)
+typedef struct HBITMAP__ *HBITMAP;
+#endif
+
+namespace WebCore {
+ struct FrameData;
+}
+
+// This complicated-looking declaration tells the FrameData Vector that it should copy without
+// invoking our constructor or destructor. This allows us to have a vector even for a struct
+// that's not copyable.
+namespace WTF {
+ template<> class VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {};
+}
+
+namespace WebCore {
+
+template <typename T> class Timer;
+
+// ================================================
+// FrameData Class
+// ================================================
+
+struct FrameData : Noncopyable {
+ FrameData()
+ : m_frame(0)
+ , m_duration(0)
+ , m_hasAlpha(true)
+ {
+ }
+
+ ~FrameData()
+ {
+ clear();
+ }
+
+ void clear();
+
+ NativeImagePtr m_frame;
+ float m_duration;
+ bool m_hasAlpha;
+};
+
+// =================================================
+// BitmapImage Class
+// =================================================
+
+class BitmapImage : public Image {
+ friend class GraphicsContext;
+public:
+#if PLATFORM(QT)
+ BitmapImage(const QPixmap &pixmap, ImageObserver* = 0);
+#endif
+ BitmapImage(ImageObserver* = 0);
+ ~BitmapImage();
+
+ virtual IntSize size() const;
+
+ virtual bool dataChanged(bool allDataReceived);
+
+ // It may look unusual that there is no start animation call as public API. This is because
+ // we start and stop animating lazily. Animation begins whenever someone draws the image. It will
+ // automatically pause once all observers no longer want to render the image anywhere.
+ virtual void stopAnimation();
+ virtual void resetAnimation();
+
+ virtual unsigned decodedSize() const { return m_decodedSize; }
+
+#if PLATFORM(MAC)
+ // Accessors for native image formats.
+ virtual NSImage* getNSImage();
+ virtual CFDataRef getTIFFRepresentation();
+#endif
+
+#if PLATFORM(CG)
+ virtual CGImageRef getCGImageRef();
+#endif
+
+#if PLATFORM(QT)
+ virtual QPixmap* getPixmap() const;
+#endif
+
+#if PLATFORM(WIN)
+ virtual bool getHBITMAP(HBITMAP);
+ virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE);
+#endif
+
+ virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
+
+private:
+#if PLATFORM(WIN)
+ 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(QT) || PLATFORM(WX)
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+#endif
+ size_t currentFrame() const { return m_currentFrame; }
+ size_t frameCount();
+ NativeImagePtr frameAtIndex(size_t);
+ float frameDurationAtIndex(size_t);
+ bool frameHasAlphaAtIndex(size_t);
+
+ // Decodes and caches a frame. Never accessed except internally.
+ void cacheFrame(size_t index);
+
+ // Called to invalidate all our cached data. If an image is loading incrementally, we only
+ // invalidate the last cached frame.
+ virtual void destroyDecodedData(bool incremental = false);
+
+ // Whether or not size is available yet.
+ bool isSizeAvailable();
+
+ // Animation.
+ bool shouldAnimate();
+ virtual void startAnimation();
+ void advanceAnimation(Timer<BitmapImage>*);
+
+ // Handle platform-specific data
+ void initPlatformData();
+ void invalidatePlatformData();
+
+ // Checks to see if the image is a 1x1 solid color. We optimize these images and just do a fill rect instead.
+ void checkForSolidColor();
+
+ virtual bool mayFillWithSolidColor() const { return m_isSolidColor && m_currentFrame == 0; }
+ virtual Color solidColor() const { return m_solidColor; }
+
+ ImageSource m_source;
+ mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
+
+ size_t m_currentFrame; // The index of the current frame of animation.
+ Vector<FrameData> m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache.
+
+ Timer<BitmapImage>* m_frameTimer;
+ int m_repetitionCount; // How many total animation loops we should do.
+ int m_repetitionsComplete; // How many repetitions we've finished.
+
+#if PLATFORM(MAC)
+ mutable RetainPtr<NSImage> m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one.
+ mutable RetainPtr<CFDataRef> m_tiffRep; // Cached TIFF rep for frame 0. Only built lazily if someone queries for one.
+#endif
+
+ Color m_solidColor; // If we're a 1x1 solid color, this is the color to use to fill.
+ bool m_isSolidColor; // Whether or not we are a 1x1 solid image.
+
+ bool m_animatingImageType; // Whether or not we're an image type that is capable of animating (GIF).
+ bool m_animationFinished; // Whether or not we've completed the entire animation.
+
+ bool m_allDataReceived; // Whether or not we've received all our data.
+
+ mutable bool m_haveSize; // Whether or not our |m_size| member variable has the final overall image size yet.
+ bool m_sizeAvailable; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
+ unsigned m_decodedSize; // The current size of all decoded frames.
+
+#if PLATFORM(QT)
+ QPixmap *m_pixmap;
+#endif
+
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/Color.cpp b/WebCore/platform/graphics/Color.cpp
new file mode 100644
index 0000000..52d2bd7
--- /dev/null
+++ b/WebCore/platform/graphics/Color.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "PlatformString.h"
+#include <math.h>
+#include <wtf/Assertions.h>
+#include <wtf/MathExtras.h>
+
+#include "ColorData.c"
+
+using namespace std;
+using namespace WTF;
+
+namespace WebCore {
+
+const RGBA32 lightenedBlack = 0xFF545454;
+const RGBA32 darkenedWhite = 0xFFABABAB;
+
+RGBA32 makeRGB(int r, int g, int b)
+{
+ return 0xFF000000 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
+}
+
+RGBA32 makeRGBA(int r, int g, int b, int a)
+{
+ return max(0, min(a, 255)) << 24 | max(0, min(r, 255)) << 16 | max(0, min(g, 255)) << 8 | max(0, min(b, 255));
+}
+
+static double calcHue(double temp1, double temp2, double hueVal)
+{
+ if (hueVal < 0.0)
+ hueVal++;
+ else if (hueVal > 1.0)
+ hueVal--;
+ if (hueVal * 6.0 < 1.0)
+ return temp1 + (temp2 - temp1) * hueVal * 6.0;
+ if (hueVal * 2.0 < 1.0)
+ return temp2;
+ if (hueVal * 3.0 < 2.0)
+ return temp1 + (temp2 - temp1) * (2.0 / 3.0 - hueVal) * 6.0;
+ return temp1;
+}
+
+// Explanation of this algorithm can be found in the CSS3 Color Module
+// specification at http://www.w3.org/TR/css3-color/#hsl-color with further
+// explanation available at http://en.wikipedia.org/wiki/HSL_color_space
+
+// all values are in the range of 0 to 1.0
+RGBA32 makeRGBAFromHSLA(double hue, double saturation, double lightness, double alpha)
+{
+ const double scaleFactor = nextafter(256.0, 0.0);
+
+ if (!saturation) {
+ int greyValue = static_cast<int>(lightness * scaleFactor);
+ return makeRGBA(greyValue, greyValue, greyValue, static_cast<int>(alpha * scaleFactor));
+ }
+
+ double temp2 = lightness < 0.5 ? lightness * (1.0 + saturation) : lightness + saturation - lightness * saturation;
+ double temp1 = 2.0 * lightness - temp2;
+
+ return makeRGBA(static_cast<int>(calcHue(temp1, temp2, hue + 1.0 / 3.0) * scaleFactor),
+ static_cast<int>(calcHue(temp1, temp2, hue) * scaleFactor),
+ static_cast<int>(calcHue(temp1, temp2, hue - 1.0 / 3.0) * scaleFactor),
+ static_cast<int>(alpha * scaleFactor));
+}
+
+// originally moved here from the CSS parser
+bool Color::parseHexColor(const String& name, RGBA32& rgb)
+{
+ unsigned length = name.length();
+ if (length != 3 && length != 6)
+ return false;
+ unsigned value = 0;
+ for (unsigned i = 0; i < length; ++i) {
+ if (!isASCIIHexDigit(name[i]))
+ return false;
+ value <<= 4;
+ value |= toASCIIHexValue(name[i]);
+ }
+ if (length == 6) {
+ rgb = 0xFF000000 | value;
+ return true;
+ }
+ // #abc converts to #aabbcc
+ rgb = 0xFF000000
+ | (value & 0xF00) << 12 | (value & 0xF00) << 8
+ | (value & 0xF0) << 8 | (value & 0xF0) << 4
+ | (value & 0xF) << 4 | (value & 0xF);
+ return true;
+}
+
+int differenceSquared(const Color& c1, const Color& c2)
+{
+ int dR = c1.red() - c2.red();
+ int dG = c1.green() - c2.green();
+ int dB = c1.blue() - c2.blue();
+ return dR * dR + dG * dG + dB * dB;
+}
+
+Color::Color(const String& name)
+{
+ if (name.startsWith("#"))
+ m_valid = parseHexColor(name.substring(1), m_color);
+ else
+ setNamedColor(name);
+}
+
+Color::Color(const char* name)
+{
+ if (name[0] == '#')
+ m_valid = parseHexColor(&name[1], m_color);
+ else {
+ const NamedColor* foundColor = findColor(name, strlen(name));
+ m_color = foundColor ? foundColor->RGBValue : 0;
+ m_color |= 0xFF000000;
+ m_valid = foundColor;
+ }
+}
+
+String Color::name() const
+{
+ if (alpha() < 0xFF)
+ return String::format("#%02X%02X%02X%02X", red(), green(), blue(), alpha());
+ return String::format("#%02X%02X%02X", red(), green(), blue());
+}
+
+static inline const NamedColor* findNamedColor(const String& name)
+{
+ char buffer[64]; // easily big enough for the longest color name
+ unsigned length = name.length();
+ if (length > sizeof(buffer) - 1)
+ return 0;
+ for (unsigned i = 0; i < length; ++i) {
+ UChar c = name[i];
+ if (!c || c > 0x7F)
+ return 0;
+ buffer[i] = toASCIILower(static_cast<char>(c));
+ }
+ buffer[length] = '\0';
+ return findColor(buffer, length);
+}
+
+void Color::setNamedColor(const String& name)
+{
+ const NamedColor* foundColor = findNamedColor(name);
+ m_color = foundColor ? foundColor->RGBValue : 0;
+ m_color |= 0xFF000000;
+ m_valid = foundColor;
+}
+
+Color Color::light() const
+{
+ // Hardcode this common case for speed.
+ if (m_color == black)
+ return lightenedBlack;
+
+ const float scaleFactor = nextafterf(256.0f, 0.0f);
+
+ float r, g, b, a;
+ getRGBA(r, g, b, a);
+
+ float v = max(r, max(g, b));
+
+ if (v == 0.0f)
+ // Lightened black with alpha.
+ return Color(0x54, 0x54, 0x54, alpha());
+
+ float multiplier = min(1.0f, v + 0.33f) / v;
+
+ return Color(static_cast<int>(multiplier * r * scaleFactor),
+ static_cast<int>(multiplier * g * scaleFactor),
+ static_cast<int>(multiplier * b * scaleFactor),
+ alpha());
+}
+
+Color Color::dark() const
+{
+ // Hardcode this common case for speed.
+ if (m_color == white)
+ return darkenedWhite;
+
+ const float scaleFactor = nextafterf(256.0f, 0.0f);
+
+ float r, g, b, a;
+ getRGBA(r, g, b, a);
+
+ float v = max(r, max(g, b));
+ float multiplier = max(0.0f, (v - 0.33f) / v);
+
+ return Color(static_cast<int>(multiplier * r * scaleFactor),
+ static_cast<int>(multiplier * g * scaleFactor),
+ static_cast<int>(multiplier * b * scaleFactor),
+ alpha());
+}
+
+static int blendComponent(int c, int a)
+{
+ // We use white.
+ float alpha = a / 255.0f;
+ int whiteBlend = 255 - a;
+ c -= whiteBlend;
+ return static_cast<int>(c / alpha);
+}
+
+const int cStartAlpha = 153; // 60%
+const int cEndAlpha = 204; // 80%;
+const int cAlphaIncrement = 17; // Increments in between.
+
+Color Color::blend(const Color& source) const
+{
+ if (!alpha() || !source.hasAlpha())
+ return source;
+
+ if (!source.alpha())
+ return *this;
+
+ int d = 255 * (alpha() + source.alpha()) - alpha() * source.alpha();
+ int a = d / 255;
+ int r = (red() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.red()) / d;
+ int g = (green() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.green()) / d;
+ int b = (blue() * alpha() * (255 - source.alpha()) + 255 * source.alpha() * source.blue()) / d;
+ return Color(r, g, b, a);
+}
+
+Color Color::blendWithWhite() const
+{
+ // If the color contains alpha already, we leave it alone.
+ if (hasAlpha())
+ return *this;
+
+ Color newColor;
+ for (int alpha = cStartAlpha; alpha <= cEndAlpha; alpha += cAlphaIncrement) {
+ // We have a solid color. Convert to an equivalent color that looks the same when blended with white
+ // at the current alpha. Try using less transparency if the numbers end up being negative.
+ int r = blendComponent(red(), alpha);
+ int g = blendComponent(green(), alpha);
+ int b = blendComponent(blue(), alpha);
+
+ newColor = Color(r, g, b, alpha);
+
+ if (r >= 0 && g >= 0 && b >= 0)
+ break;
+ }
+ return newColor;
+}
+
+void Color::getRGBA(float& r, float& g, float& b, float& a) const
+{
+ r = red() / 255.0f;
+ g = green() / 255.0f;
+ b = blue() / 255.0f;
+ a = alpha() / 255.0f;
+}
+
+void Color::getRGBA(double& r, double& g, double& b, double& a) const
+{
+ r = red() / 255.0;
+ g = green() / 255.0;
+ b = blue() / 255.0;
+ a = alpha() / 255.0;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h
new file mode 100644
index 0000000..5706c6f
--- /dev/null
+++ b/WebCore/platform/graphics/Color.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2003-6 Apple Computer, 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 Color_h
+#define Color_h
+
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGColor* CGColorRef;
+#endif
+
+#if PLATFORM(QT)
+class QColor;
+#endif
+
+#if PLATFORM(GTK)
+typedef struct _GdkColor GdkColor;
+#endif
+
+#if PLATFORM(WX)
+class wxColour;
+#endif
+
+namespace WebCore {
+
+class String;
+class Color;
+
+typedef unsigned RGBA32; // RGBA quadruplet
+
+RGBA32 makeRGB(int r, int g, int b);
+RGBA32 makeRGBA(int r, int g, int b, int a);
+RGBA32 makeRGBAFromHSLA(double h, double s, double l, double a);
+
+int differenceSquared(const Color&, const Color&);
+
+class Color {
+public:
+ Color() : m_color(0), m_valid(false) { }
+ Color(RGBA32 col) : m_color(col), m_valid(true) { }
+ Color(int r, int g, int b) : m_color(makeRGB(r, g, b)), m_valid(true) { }
+ Color(int r, int g, int b, int a) : m_color(makeRGBA(r, g, b, a)), m_valid(true) { }
+ explicit Color(const String&);
+ explicit Color(const char*);
+
+ String name() const;
+ void setNamedColor(const String&);
+
+ bool isValid() const { return m_valid; }
+
+ bool hasAlpha() const { return alpha() < 255; }
+
+ int red() const { return (m_color >> 16) & 0xFF; }
+ int green() const { return (m_color >> 8) & 0xFF; }
+ int blue() const { return m_color & 0xFF; }
+ int alpha() const { return (m_color >> 24) & 0xFF; }
+
+ RGBA32 rgb() const { return m_color; } // Preserve the alpha.
+ void setRGB(int r, int g, int b) { m_color = makeRGB(r, g, b); m_valid = true; }
+ void setRGB(RGBA32 rgb) { m_color = rgb; m_valid = true; }
+ void getRGBA(float& r, float& g, float& b, float& a) const;
+ void getRGBA(double& r, double& g, double& b, double& a) const;
+
+ Color light() const;
+ Color dark() const;
+
+ Color blend(const Color&) const;
+ Color blendWithWhite() const;
+
+#if PLATFORM(QT)
+ Color(const QColor&);
+ operator QColor() const;
+#endif
+
+#if PLATFORM(GTK)
+ Color(const GdkColor&);
+ // We can't sensibly go back to GdkColor without losing the alpha value
+#endif
+
+#if PLATFORM(WX)
+ Color(const wxColour&);
+ operator wxColour() const;
+#endif
+
+#if PLATFORM(CG)
+ Color(CGColorRef);
+#endif
+
+ static bool parseHexColor(const String& name, RGBA32& rgb);
+
+ static const RGBA32 black = 0xFF000000;
+ static const RGBA32 white = 0xFFFFFFFF;
+ static const RGBA32 darkGray = 0xFF808080;
+ static const RGBA32 gray = 0xFFA0A0A0;
+ static const RGBA32 lightGray = 0xFFC0C0C0;
+ static const RGBA32 transparent = 0x00000000;
+
+private:
+ RGBA32 m_color;
+ bool m_valid : 1;
+};
+
+inline bool operator==(const Color& a, const Color& b)
+{
+ return a.rgb() == b.rgb() && a.isValid() == b.isValid();
+}
+
+inline bool operator!=(const Color& a, const Color& b)
+{
+ return !(a == b);
+}
+
+Color focusRingColor();
+void setFocusRingColorChangeFunction(void (*)());
+
+#if PLATFORM(CG)
+CGColorRef cgColor(const Color&);
+#endif
+
+} // namespace WebCore
+
+#endif // Color_h
diff --git a/WebCore/platform/graphics/FloatPoint.cpp b/WebCore/platform/graphics/FloatPoint.cpp
new file mode 100644
index 0000000..3ca0361
--- /dev/null
+++ b/WebCore/platform/graphics/FloatPoint.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 "AffineTransform.h"
+#include "FloatConversion.h"
+#include "IntPoint.h"
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const IntPoint& p) : m_x(p.x()), m_y(p.y())
+{
+}
+
+FloatPoint FloatPoint::matrixTransform(const AffineTransform& transform) const
+{
+ double newX, newY;
+ transform.map(static_cast<double>(m_x), static_cast<double>(m_y), &newX, &newY);
+ return narrowPrecision(newX, newY);
+}
+
+FloatPoint FloatPoint::narrowPrecision(double x, double y)
+{
+ return FloatPoint(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y));
+}
+
+}
diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h
new file mode 100644
index 0000000..7b8ba1d
--- /dev/null
+++ b/WebCore/platform/graphics/FloatPoint.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 FloatPoint_h
+#define FloatPoint_h
+
+#include "FloatSize.h"
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGPoint CGPoint;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+typedef struct CGPoint NSPoint;
+#else
+typedef struct _NSPoint NSPoint;
+#endif
+#endif
+
+#if PLATFORM(QT)
+class QPointF;
+#endif
+
+#if PLATFORM(SYMBIAN)
+class TPoint;
+#endif
+
+namespace WebCore {
+
+class AffineTransform;
+class IntPoint;
+
+class FloatPoint {
+public:
+ FloatPoint() : m_x(0), m_y(0) { }
+ FloatPoint(float x, float y) : m_x(x), m_y(y) { }
+ FloatPoint(const IntPoint&);
+
+ static FloatPoint narrowPrecision(double x, double y);
+
+ float x() const { return m_x; }
+ float y() const { return m_y; }
+
+ void setX(float x) { m_x = x; }
+ void setY(float y) { m_y = y; }
+ void move(float dx, float dy) { m_x += dx; m_y += dy; }
+
+#if PLATFORM(CG)
+ FloatPoint(const CGPoint&);
+ operator CGPoint() const;
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+ FloatPoint(const NSPoint&);
+ operator NSPoint() const;
+#endif
+
+#if PLATFORM(QT)
+ FloatPoint(const QPointF&);
+ operator QPointF() const;
+#endif
+
+#if PLATFORM(SYMBIAN)
+ operator TPoint() const;
+ FloatPoint(const TPoint& );
+#endif
+
+ FloatPoint matrixTransform(const AffineTransform&) const;
+
+private:
+ float m_x, m_y;
+};
+
+
+inline FloatPoint& operator+=(FloatPoint& a, const FloatSize& b)
+{
+ a.move(b.width(), b.height());
+ return a;
+}
+
+inline FloatPoint& operator-=(FloatPoint& a, const FloatSize& b)
+{
+ a.move(-b.width(), -b.height());
+ return a;
+}
+
+inline FloatPoint operator+(const FloatPoint& a, const FloatSize& b)
+{
+ return FloatPoint(a.x() + b.width(), a.y() + b.height());
+}
+
+inline FloatSize operator-(const FloatPoint& a, const FloatPoint& b)
+{
+ return FloatSize(a.x() - b.x(), a.y() - b.y());
+}
+
+inline FloatPoint operator-(const FloatPoint& a, const FloatSize& b)
+{
+ return FloatPoint(a.x() - b.width(), a.y() - b.height());
+}
+
+inline bool operator==(const FloatPoint& a, const FloatPoint& b)
+{
+ return a.x() == b.x() && a.y() == b.y();
+}
+
+inline bool operator!=(const FloatPoint& a, const FloatPoint& b)
+{
+ return a.x() != b.x() || a.y() != b.y();
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/FloatPoint3D.cpp b/WebCore/platform/graphics/FloatPoint3D.cpp
new file mode 100644
index 0000000..ec52d40
--- /dev/null
+++ b/WebCore/platform/graphics/FloatPoint3D.cpp
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <wildfox@kde.org>
+ 2004, 2005 Rob Buis <buis@kde.org>
+ 2005 Eric Seidel <eric@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include <math.h>
+#include "FloatPoint3D.h"
+
+namespace WebCore {
+
+FloatPoint3D::FloatPoint3D()
+ : m_x(0.f)
+ , m_y(0.f)
+ , m_z(0.f)
+{
+}
+
+FloatPoint3D::FloatPoint3D(float x, float y, float z)
+ : m_x(x)
+ , m_y(y)
+ , m_z(z)
+{
+}
+
+float FloatPoint3D::x() const
+{
+ return m_x;
+}
+
+void FloatPoint3D::setX(float x)
+{
+ m_x = x;
+}
+
+float FloatPoint3D::y() const
+{
+ return m_y;
+}
+
+void FloatPoint3D::setY(float y)
+{
+ m_y = y;
+}
+
+float FloatPoint3D::z() const
+{
+ return m_z;
+}
+
+void FloatPoint3D::setZ(float z)
+{
+ m_z = z;
+}
+
+void FloatPoint3D::normalize()
+{
+ float length = sqrtf(m_x * m_x + m_y * m_y + m_z * m_z);
+
+ m_x /= length;
+ m_y /= length;
+ m_z /= length;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/platform/graphics/FloatPoint3D.h b/WebCore/platform/graphics/FloatPoint3D.h
new file mode 100644
index 0000000..55f70e7
--- /dev/null
+++ b/WebCore/platform/graphics/FloatPoint3D.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <wildfox@kde.org>
+ 2004, 2005 Rob Buis <buis@kde.org>
+ 2005 Eric Seidel <eric@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FloatPoint3D_h
+#define FloatPoint3D_h
+
+#if ENABLE(SVG)
+
+namespace WebCore {
+
+class FloatPoint3D {
+public:
+ FloatPoint3D();
+ FloatPoint3D(float x, float y, float z);
+
+ float x() const;
+ void setX(float x);
+
+ float y() const;
+ void setY(float y);
+
+ float z() const;
+ void setZ(float z);
+
+ void normalize();
+
+private:
+ float m_x;
+ float m_y;
+ float m_z;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // FloatPoint3D_h
diff --git a/WebCore/platform/graphics/FloatRect.cpp b/WebCore/platform/graphics/FloatRect.cpp
new file mode 100644
index 0000000..bb604d1
--- /dev/null
+++ b/WebCore/platform/graphics/FloatRect.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 "FloatConversion.h"
+#include "IntRect.h"
+#include <algorithm>
+
+using std::max;
+using std::min;
+
+namespace WebCore {
+
+FloatRect::FloatRect(const IntRect& r) : m_location(r.location()), m_size(r.size())
+{
+}
+
+FloatRect FloatRect::narrowPrecision(double x, double y, double width, double height)
+{
+ return FloatRect(narrowPrecisionToFloat(x), narrowPrecisionToFloat(y), narrowPrecisionToFloat(width), narrowPrecisionToFloat(height));
+}
+
+bool FloatRect::intersects(const FloatRect& other) const
+{
+ // Checking emptiness handles negative widths as well as zero.
+ return !isEmpty() && !other.isEmpty()
+ && x() < other.right() && other.x() < right()
+ && y() < other.bottom() && other.y() < bottom();
+}
+
+bool FloatRect::contains(const FloatRect& other) const
+{
+ return x() <= other.x() && right() >= other.right()
+ && y() <= other.y() && bottom() >= other.bottom();
+}
+
+void FloatRect::intersect(const FloatRect& other)
+{
+ float l = max(x(), other.x());
+ float t = max(y(), other.y());
+ float r = min(right(), other.right());
+ float b = min(bottom(), other.bottom());
+
+ // Return a clean empty rectangle for non-intersecting cases.
+ if (l >= r || t >= b) {
+ l = 0;
+ t = 0;
+ r = 0;
+ b = 0;
+ }
+
+ m_location.setX(l);
+ m_location.setY(t);
+ m_size.setWidth(r - l);
+ m_size.setHeight(b - t);
+}
+
+void FloatRect::unite(const FloatRect& other)
+{
+ // Handle empty special cases first.
+ if (other.isEmpty())
+ return;
+ if (isEmpty()) {
+ *this = other;
+ return;
+ }
+
+ float l = min(x(), other.x());
+ float t = min(y(), other.y());
+ float r = max(right(), other.right());
+ float b = max(bottom(), other.bottom());
+
+ m_location.setX(l);
+ m_location.setY(t);
+ m_size.setWidth(r - l);
+ m_size.setHeight(b - t);
+}
+
+void FloatRect::scale(float s)
+{
+ m_location.setX(x() * s);
+ m_location.setY(y() * s);
+ m_size.setWidth(width() * s);
+ m_size.setHeight(height() * s);
+}
+
+IntRect enclosingIntRect(const FloatRect& rect)
+{
+ int l = static_cast<int>(rect.x());
+ int t = static_cast<int>(rect.y());
+ // FIXME: These two need to be a "ceiling" operation, not rounding.
+ // We changed them to do "+ 0.5f" to compile on Win32 where there's
+ // no ceilf, but they should be changed back to "ceiling" at some point
+ // and we should provide an implementation of ceilf for Win32.
+ int r = static_cast<int>(rect.right() + 0.5f);
+ int b = static_cast<int>(rect.bottom() + 0.5f);
+ return IntRect(l, t, r - l, b - t);
+}
+
+}
diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h
new file mode 100644
index 0000000..867813d
--- /dev/null
+++ b/WebCore/platform/graphics/FloatRect.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 FloatRect_h
+#define FloatRect_h
+
+#include "FloatPoint.h"
+
+#if PLATFORM(CG)
+typedef struct CGRect CGRect;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+typedef struct CGRect NSRect;
+#else
+typedef struct _NSRect NSRect;
+#endif
+#endif
+
+#if PLATFORM(QT)
+class QRectF;
+#endif
+
+#if PLATFORM(WX) && USE(WXGC)
+class wxRect2DDouble;
+#endif
+
+namespace WebCore {
+
+class IntRect;
+
+class FloatRect {
+public:
+ FloatRect() { }
+ FloatRect(const FloatPoint& location, const FloatSize& size)
+ : m_location(location), m_size(size) { }
+ FloatRect(float x, float y, float width, float height)
+ : m_location(FloatPoint(x, y)), m_size(FloatSize(width, height)) { }
+ FloatRect(const IntRect&);
+
+ static FloatRect narrowPrecision(double x, double y, double width, double height);
+
+ FloatPoint location() const { return m_location; }
+ FloatSize size() const { return m_size; }
+
+ void setLocation(const FloatPoint& location) { m_location = location; }
+ void setSize(const FloatSize& size) { m_size = size; }
+
+ float x() const { return m_location.x(); }
+ float y() const { return m_location.y(); }
+ float width() const { return m_size.width(); }
+ float height() const { return m_size.height(); }
+
+ void setX(float x) { m_location.setX(x); }
+ void setY(float y) { m_location.setY(y); }
+ void setWidth(float width) { m_size.setWidth(width); }
+ void setHeight(float height) { m_size.setHeight(height); }
+
+ bool isEmpty() const { return m_size.isEmpty(); }
+
+ float right() const { return x() + width(); }
+ float bottom() const { return y() + height(); }
+
+ void move(const FloatSize& delta) { m_location += delta; }
+ void move(float dx, float dy) { m_location.move(dx, dy); }
+
+ bool intersects(const FloatRect&) const;
+ bool contains(const FloatRect&) const;
+
+ void intersect(const FloatRect&);
+ void unite(const FloatRect&);
+
+ // Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version
+ // is really checking for containment of 1x1 rect, but that doesn't make sense with floats.
+ bool contains(float px, float py) const
+ { return px >= x() && px <= right() && py >= y() && py <= bottom(); }
+ bool contains(const FloatPoint& point) const { return contains(point.x(), point.y()); }
+
+
+ void inflateX(float dx) {
+ m_location.setX(m_location.x() - dx);
+ m_size.setWidth(m_size.width() + dx + dx);
+ }
+ void inflateY(float dy) {
+ m_location.setY(m_location.y() - dy);
+ m_size.setHeight(m_size.height() + dy + dy);
+ }
+ void inflate(float d) { inflateX(d); inflateY(d); }
+ void scale(float s);
+
+#if PLATFORM(CG)
+ FloatRect(const CGRect&);
+ operator CGRect() const;
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+ FloatRect(const NSRect&);
+ operator NSRect() const;
+#endif
+
+#if PLATFORM(QT)
+ FloatRect(const QRectF&);
+ operator QRectF() const;
+#endif
+#if PLATFORM(SYMBIAN)
+ FloatRect(const TRect&);
+ operator TRect() const;
+ TRect rect() const;
+#endif
+
+#if PLATFORM(WX) && USE(WXGC)
+ FloatRect(const wxRect2DDouble&);
+ operator wxRect2DDouble() const;
+#endif
+
+private:
+ FloatPoint m_location;
+ FloatSize m_size;
+};
+
+inline FloatRect intersection(const FloatRect& a, const FloatRect& b)
+{
+ FloatRect c = a;
+ c.intersect(b);
+ return c;
+}
+
+inline FloatRect unionRect(const FloatRect& a, const FloatRect& b)
+{
+ FloatRect c = a;
+ c.unite(b);
+ return c;
+}
+
+inline bool operator==(const FloatRect& a, const FloatRect& b)
+{
+ return a.location() == b.location() && a.size() == b.size();
+}
+
+inline bool operator!=(const FloatRect& a, const FloatRect& b)
+{
+ return a.location() != b.location() || a.size() != b.size();
+}
+
+IntRect enclosingIntRect(const FloatRect&);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/FloatSize.cpp b/WebCore/platform/graphics/FloatSize.cpp
new file mode 100644
index 0000000..86fa4c0
--- /dev/null
+++ b/WebCore/platform/graphics/FloatSize.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 "FloatSize.h"
+
+#include "FloatConversion.h"
+#include "IntSize.h"
+
+namespace WebCore {
+
+FloatSize::FloatSize(const IntSize& size) : m_width(size.width()), m_height(size.height())
+{
+}
+
+FloatSize FloatSize::narrowPrecision(double width, double height)
+{
+ return FloatSize(narrowPrecisionToFloat(width), narrowPrecisionToFloat(height));
+}
+
+}
diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h
new file mode 100644
index 0000000..cf1e1c5
--- /dev/null
+++ b/WebCore/platform/graphics/FloatSize.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 FloatSize_h
+#define FloatSize_h
+
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGSize CGSize;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+typedef struct CGSize NSSize;
+#else
+typedef struct _NSSize NSSize;
+#endif
+#endif
+
+namespace WebCore {
+
+class IntSize;
+
+class FloatSize {
+public:
+ FloatSize() : m_width(0), m_height(0) { }
+ FloatSize(float width, float height) : m_width(width), m_height(height) { }
+ FloatSize(const IntSize&);
+
+ static FloatSize narrowPrecision(double width, double height);
+
+ float width() const { return m_width; }
+ float height() const { return m_height; }
+
+ void setWidth(float width) { m_width = width; }
+ void setHeight(float height) { m_height = height; }
+
+ bool isEmpty() const { return m_width <= 0 || m_height <= 0; }
+
+ FloatSize expandedTo(const FloatSize& other) const
+ {
+ return FloatSize(m_width > other.m_width ? m_width : other.m_width,
+ m_height > other.m_height ? m_height : other.m_height);
+ }
+
+#if PLATFORM(CG)
+ explicit FloatSize(const CGSize&); // don't do this implicitly since it's lossy
+ operator CGSize() const;
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+ explicit FloatSize(const NSSize &); // don't do this implicitly since it's lossy
+ operator NSSize() const;
+#endif
+
+private:
+ float m_width, m_height;
+};
+
+inline FloatSize& operator+=(FloatSize& a, const FloatSize& b)
+{
+ a.setWidth(a.width() + b.width());
+ a.setHeight(a.height() + b.height());
+ return a;
+}
+
+inline FloatSize& operator-=(FloatSize& a, const FloatSize& b)
+{
+ a.setWidth(a.width() - b.width());
+ a.setHeight(a.height() - b.height());
+ return a;
+}
+
+inline FloatSize operator+(const FloatSize& a, const FloatSize& b)
+{
+ return FloatSize(a.width() + b.width(), a.height() + b.height());
+}
+
+inline FloatSize operator-(const FloatSize& a, const FloatSize& b)
+{
+ return FloatSize(a.width() - b.width(), a.height() - b.height());
+}
+
+inline FloatSize operator-(const FloatSize& size)
+{
+ return FloatSize(-size.width(), -size.height());
+}
+
+inline bool operator==(const FloatSize& a, const FloatSize& b)
+{
+ return a.width() == b.width() && a.height() == b.height();
+}
+
+inline bool operator!=(const FloatSize& a, const FloatSize& b)
+{
+ return a.width() != b.width() || a.height() != b.height();
+}
+
+} // namespace WebCore
+
+#endif // FloatSize_h
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
new file mode 100644
index 0000000..05704d3
--- /dev/null
+++ b/WebCore/platform/graphics/Font.cpp
@@ -0,0 +1,809 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "CharacterNames.h"
+#include "FloatRect.h"
+#include "FontCache.h"
+#include "FontFallbackList.h"
+#include "IntPoint.h"
+#include "GlyphBuffer.h"
+#include <wtf/unicode/Unicode.h>
+#include <wtf/MathExtras.h>
+
+#if USE(ICU_UNICODE)
+#include <unicode/unorm.h>
+#endif
+
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+// According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
+const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
+
+const uint8_t Font::gRoundingHackCharacterTable[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+Font::CodePath Font::codePath = Auto;
+
+struct WidthIterator {
+ WidthIterator(const Font* font, const TextRun& run);
+
+ void advance(int to, GlyphBuffer* glyphBuffer = 0);
+ bool advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer = 0);
+
+ const Font* m_font;
+
+ const TextRun& m_run;
+ int m_end;
+
+ unsigned m_currentCharacter;
+ float m_runWidthSoFar;
+ float m_padding;
+ float m_padPerSpace;
+ float m_finalRoundingWidth;
+
+private:
+ UChar32 normalizeVoicingMarks(int currentCharacter);
+};
+
+WidthIterator::WidthIterator(const Font* font, const TextRun& run)
+ : m_font(font)
+ , m_run(run)
+ , m_end(run.length())
+ , m_currentCharacter(0)
+ , m_runWidthSoFar(0)
+ , m_finalRoundingWidth(0)
+{
+ // If the padding is non-zero, count the number of spaces in the run
+ // and divide that by the padding for per space addition.
+ m_padding = m_run.padding();
+ if (!m_padding)
+ m_padPerSpace = 0;
+ else {
+ float numSpaces = 0;
+ for (int i = 0; i < run.length(); i++)
+ if (Font::treatAsSpace(m_run[i]))
+ numSpaces++;
+
+ if (numSpaces == 0)
+ m_padPerSpace = 0;
+ else
+ m_padPerSpace = ceilf(m_run.padding() / numSpaces);
+ }
+}
+
+void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
+{
+ if (offset > m_end)
+ offset = m_end;
+
+ int currentCharacter = m_currentCharacter;
+ const UChar* cp = m_run.data(currentCharacter);
+
+ bool rtl = m_run.rtl();
+ bool hasExtraSpacing = m_font->letterSpacing() || m_font->wordSpacing() || m_padding;
+
+ float runWidthSoFar = m_runWidthSoFar;
+ float lastRoundingWidth = m_finalRoundingWidth;
+
+ while (currentCharacter < offset) {
+ UChar32 c = *cp;
+ unsigned clusterLength = 1;
+ if (c >= 0x3041) {
+ if (c <= 0x30FE) {
+ // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
+ // Normalize into composed form, and then look for glyph with base + combined mark.
+ // Check above for character range to minimize performance impact.
+ UChar32 normalized = normalizeVoicingMarks(currentCharacter);
+ if (normalized) {
+ c = normalized;
+ clusterLength = 2;
+ }
+ } else if (U16_IS_SURROGATE(c)) {
+ if (!U16_IS_SURROGATE_LEAD(c))
+ break;
+
+ // Do we have a surrogate pair? If so, determine the full Unicode (32 bit)
+ // code point before glyph lookup.
+ // Make sure we have another character and it's a low surrogate.
+ if (currentCharacter + 1 >= m_run.length())
+ break;
+ UChar low = cp[1];
+ if (!U16_IS_TRAIL(low))
+ break;
+ c = U16_GET_SUPPLEMENTARY(c, low);
+ clusterLength = 2;
+ }
+ }
+
+ const GlyphData& glyphData = m_font->glyphDataForCharacter(c, rtl);
+ Glyph glyph = glyphData.glyph;
+ const SimpleFontData* fontData = glyphData.fontData;
+
+ ASSERT(fontData);
+
+ // Now that we have a glyph and font data, get its width.
+ float width;
+ if (c == '\t' && m_run.allowTabs()) {
+ float tabWidth = m_font->tabWidth();
+ width = tabWidth - fmodf(m_run.xPos() + runWidthSoFar, tabWidth);
+ } else {
+ width = fontData->widthForGlyph(glyph);
+ // We special case spaces in two ways when applying word rounding.
+ // First, we round spaces to an adjusted width in all fonts.
+ // Second, in fixed-pitch fonts we ensure that all characters that
+ // match the width of the space character have the same width as the space character.
+ if (width == fontData->m_spaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding())
+ width = fontData->m_adjustedSpaceWidth;
+ }
+
+ if (hasExtraSpacing && !m_run.spacingDisabled()) {
+ // Account for letter-spacing.
+ if (width && m_font->letterSpacing())
+ width += m_font->letterSpacing();
+
+ if (Font::treatAsSpace(c)) {
+ // Account for padding. WebCore uses space padding to justify text.
+ // We distribute the specified padding over the available spaces in the run.
+ if (m_padding) {
+ // Use left over padding if not evenly divisible by number of spaces.
+ if (m_padding < m_padPerSpace) {
+ width += m_padding;
+ m_padding = 0;
+ } else {
+ width += m_padPerSpace;
+ m_padding -= m_padPerSpace;
+ }
+ }
+
+ // Account for word spacing.
+ // We apply additional space between "words" by adding width to the space character.
+ if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
+ width += m_font->wordSpacing();
+ }
+ }
+
+ // Advance past the character we just dealt with.
+ cp += clusterLength;
+ currentCharacter += clusterLength;
+
+ // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters
+ // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
+ // We adjust the width of the last character of a "word" to ensure an integer width.
+ // If we move KHTML to floats we can remove this (and related) hacks.
+
+ float oldWidth = width;
+
+ // Force characters that are used to determine word boundaries for the rounding hack
+ // to be integer width, so following words will start on an integer boundary.
+ if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c))
+ width = ceilf(width);
+
+ // Check to see if the next character is a "rounding hack character", if so, adjust
+ // width so that the total run width will be on an integer boundary.
+ if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
+ || (m_run.applyRunRounding() && currentCharacter >= m_end)) {
+ float totalWidth = runWidthSoFar + width;
+ width += ceilf(totalWidth) - totalWidth;
+ }
+
+ runWidthSoFar += width;
+
+ if (glyphBuffer)
+ glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
+
+ lastRoundingWidth = width - oldWidth;
+ }
+
+ m_currentCharacter = currentCharacter;
+ m_runWidthSoFar = runWidthSoFar;
+ m_finalRoundingWidth = lastRoundingWidth;
+}
+
+bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
+{
+ glyphBuffer->clear();
+ advance(m_currentCharacter + 1, glyphBuffer);
+ float w = 0;
+ for (int i = 0; i < glyphBuffer->size(); ++i)
+ w += glyphBuffer->advanceAt(i);
+ width = w;
+ return !glyphBuffer->isEmpty();
+}
+
+UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
+{
+ if (currentCharacter + 1 < m_end) {
+ if (combiningClass(m_run[currentCharacter + 1]) == hiraganaKatakanaVoicingMarksCombiningClass) {
+#if USE(ICU_UNICODE)
+ // Normalize into composed form using 3.2 rules.
+ UChar normalizedCharacters[2] = { 0, 0 };
+ UErrorCode uStatus = U_ZERO_ERROR;
+ int32_t resultLength = unorm_normalize(m_run.data(currentCharacter), 2,
+ UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
+ if (resultLength == 1 && uStatus == 0)
+ return normalizedCharacters[0];
+#elif USE(QT4_UNICODE)
+ QString tmp(reinterpret_cast<const QChar*>(m_run.data(currentCharacter)), 2);
+ QString res = tmp.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2);
+ if (res.length() == 1)
+ return res.at(0).unicode();
+#endif
+ }
+ }
+ return 0;
+}
+
+// ============================================================================================
+// Font Implementation (Cross-Platform Portion)
+// ============================================================================================
+
+Font::Font()
+ : m_pageZero(0)
+ , m_cachedPrimaryFont(0)
+ , m_letterSpacing(0)
+ , m_wordSpacing(0)
+ , m_isPlatformFont(false)
+{
+}
+
+Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
+ : m_fontDescription(fd)
+ , m_pageZero(0)
+ , m_cachedPrimaryFont(0)
+ , m_letterSpacing(letterSpacing)
+ , m_wordSpacing(wordSpacing)
+ , m_isPlatformFont(false)
+{
+}
+
+Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
+ : m_fontList(new FontFallbackList)
+ , m_pageZero(0)
+ , m_cachedPrimaryFont(0)
+ , m_letterSpacing(0)
+ , m_wordSpacing(0)
+ , m_isPlatformFont(true)
+{
+ m_fontDescription.setUsePrinterFont(isPrinterFont);
+ m_fontList->setPlatformFont(fontData);
+}
+
+Font::Font(const Font& other)
+ : m_fontDescription(other.m_fontDescription)
+ , m_fontList(other.m_fontList)
+ , m_pages(other.m_pages)
+ , m_pageZero(other.m_pageZero)
+ , m_cachedPrimaryFont(other.m_cachedPrimaryFont)
+ , m_letterSpacing(other.m_letterSpacing)
+ , m_wordSpacing(other.m_wordSpacing)
+ , m_isPlatformFont(other.m_isPlatformFont)
+{
+}
+
+Font& Font::operator=(const Font& other)
+{
+ m_fontDescription = other.m_fontDescription;
+ m_fontList = other.m_fontList;
+ m_pages = other.m_pages;
+ m_pageZero = other.m_pageZero;
+ m_cachedPrimaryFont = other.m_cachedPrimaryFont;
+ m_letterSpacing = other.m_letterSpacing;
+ m_wordSpacing = other.m_wordSpacing;
+ m_isPlatformFont = other.m_isPlatformFont;
+ return *this;
+}
+
+Font::~Font()
+{
+}
+
+bool Font::operator==(const Font& other) const
+{
+ // Our FontData don't have to be checked, since checking the font description will be fine.
+ // FIXME: This does not work if the font was made with the FontPlatformData constructor.
+ if ((m_fontList && m_fontList->loadingCustomFonts()) ||
+ (other.m_fontList && other.m_fontList->loadingCustomFonts()))
+ return false;
+
+ FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
+ FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
+
+ return first == second
+ && m_fontDescription == other.m_fontDescription
+ && m_letterSpacing == other.m_letterSpacing
+ && m_wordSpacing == other.m_wordSpacing;
+}
+
+const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
+{
+ bool useSmallCapsFont = forceSmallCaps;
+ if (m_fontDescription.smallCaps()) {
+ UChar32 upperC = Unicode::toUpper(c);
+ if (upperC != c) {
+ c = upperC;
+ useSmallCapsFont = true;
+ }
+ }
+
+ if (mirror)
+ c = mirroredChar(c);
+
+ unsigned pageNumber = (c / GlyphPage::size);
+
+ GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
+ if (!node) {
+ node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
+ if (pageNumber)
+ m_pages.set(pageNumber, node);
+ else
+ m_pageZero = node;
+ }
+
+ GlyphPage* page;
+ if (!useSmallCapsFont) {
+ // Fastest loop, for the common case (not small caps).
+ while (true) {
+ page = node->page();
+ if (page) {
+ const GlyphData& data = page->glyphDataForCharacter(c);
+ if (data.fontData)
+ return data;
+ if (node->isSystemFallback())
+ break;
+ }
+
+ // Proceed with the fallback list.
+ node = node->getChild(fontDataAt(node->level()), pageNumber);
+ if (pageNumber)
+ m_pages.set(pageNumber, node);
+ else
+ m_pageZero = node;
+ }
+ } else {
+ while (true) {
+ page = node->page();
+ if (page) {
+ const GlyphData& data = page->glyphDataForCharacter(c);
+ if (data.fontData) {
+ // The smallCapsFontData function should not normally return 0.
+ // But if it does, we will just render the capital letter big.
+ const SimpleFontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
+ if (!smallCapsFontData)
+ return data;
+
+ GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
+ const GlyphData& data = smallCapsNode->page()->glyphDataForCharacter(c);
+ if (data.fontData)
+ return data;
+
+ // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
+ // a font has the lowercase character but the small caps font does not have its uppercase version.
+ return smallCapsFontData->missingGlyphData();
+ }
+
+ if (node->isSystemFallback())
+ break;
+ }
+
+ // Proceed with the fallback list.
+ node = node->getChild(fontDataAt(node->level()), pageNumber);
+ if (pageNumber)
+ m_pages.set(pageNumber, node);
+ else
+ m_pageZero = node;
+ }
+ }
+
+ ASSERT(page);
+ ASSERT(node->isSystemFallback());
+
+ // System fallback is character-dependent. When we get here, we
+ // know that the character in question isn't in the system fallback
+ // font's glyph page. Try to lazily create it here.
+ UChar codeUnits[2];
+ int codeUnitsLength;
+ if (c <= 0xFFFF) {
+ UChar c16 = c;
+ if (Font::treatAsSpace(c16))
+ codeUnits[0] = ' ';
+ else if (Font::treatAsZeroWidthSpace(c16))
+ codeUnits[0] = zeroWidthSpace;
+ else
+ codeUnits[0] = c16;
+ codeUnitsLength = 1;
+ } else {
+ codeUnits[0] = U16_LEAD(c);
+ codeUnits[1] = U16_TRAIL(c);
+ codeUnitsLength = 2;
+ }
+ const SimpleFontData* characterFontData = FontCache::getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
+ if (useSmallCapsFont)
+ characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
+ if (characterFontData) {
+ // Got the fallback glyph and font.
+ GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
+ const GlyphData& data = fallbackPage && fallbackPage->glyphDataForCharacter(c).fontData ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
+ // Cache it so we don't have to do system fallback again next time.
+ if (!useSmallCapsFont)
+ page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
+ return data;
+ }
+
+ // Even system fallback can fail; use the missing glyph in that case.
+ // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
+ const GlyphData& data = primaryFont()->missingGlyphData();
+ if (!useSmallCapsFont)
+ page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
+ return data;
+}
+
+void Font::cachePrimaryFont() const
+{
+ ASSERT(m_fontList);
+ ASSERT(!m_cachedPrimaryFont);
+ m_cachedPrimaryFont = m_fontList->primaryFont(this)->fontDataForCharacter(' ');
+}
+
+const FontData* Font::fontDataAt(unsigned index) const
+{
+ ASSERT(m_fontList);
+ return m_fontList->fontDataAt(this, index);
+}
+
+const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
+{
+ ASSERT(m_fontList);
+ return m_fontList->fontDataForCharacters(this, characters, length);
+}
+
+void Font::update(PassRefPtr<FontSelector> fontSelector) const
+{
+ // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
+ // being reasonably safe (because inherited fonts in the render tree pick up the new
+ // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
+ // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
+ // and could eventually be rectified by using RefPtrs for Fonts themselves.
+ if (!m_fontList)
+ m_fontList = new FontFallbackList();
+ m_fontList->invalidate(fontSelector);
+ m_cachedPrimaryFont = 0;
+ m_pageZero = 0;
+ m_pages.clear();
+}
+
+int Font::width(const TextRun& run) const
+{
+ return lroundf(floatWidth(run));
+}
+
+int Font::ascent() const
+{
+ return primaryFont()->ascent();
+}
+
+int Font::descent() const
+{
+ return primaryFont()->descent();
+}
+
+int Font::lineSpacing() const
+{
+ return primaryFont()->lineSpacing();
+}
+
+float Font::xHeight() const
+{
+ return primaryFont()->xHeight();
+}
+
+unsigned Font::unitsPerEm() const
+{
+ return primaryFont()->unitsPerEm();
+}
+
+int Font::spaceWidth() const
+{
+ return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
+}
+
+bool Font::isFixedPitch() const
+{
+ ASSERT(m_fontList);
+ return m_fontList->isFixedPitch(this);
+}
+
+void Font::setCodePath(CodePath p)
+{
+ codePath = p;
+}
+
+bool Font::canUseGlyphCache(const TextRun& run) const
+{
+ switch (codePath) {
+ case Auto:
+ break;
+ case Simple:
+ return true;
+ case Complex:
+ return false;
+ }
+
+ // Start from 0 since drawing and highlighting also measure the characters before run->from
+ for (int i = 0; i < run.length(); i++) {
+ const UChar c = run[i];
+ if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
+ continue;
+ if (c <= 0x36F)
+ return false;
+
+ if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
+ continue;
+ if (c <= 0x05CF)
+ return false;
+
+ if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
+ continue;
+ if (c <= 0x1059)
+ return false;
+
+ if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
+ continue;
+ if (c <= 0x11FF)
+ return false;
+
+ if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian
+ continue;
+ if (c <= 0x18AF)
+ return false;
+
+ if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
+ continue;
+ if (c <= 0x194F)
+ return false;
+
+ if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
+ continue;
+ if (c <= 0x20FF)
+ return false;
+
+ if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
+ continue;
+ if (c <= 0xFE2F)
+ return false;
+ }
+
+ return true;
+
+}
+
+void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // This glyph buffer holds our glyphs+advances+font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x();
+ WidthIterator it(this, run);
+ it.advance(from);
+ float beforeWidth = it.m_runWidthSoFar;
+ it.advance(to, &glyphBuffer);
+
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return;
+
+ float afterWidth = it.m_runWidthSoFar;
+
+ if (run.rtl()) {
+ float finalRoundingWidth = it.m_finalRoundingWidth;
+ it.advance(run.length());
+ startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
+ } else
+ startX += beforeWidth;
+
+ // Swap the order of the glyphs if right-to-left.
+ if (run.rtl())
+ for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
+ glyphBuffer.swap(i, end);
+
+ // Calculate the starting point of the glyphs to be displayed by adding
+ // all the advances up to the first glyph.
+ FloatPoint startPoint(startX, point.y());
+ drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+}
+
+void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer,
+ const TextRun& run, const FloatPoint& point) const
+{
+ // Draw each contiguous run of glyphs that use the same font data.
+ const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
+ FloatSize offset = glyphBuffer.offsetAt(0);
+ FloatPoint startPoint(point);
+ float nextX = startPoint.x();
+ int lastFrom = 0;
+ int nextGlyph = 0;
+ while (nextGlyph < glyphBuffer.size()) {
+ const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
+ FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
+ if (nextFontData != fontData || nextOffset != offset) {
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+
+ lastFrom = nextGlyph;
+ fontData = nextFontData;
+ offset = nextOffset;
+ startPoint.setX(nextX);
+ }
+ nextX += glyphBuffer.advanceAt(nextGlyph);
+ nextGlyph++;
+ }
+
+ drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
+}
+
+void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // Don't draw anything while we are using custom fonts that are in the process of loading.
+ if (m_fontList && m_fontList->loadingCustomFonts())
+ return;
+
+ to = (to == -1 ? run.length() : to);
+
+#if ENABLE(SVG_FONTS)
+ if (primaryFont()->isSVGFont()) {
+ drawTextUsingSVGFont(context, run, point, from, to);
+ return;
+ }
+#endif
+
+ if (canUseGlyphCache(run))
+ drawSimpleText(context, run, point, from, to);
+ else
+ drawComplexText(context, run, point, from, to);
+}
+
+float Font::floatWidth(const TextRun& run) const
+{
+#if ENABLE(SVG_FONTS)
+ if (primaryFont()->isSVGFont())
+ return floatWidthUsingSVGFont(run);
+#endif
+
+ if (canUseGlyphCache(run))
+ return floatWidthForSimpleText(run, 0);
+ return floatWidthForComplexText(run);
+}
+
+float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer) const
+{
+ WidthIterator it(this, run);
+ it.advance(run.length(), glyphBuffer);
+ return it.m_runWidthSoFar;
+}
+
+FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
+{
+#if ENABLE(SVG_FONTS)
+ if (primaryFont()->isSVGFont())
+ return selectionRectForTextUsingSVGFont(run, point, h, from, to);
+#endif
+
+ to = (to == -1 ? run.length() : to);
+ if (canUseGlyphCache(run))
+ return selectionRectForSimpleText(run, point, h, from, to);
+ return selectionRectForComplexText(run, point, h, from, to);
+}
+
+FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
+{
+ WidthIterator it(this, run);
+ it.advance(from);
+ float beforeWidth = it.m_runWidthSoFar;
+ it.advance(to);
+ float afterWidth = it.m_runWidthSoFar;
+
+ // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
+ if (run.rtl()) {
+ it.advance(run.length());
+ float totalWidth = it.m_runWidthSoFar;
+ return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
+ } else {
+ return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
+ }
+}
+
+int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+#if ENABLE(SVG_FONTS)
+ if (primaryFont()->isSVGFont())
+ return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
+#endif
+
+ if (canUseGlyphCache(run))
+ return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
+ return offsetForPositionForComplexText(run, x, includePartialGlyphs);
+}
+
+int Font::offsetForPositionForSimpleText(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+ float delta = (float)x;
+
+ WidthIterator it(this, run);
+ GlyphBuffer localGlyphBuffer;
+ unsigned offset;
+ if (run.rtl()) {
+ delta -= floatWidthForSimpleText(run, 0);
+ while (1) {
+ offset = it.m_currentCharacter;
+ float w;
+ if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+ break;
+ delta += w;
+ if (includePartialGlyphs) {
+ if (delta - w / 2 >= 0)
+ break;
+ } else {
+ if (delta >= 0)
+ break;
+ }
+ }
+ } else {
+ while (1) {
+ offset = it.m_currentCharacter;
+ float w;
+ if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+ break;
+ delta -= w;
+ if (includePartialGlyphs) {
+ if (delta + w / 2 <= 0)
+ break;
+ } else {
+ if (delta <= 0)
+ break;
+ }
+ }
+ }
+
+ return offset;
+}
+
+FontSelector* Font::fontSelector() const
+{
+ return m_fontList ? m_fontList->fontSelector() : 0;
+}
+
+}
diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h
new file mode 100644
index 0000000..0ea04eb
--- /dev/null
+++ b/WebCore/platform/graphics/Font.h
@@ -0,0 +1,291 @@
+/*
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006, 2007 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef Font_h
+#define Font_h
+
+#include "FontDescription.h"
+#include <wtf/HashMap.h>
+
+#if PLATFORM(QT)
+#include <QtGui/qfont.h>
+#include <QtGui/qfontmetrics.h>
+#endif
+
+namespace WebCore {
+
+class FloatPoint;
+class FloatRect;
+class FontData;
+class FontFallbackList;
+class FontPlatformData;
+class FontSelector;
+class GlyphBuffer;
+class GlyphPageTreeNode;
+class GraphicsContext;
+class IntPoint;
+class RenderObject;
+class SimpleFontData;
+class SVGPaintServer;
+
+struct GlyphData;
+
+class TextRun {
+public:
+ TextRun(const UChar* c, int len, bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+ bool applyRunRounding = true, bool applyWordRounding = true)
+ : m_characters(c)
+ , m_len(len)
+ , m_allowTabs(allowTabs)
+ , m_xpos(xpos)
+ , m_padding(padding)
+ , m_rtl(rtl)
+ , m_directionalOverride(directionalOverride)
+ , m_applyRunRounding(applyRunRounding)
+ , m_applyWordRounding(applyWordRounding)
+ , m_disableSpacing(false)
+#if ENABLE(SVG_FONTS)
+ , m_referencingRenderObject(0)
+ , m_activePaintServer(0)
+#endif
+ {
+ }
+
+ TextRun(const String& s, bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+ bool applyRunRounding = true, bool applyWordRounding = true)
+ : m_characters(s.characters())
+ , m_len(s.length())
+ , m_allowTabs(allowTabs)
+ , m_xpos(xpos)
+ , m_padding(padding)
+ , m_rtl(rtl)
+ , m_directionalOverride(directionalOverride)
+ , m_applyRunRounding(applyRunRounding)
+ , m_applyWordRounding(applyWordRounding)
+ , m_disableSpacing(false)
+#if ENABLE(SVG_FONTS)
+ , m_referencingRenderObject(0)
+ , m_activePaintServer(0)
+#endif
+ {
+ }
+
+ const UChar operator[](int i) const { return m_characters[i]; }
+ const UChar* data(int i) const { return &m_characters[i]; }
+
+ const UChar* characters() const { return m_characters; }
+ int length() const { return m_len; }
+
+ void setText(const UChar* c, int len) { m_characters = c; m_len = len; }
+
+ bool allowTabs() const { return m_allowTabs; }
+ int xPos() const { return m_xpos; }
+ int padding() const { return m_padding; }
+ bool rtl() const { return m_rtl; }
+ bool ltr() const { return !m_rtl; }
+ bool directionalOverride() const { return m_directionalOverride; }
+ bool applyRunRounding() const { return m_applyRunRounding; }
+ bool applyWordRounding() const { return m_applyWordRounding; }
+ bool spacingDisabled() const { return m_disableSpacing; }
+
+ void disableSpacing() { m_disableSpacing = true; }
+ void disableRoundingHacks() { m_applyRunRounding = m_applyWordRounding = false; }
+ void setRTL(bool b) { m_rtl = b; }
+ void setDirectionalOverride(bool override) { m_directionalOverride = override; }
+
+#if ENABLE(SVG_FONTS)
+ RenderObject* referencingRenderObject() const { return m_referencingRenderObject; }
+ void setReferencingRenderObject(RenderObject* object) { m_referencingRenderObject = object; }
+
+ SVGPaintServer* activePaintServer() const { return m_activePaintServer; }
+ void setActivePaintServer(SVGPaintServer* object) { m_activePaintServer = object; }
+#endif
+
+private:
+ const UChar* m_characters;
+ int m_len;
+
+ bool m_allowTabs;
+ int m_xpos;
+ int m_padding;
+ bool m_rtl;
+ bool m_directionalOverride;
+ bool m_applyRunRounding;
+ bool m_applyWordRounding;
+ bool m_disableSpacing;
+
+#if ENABLE(SVG_FONTS)
+ RenderObject* m_referencingRenderObject;
+ SVGPaintServer* m_activePaintServer;
+#endif
+};
+
+class Font {
+public:
+ Font();
+ Font(const FontDescription&, short letterSpacing, short wordSpacing);
+#if !PLATFORM(QT)
+ Font(const FontPlatformData&, bool isPrinting); // This constructor is only used if the platform wants to start with a native font.
+#endif
+ ~Font();
+
+ Font(const Font&);
+ Font& operator=(const Font&);
+
+ bool operator==(const Font& other) const;
+ bool operator!=(const Font& other) const {
+ return !(*this == other);
+ }
+
+ const FontDescription& fontDescription() const { return m_fontDescription; }
+
+ int pixelSize() const { return fontDescription().computedPixelSize(); }
+ float size() const { return fontDescription().computedSize(); }
+
+ void update(PassRefPtr<FontSelector>) const;
+
+ void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1) const;
+
+ int width(const TextRun&) const;
+ float floatWidth(const TextRun&) const;
+
+ int offsetForPosition(const TextRun&, int position, bool includePartialGlyphs) const;
+ FloatRect selectionRectForText(const TextRun&, const IntPoint&, int h, int from = 0, int to = -1) const;
+
+ bool isSmallCaps() const { return m_fontDescription.smallCaps(); }
+
+ short wordSpacing() const { return m_wordSpacing; }
+ short letterSpacing() const { return m_letterSpacing; }
+#if !PLATFORM(QT)
+ void setWordSpacing(short s) { m_wordSpacing = s; }
+ void setLetterSpacing(short s) { m_letterSpacing = s; }
+#else
+ void setWordSpacing(short s);
+ void setLetterSpacing(short s);
+#endif
+ bool isFixedPitch() const;
+ bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); }
+
+ FontRenderingMode renderingMode() const { return m_fontDescription.renderingMode(); }
+
+ FontFamily& firstFamily() { return m_fontDescription.firstFamily(); }
+ const FontFamily& family() const { return m_fontDescription.family(); }
+
+ bool italic() const { return m_fontDescription.italic(); }
+ unsigned weight() const { return m_fontDescription.weight(); }
+ bool bold() const { return m_fontDescription.bold(); }
+
+#if !PLATFORM(QT)
+ bool isPlatformFont() const { return m_isPlatformFont; }
+#endif
+
+#if PLATFORM(QT)
+ inline const QFont &font() const { return m_font; }
+ inline const QFont &scFont() const { return m_scFont; }
+#endif
+
+ // Metrics that we query the FontFallbackList for.
+ int ascent() const;
+ int descent() const;
+ int height() const { return ascent() + descent(); }
+ int lineSpacing() const;
+ float xHeight() const;
+ unsigned unitsPerEm() const;
+ int spaceWidth() const;
+ int tabWidth() const { return 8 * spaceWidth(); }
+
+#if !PLATFORM(QT)
+ const SimpleFontData* primaryFont() const {
+ if (!m_cachedPrimaryFont)
+ cachePrimaryFont();
+ return m_cachedPrimaryFont;
+ }
+
+ const FontData* fontDataAt(unsigned) const;
+ const GlyphData& glyphDataForCharacter(UChar32, bool mirror, bool forceSmallCaps = false) const;
+ // Used for complex text, and does not utilize the glyph map cache.
+ const FontData* fontDataForCharacters(const UChar*, int length) const;
+
+private:
+ bool canUseGlyphCache(const TextRun&) const;
+ void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
+#if ENABLE(SVG_FONTS)
+ void drawTextUsingSVGFont(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
+ float floatWidthUsingSVGFont(const TextRun&) const;
+ FloatRect selectionRectForTextUsingSVGFont(const TextRun&, const IntPoint&, int h, int from, int to) const;
+ int offsetForPositionForTextUsingSVGFont(const TextRun&, int position, bool includePartialGlyphs) const;
+#endif
+ void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
+ void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const;
+ void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
+ float floatWidthForSimpleText(const TextRun&, GlyphBuffer*) const;
+ float floatWidthForComplexText(const TextRun&) const;
+ int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const;
+ int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const;
+ FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const;
+ FloatRect selectionRectForComplexText(const TextRun&, const IntPoint&, int h, int from, int to) const;
+ void cachePrimaryFont() const;
+#endif
+ friend struct WidthIterator;
+
+ // Useful for debugging the different font rendering code paths.
+public:
+#if !PLATFORM(QT)
+ enum CodePath { Auto, Simple, Complex };
+ static void setCodePath(CodePath);
+ static CodePath codePath;
+
+ static const uint8_t gRoundingHackCharacterTable[256];
+ static bool isRoundingHackCharacter(UChar32 c)
+ {
+ return (((c & ~0xFF) == 0 && gRoundingHackCharacterTable[c]));
+ }
+
+ FontSelector* fontSelector() const;
+#endif
+ static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; }
+ static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == 0x200e || c == 0x200f || c >= 0x202a && c <= 0x202e; }
+private:
+ FontDescription m_fontDescription;
+#if !PLATFORM(QT)
+ mutable RefPtr<FontFallbackList> m_fontList;
+ mutable HashMap<int, GlyphPageTreeNode*> m_pages;
+ mutable GlyphPageTreeNode* m_pageZero;
+ mutable const SimpleFontData* m_cachedPrimaryFont;
+#endif
+ short m_letterSpacing;
+ short m_wordSpacing;
+#if !PLATFORM(QT)
+ bool m_isPlatformFont;
+#else
+ QFont m_font;
+ QFont m_scFont;
+ int m_spaceWidth;
+#endif
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/FontCache.cpp b/WebCore/platform/graphics/FontCache.cpp
new file mode 100644
index 0000000..6abbb2e
--- /dev/null
+++ b/WebCore/platform/graphics/FontCache.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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 "FontFallbackList.h"
+#include "FontPlatformData.h"
+#include "FontSelector.h"
+#include "StringHash.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+struct FontPlatformDataCacheKey {
+ FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, bool bold = false, bool italic = false,
+ bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode)
+ : m_family(family)
+ , m_size(size)
+ , m_bold(bold)
+ , m_italic(italic)
+ , m_printerFont(isPrinterFont)
+ , m_renderingMode(renderingMode)
+ {
+ }
+
+ bool operator==(const FontPlatformDataCacheKey& other) const
+ {
+ return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size &&
+ m_bold == other.m_bold && m_italic == other.m_italic && m_printerFont == other.m_printerFont &&
+ m_renderingMode == other.m_renderingMode;
+ }
+
+ AtomicString m_family;
+ unsigned m_size;
+ bool m_bold;
+ bool m_italic;
+ bool m_printerFont;
+ FontRenderingMode m_renderingMode;
+};
+
+inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
+{
+ unsigned hashCodes[4] = {
+ CaseFoldingHash::hash(fontKey.m_family),
+ fontKey.m_size,
+ static_cast<unsigned>(fontKey.m_bold) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 |
+ static_cast<unsigned>(fontKey.m_renderingMode)
+ };
+ return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), 4 * sizeof(unsigned) / sizeof(UChar));
+}
+
+struct FontPlatformDataCacheKeyHash {
+ static unsigned hash(const FontPlatformDataCacheKey& font)
+ {
+ return computeHash(font);
+ }
+
+ static bool equal(const FontPlatformDataCacheKey& a, const FontPlatformDataCacheKey& b)
+ {
+ return a == b;
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+struct FontPlatformDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformDataCacheKey> {
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ static const FontPlatformDataCacheKey& deletedValue()
+ {
+ static FontPlatformDataCacheKey key(nullAtom, 0xFFFFFFFFU, false, false);
+ return key;
+ }
+ static const FontPlatformDataCacheKey& emptyValue()
+ {
+ static FontPlatformDataCacheKey key(nullAtom, 0, false, false);
+ return key;
+ }
+};
+
+typedef HashMap<FontPlatformDataCacheKey, FontPlatformData*, FontPlatformDataCacheKeyHash, FontPlatformDataCacheKeyTraits> FontPlatformDataCache;
+
+static FontPlatformDataCache* gFontPlatformDataCache = 0;
+
+static const AtomicString& alternateFamilyName(const AtomicString& familyName)
+{
+ // Alias Courier <-> Courier New
+ static AtomicString courier("Courier"), courierNew("Courier New");
+ if (equalIgnoringCase(familyName, courier))
+ return courierNew;
+ if (equalIgnoringCase(familyName, courierNew))
+ return courier;
+
+ // Alias Times and Times New Roman.
+ static AtomicString times("Times"), timesNewRoman("Times New Roman");
+ if (equalIgnoringCase(familyName, times))
+ return timesNewRoman;
+ if (equalIgnoringCase(familyName, timesNewRoman))
+ return times;
+
+ // Alias Arial and Helvetica
+ static AtomicString arial("Arial"), helvetica("Helvetica");
+ if (equalIgnoringCase(familyName, arial))
+ return helvetica;
+ if (equalIgnoringCase(familyName, helvetica))
+ return arial;
+
+ return emptyAtom;
+}
+
+FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription,
+ const AtomicString& familyName,
+ bool checkingAlternateName)
+{
+ if (!gFontPlatformDataCache) {
+ gFontPlatformDataCache = new FontPlatformDataCache;
+ platformInit();
+ }
+
+ FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.bold(), fontDescription.italic(),
+ fontDescription.usePrinterFont(), fontDescription.renderingMode());
+ FontPlatformData* result = 0;
+ bool foundResult;
+ FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
+ if (it == gFontPlatformDataCache->end()) {
+ result = createFontPlatformData(fontDescription, familyName);
+ gFontPlatformDataCache->set(key, result);
+ foundResult = result;
+ } else {
+ result = it->second;
+ foundResult = true;
+ }
+
+ if (!foundResult && !checkingAlternateName) {
+ // We were unable to find a font. We have a small set of fonts that we alias to other names,
+ // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name.
+ const AtomicString& alternateName = alternateFamilyName(familyName);
+ if (!alternateName.isEmpty())
+ result = getCachedFontPlatformData(fontDescription, alternateName, true);
+ if (result)
+ gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name.
+ }
+
+ return result;
+}
+
+struct FontDataCacheKeyHash {
+ static unsigned hash(const FontPlatformData& platformData)
+ {
+ return platformData.hash();
+ }
+
+ static bool equal(const FontPlatformData& a, const FontPlatformData& b)
+ {
+ return a == b;
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> {
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ static const FontPlatformData& deletedValue()
+ {
+ static FontPlatformData key = FontPlatformData::Deleted();
+ return key;
+ }
+ static const FontPlatformData& emptyValue()
+ {
+ static FontPlatformData key;
+ return key;
+ }
+};
+
+typedef HashMap<FontPlatformData, SimpleFontData*, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache;
+
+static FontDataCache* gFontDataCache = 0;
+
+SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData)
+{
+ if (!platformData)
+ return 0;
+
+ if (!gFontDataCache)
+ gFontDataCache = new FontDataCache;
+
+ SimpleFontData* result = gFontDataCache->get(*platformData);
+ if (!result) {
+ result = new SimpleFontData(*platformData);
+ gFontDataCache->set(*platformData, result);
+ }
+
+ return result;
+}
+
+const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector)
+{
+ FontPlatformData* result = 0;
+
+ int startIndex = familyIndex;
+ const FontFamily* startFamily = &font.fontDescription().family();
+ for (int i = 0; startFamily && i < startIndex; i++)
+ startFamily = startFamily->next();
+ const FontFamily* currFamily = startFamily;
+ while (currFamily && !result) {
+ familyIndex++;
+ if (currFamily->family().length()) {
+ if (fontSelector) {
+ FontData* data = fontSelector->getFontData(font.fontDescription(), currFamily->family());
+ if (data)
+ return data;
+ }
+ result = getCachedFontPlatformData(font.fontDescription(), currFamily->family());
+ }
+ currFamily = currFamily->next();
+ }
+
+ if (!currFamily)
+ familyIndex = cAllFamiliesScanned;
+
+ if (!result)
+ // We didn't find a font. Try to find a similar font using our own specific knowledge about our platform.
+ // For example on OS X, we know to map any families containing the words Arabic, Pashto, or Urdu to the
+ // Geeza Pro font.
+ result = getSimilarFontPlatformData(font);
+
+ if (!result && startIndex == 0) {
+ // If it's the primary font that we couldn't find, we try the following. In all other cases, we will
+ // just use per-character system fallback.
+
+ if (fontSelector) {
+ // Try the user's preferred standard font.
+ if (FontData* data = fontSelector->getFontData(font.fontDescription(), "-webkit-standard"))
+ return data;
+ }
+
+ // Still no result. Hand back our last resort fallback font.
+ result = getLastResortFallbackFont(font.fontDescription());
+ }
+
+ // Now that we have a result, we need to go from FontPlatformData -> FontData.
+ return getCachedFontData(result);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h
new file mode 100644
index 0000000..e1a704b
--- /dev/null
+++ b/WebCore/platform/graphics/FontCache.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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.
+ */
+
+#ifndef FontCache_h
+#define FontCache_h
+
+#include <wtf/unicode/Unicode.h>
+
+#if PLATFORM(WIN)
+#include <objidl.h>
+#include <mlang.h>
+#endif
+
+namespace WebCore
+{
+
+class AtomicString;
+class Font;
+class FontPlatformData;
+class FontData;
+class FontDescription;
+class FontSelector;
+class SimpleFontData;
+
+class FontCache {
+public:
+ static const FontData* getFontData(const Font&, int& familyIndex, FontSelector*);
+
+ // This method is implemented by the platform.
+ static const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length);
+
+ // Also implemented by the platform.
+ static void platformInit();
+
+#if PLATFORM(WIN)
+ static IMLangFontLink2* getFontLinkInterface();
+#endif
+
+ static bool fontExists(const FontDescription&, const AtomicString& family);
+
+ static FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false);
+ static SimpleFontData* getCachedFontData(const FontPlatformData*);
+ static FontPlatformData* getLastResortFallbackFont(const FontDescription&);
+
+private:
+ // These methods are implemented by each platform.
+ static FontPlatformData* getSimilarFontPlatformData(const Font&);
+ static FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family);
+
+ friend class SimpleFontData;
+ friend class FontFallbackList;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/FontData.cpp b/WebCore/platform/graphics/FontData.cpp
new file mode 100644
index 0000000..c40e13c
--- /dev/null
+++ b/WebCore/platform/graphics/FontData.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "FontData.h"
+
+namespace WebCore {
+
+FontData::~FontData()
+{
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/FontData.h b/WebCore/platform/graphics/FontData.h
new file mode 100644
index 0000000..352d965
--- /dev/null
+++ b/WebCore/platform/graphics/FontData.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 FontData_h
+#define FontData_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class SimpleFontData;
+
+class FontData : Noncopyable {
+public:
+ virtual ~FontData();
+
+ virtual const SimpleFontData* fontDataForCharacter(UChar32) const = 0;
+ virtual bool containsCharacters(const UChar*, int length) const = 0;
+ virtual bool isCustomFont() const = 0;
+ virtual bool isLoading() const = 0;
+ virtual bool isSegmented() const = 0;
+};
+
+} // namespace WebCore
+
+#endif // FontData_h
diff --git a/WebCore/platform/graphics/FontDescription.h b/WebCore/platform/graphics/FontDescription.h
new file mode 100644
index 0000000..6bb232e
--- /dev/null
+++ b/WebCore/platform/graphics/FontDescription.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003-6 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIother.m_ If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USm_
+ *
+ */
+
+#ifndef FontDescription_h
+#define FontDescription_h
+
+#include "FontFamily.h"
+
+namespace WebCore {
+
+const unsigned cNormalWeight = 50;
+const unsigned cBoldWeight = 63;
+
+// This setting is used to provide ways of switching between multiple rendering modes that may have different
+// metrics. It is used to switch between CG and GDI text on Windows.
+enum FontRenderingMode { NormalRenderingMode, AlternateRenderingMode };
+
+class FontDescription {
+public:
+ enum GenericFamilyType { NoFamily, StandardFamily, SerifFamily, SansSerifFamily,
+ MonospaceFamily, CursiveFamily, FantasyFamily };
+
+ FontDescription()
+ : m_specifiedSize(0), m_computedSize(0),
+ m_italic(false), m_smallCaps(false), m_isAbsoluteSize(false), m_weight(cNormalWeight),
+ m_genericFamily(NoFamily), m_usePrinterFont(false), m_renderingMode(NormalRenderingMode), m_keywordSize(0)
+ {}
+
+ bool operator==(const FontDescription&) const;
+ bool operator!=(const FontDescription& other) const { return !(*this == other); }
+
+ const FontFamily& family() const { return m_familyList; }
+ FontFamily& firstFamily() { return m_familyList; }
+ float specifiedSize() const { return m_specifiedSize; }
+ float computedSize() const { return m_computedSize; }
+ bool italic() const { return m_italic; }
+ bool bold() const { return weight() == cBoldWeight; }
+ int computedPixelSize() const { return int(m_computedSize + 0.5f); }
+ bool smallCaps() const { return m_smallCaps; }
+ bool isAbsoluteSize() const { return m_isAbsoluteSize; }
+ unsigned weight() const { return m_weight; }
+ GenericFamilyType genericFamily() const { return static_cast<GenericFamilyType>(m_genericFamily); }
+ bool usePrinterFont() const { return m_usePrinterFont; }
+ FontRenderingMode renderingMode() const { return static_cast<FontRenderingMode>(m_renderingMode); }
+ int keywordSize() const { return m_keywordSize; }
+
+ void setFamily(const FontFamily& family) { m_familyList = family; }
+ void setComputedSize(float s) { m_computedSize = s; }
+ void setSpecifiedSize(float s) { m_specifiedSize = s; }
+ void setItalic(bool i) { m_italic = i; }
+ void setBold(bool b) { m_weight = (b ? cBoldWeight : cNormalWeight); }
+ void setSmallCaps(bool c) { m_smallCaps = c; }
+ void setIsAbsoluteSize(bool s) { m_isAbsoluteSize = s; }
+ void setWeight(unsigned w) { m_weight = w; }
+ void setGenericFamily(GenericFamilyType genericFamily) { m_genericFamily = genericFamily; }
+ void setUsePrinterFont(bool p) { m_usePrinterFont = p; }
+ void setRenderingMode(FontRenderingMode mode) { m_renderingMode = mode; }
+ void setKeywordSize(int s) { m_keywordSize = s; }
+
+private:
+ FontFamily m_familyList; // The list of font families to be used.
+
+ float m_specifiedSize; // Specified CSS value. Independent of rendering issues such as integer
+ // rounding, minimum font sizes, and zooming.
+ float m_computedSize; // Computed size adjusted for the minimum font size and the zoom factor.
+
+ bool m_italic : 1;
+ bool m_smallCaps : 1;
+ bool m_isAbsoluteSize : 1; // Whether or not CSS specified an explicit size
+ // (logical sizes like "medium" don't count).
+ unsigned m_weight : 8;
+ unsigned m_genericFamily : 3; // GenericFamilyType
+ bool m_usePrinterFont : 1;
+
+ unsigned m_renderingMode : 1; // Used to switch between CG and GDI text on Windows.
+
+ int 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>).
+};
+
+inline bool FontDescription::operator==(const FontDescription& other) const
+{
+ return m_familyList == other.m_familyList
+ && m_specifiedSize == other.m_specifiedSize
+ && m_computedSize == other.m_computedSize
+ && m_italic == other.m_italic
+ && m_smallCaps == other.m_smallCaps
+ && m_isAbsoluteSize == other.m_isAbsoluteSize
+ && m_weight == other.m_weight
+ && m_genericFamily == other.m_genericFamily
+ && m_usePrinterFont == other.m_usePrinterFont
+ && m_renderingMode == other.m_renderingMode
+ && m_keywordSize == other.m_keywordSize;
+}
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/FontFallbackList.cpp b/WebCore/platform/graphics/FontFallbackList.cpp
new file mode 100644
index 0000000..0fdd99c
--- /dev/null
+++ b/WebCore/platform/graphics/FontFallbackList.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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 "FontFallbackList.h"
+
+#include "Font.h"
+#include "FontCache.h"
+#include "SegmentedFontData.h"
+
+namespace WebCore {
+
+FontFallbackList::FontFallbackList()
+ : RefCounted<FontFallbackList>(0)
+ , m_familyIndex(0)
+ , m_pitch(UnknownPitch)
+ , m_loadingCustomFonts(false)
+ , m_fontSelector(0)
+{
+}
+
+void FontFallbackList::invalidate(PassRefPtr<FontSelector> fontSelector)
+{
+ m_fontList.clear();
+ m_familyIndex = 0;
+ m_pitch = UnknownPitch;
+ m_loadingCustomFonts = false;
+ m_fontSelector = fontSelector;
+}
+
+void FontFallbackList::determinePitch(const Font* font) const
+{
+ const FontData* fontData = primaryFont(font);
+ if (!fontData->isSegmented())
+ m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch();
+ else {
+ const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
+ unsigned numRanges = segmentedFontData->numRanges();
+ if (numRanges == 1)
+ m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch();
+ else
+ m_pitch = VariablePitch;
+ }
+}
+
+const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realizedFontIndex) const
+{
+ if (realizedFontIndex < m_fontList.size())
+ return m_fontList[realizedFontIndex]; // This fallback font is already in our list.
+
+ // Make sure we're not passing in some crazy value here.
+ ASSERT(realizedFontIndex == m_fontList.size());
+
+ if (m_familyIndex == cAllFamiliesScanned)
+ return 0;
+
+ // Ask the font cache for the font data.
+ // We are obtaining this font for the first time. We keep track of the families we've looked at before
+ // in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our
+ // |m_familyIndex| as it scans for the right font to make.
+ const FontData* result = FontCache::getFontData(*font, m_familyIndex, m_fontSelector.get());
+ if (result) {
+ m_fontList.append(result);
+ if (result->isLoading())
+ m_loadingCustomFonts = true;
+ }
+ return result;
+}
+
+const FontData* FontFallbackList::fontDataForCharacters(const Font* font, const UChar* characters, int length) const
+{
+ // This method is only called when the primary font does not contain the characters we need.
+ // Begin our search at position 1.
+ unsigned realizedFontIndex = 1;
+ const FontData* fontData = fontDataAt(font, realizedFontIndex);
+ while (fontData && !fontData->containsCharacters(characters, length))
+ fontData = fontDataAt(font, ++realizedFontIndex);
+
+ if (!fontData)
+ fontData = FontCache::getFontDataForCharacters(*font, characters, length);
+
+ return fontData;
+}
+
+void FontFallbackList::setPlatformFont(const FontPlatformData& platformData)
+{
+ m_familyIndex = cAllFamiliesScanned;
+ m_fontList.append(FontCache::getCachedFontData(&platformData));
+}
+
+}
diff --git a/WebCore/platform/graphics/FontFallbackList.h b/WebCore/platform/graphics/FontFallbackList.h
new file mode 100644
index 0000000..38128a2
--- /dev/null
+++ b/WebCore/platform/graphics/FontFallbackList.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// This file has no guards on purpose in order to detect redundant includes. This is a private header
+// and so this may catch someone trying to include this file in public cpp files.
+
+#include "FontSelector.h"
+#include "SimpleFontData.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class Font;
+class GraphicsContext;
+class IntRect;
+class FontDescription;
+class FontPlatformData;
+class FontSelector;
+
+const int cAllFamiliesScanned = -1;
+
+class FontFallbackList : public RefCounted<FontFallbackList> {
+public:
+ FontFallbackList();
+
+ void invalidate(PassRefPtr<FontSelector>);
+
+ bool isFixedPitch(const Font* f) const { if (m_pitch == UnknownPitch) determinePitch(f); return m_pitch == FixedPitch; };
+ void determinePitch(const Font*) const;
+
+ bool loadingCustomFonts() const { return m_loadingCustomFonts; }
+
+ FontSelector* fontSelector() const { return m_fontSelector.get(); }
+
+private:
+ const FontData* primaryFont(const Font* f) const { return fontDataAt(f, 0); }
+ const FontData* fontDataAt(const Font*, unsigned index) const;
+ const FontData* fontDataForCharacters(const Font*, const UChar*, int length) const;
+
+ void setPlatformFont(const FontPlatformData&);
+
+ mutable Vector<const FontData*, 1> m_fontList;
+ mutable int m_familyIndex;
+ mutable Pitch m_pitch;
+ mutable bool m_loadingCustomFonts;
+ RefPtr<FontSelector> m_fontSelector;
+
+ friend class Font;
+};
+
+}
+
diff --git a/WebCore/platform/graphics/FontFamily.cpp b/WebCore/platform/graphics/FontFamily.cpp
new file mode 100644
index 0000000..c87c661
--- /dev/null
+++ b/WebCore/platform/graphics/FontFamily.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004 Apple Computer, 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"
+#include "FontFamily.h"
+
+namespace WebCore {
+
+FontFamily::FontFamily(const FontFamily& other)
+ : RefCounted<FontFamily>(0)
+ , m_family(other.m_family)
+ , m_next(other.m_next)
+{
+}
+
+FontFamily& FontFamily::operator=(const FontFamily& other)
+{
+ m_family = other.m_family;
+ m_next = other.m_next;
+ return *this;
+}
+
+bool FontFamily::operator==(const FontFamily &compareFontFamily) const
+{
+ if ((!m_next && compareFontFamily.m_next) ||
+ (m_next && !compareFontFamily.m_next) ||
+ ((m_next && compareFontFamily.m_next) && (*m_next != *(compareFontFamily.m_next))))
+ return false;
+
+ return m_family == compareFontFamily.m_family;
+}
+
+}
diff --git a/WebCore/platform/graphics/FontFamily.h b/WebCore/platform/graphics/FontFamily.h
new file mode 100644
index 0000000..7a382cc
--- /dev/null
+++ b/WebCore/platform/graphics/FontFamily.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, 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 FontFamily_h
+#define FontFamily_h
+
+#include "AtomicString.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class FontFamily : public RefCounted<FontFamily> {
+public:
+ FontFamily() : RefCounted<FontFamily>(0) { }
+
+ FontFamily(const FontFamily&);
+ FontFamily& operator=(const FontFamily&);
+
+ void setFamily(const AtomicString& family) { m_family = family; }
+ const AtomicString& family() const { return m_family; }
+ bool familyIsEmpty() const { return m_family.isEmpty(); }
+
+ FontFamily* next() { return m_next.get(); }
+ const FontFamily* next() const { return m_next.get(); }
+
+ void appendFamily(PassRefPtr<FontFamily> family) { m_next = family; }
+
+ bool operator==(const FontFamily&) const;
+ bool operator!=(const FontFamily& x) const { return !(*this == x); }
+
+private:
+ AtomicString m_family;
+ RefPtr<FontFamily> m_next;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/FontSelector.h b/WebCore/platform/graphics/FontSelector.h
new file mode 100644
index 0000000..b0e9dfa
--- /dev/null
+++ b/WebCore/platform/graphics/FontSelector.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2007 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 FontSelector_h
+#define FontSelector_h
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class AtomicString;
+class FontData;
+class FontDescription;
+
+class FontSelector : public RefCounted<FontSelector> {
+public:
+ FontSelector() : RefCounted<FontSelector>(0) { }
+ virtual ~FontSelector() { }
+ virtual FontData* getFontData(const FontDescription&, const AtomicString& familyName) = 0;
+};
+
+} // namespace WebCore
+
+#endif // FontSelector_h
diff --git a/WebCore/platform/graphics/GlyphBuffer.h b/WebCore/platform/graphics/GlyphBuffer.h
new file mode 100644
index 0000000..f65996d
--- /dev/null
+++ b/WebCore/platform/graphics/GlyphBuffer.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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.
+ */
+
+#ifndef GlyphBuffer_h
+#define GlyphBuffer_h
+
+#include "FloatSize.h"
+
+#if PLATFORM(CG)
+#include <ApplicationServices/ApplicationServices.h>
+#elif PLATFORM(CAIRO)
+#include <cairo.h>
+#endif
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+typedef unsigned short Glyph;
+class SimpleFontData;
+
+#if PLATFORM(CG)
+typedef Glyph GlyphBufferGlyph;
+typedef CGSize GlyphBufferAdvance;
+#elif PLATFORM(CAIRO)
+typedef cairo_glyph_t GlyphBufferGlyph;
+typedef FloatSize GlyphBufferAdvance;
+#elif PLATFORM(WX)
+typedef Glyph GlyphBufferGlyph;
+typedef FloatSize GlyphBufferAdvance;
+#elif PLATFORM(QT)
+typedef unsigned short GlyphBufferGlyph;
+typedef FloatSize GlyphBufferAdvance;
+#endif
+
+class GlyphBuffer {
+public:
+ bool isEmpty() const { return m_fontData.isEmpty(); }
+ int size() const { return m_fontData.size(); }
+
+ void clear()
+ {
+ m_fontData.clear();
+ m_glyphs.clear();
+ m_advances.clear();
+#if PLATFORM(WIN)
+ m_offsets.clear();
+#endif
+ }
+
+ GlyphBufferGlyph* glyphs(int from) { return m_glyphs.data() + from; }
+ GlyphBufferAdvance* advances(int from) { return m_advances.data() + from; }
+ const GlyphBufferGlyph* glyphs(int from) const { return m_glyphs.data() + from; }
+ const GlyphBufferAdvance* advances(int from) const { return m_advances.data() + from; }
+
+ const SimpleFontData* fontDataAt(int index) const { return m_fontData[index]; }
+
+ void swap(int index1, int index2)
+ {
+ const SimpleFontData* f = m_fontData[index1];
+ m_fontData[index1] = m_fontData[index2];
+ m_fontData[index2] = f;
+
+ GlyphBufferGlyph g = m_glyphs[index1];
+ m_glyphs[index1] = m_glyphs[index2];
+ m_glyphs[index2] = g;
+
+ GlyphBufferAdvance s = m_advances[index1];
+ m_advances[index1] = m_advances[index2];
+ m_advances[index2] = s;
+
+#if PLATFORM(WIN)
+ FloatSize offset = m_offsets[index1];
+ m_offsets[index1] = m_offsets[index2];
+ m_offsets[index2] = offset;
+#endif
+ }
+
+ Glyph glyphAt(int index) const
+ {
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(WX)
+ return m_glyphs[index];
+#elif PLATFORM(CAIRO)
+ return m_glyphs[index].index;
+#endif
+ }
+
+ float advanceAt(int index) const
+ {
+#if PLATFORM(CG)
+ return m_advances[index].width;
+#elif PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
+ return m_advances[index].width();
+#endif
+ }
+
+ FloatSize offsetAt(int index) const
+ {
+#if PLATFORM(WIN)
+ return m_offsets[index];
+#else
+ return FloatSize();
+#endif
+ }
+
+ void add(Glyph glyph, const SimpleFontData* font, float width, const FloatSize* offset = 0)
+ {
+ m_fontData.append(font);
+#if PLATFORM(CG)
+ m_glyphs.append(glyph);
+ CGSize advance;
+ advance.width = width;
+ advance.height = 0;
+ m_advances.append(advance);
+#elif PLATFORM(CAIRO)
+ cairo_glyph_t cairoGlyph;
+ cairoGlyph.index = glyph;
+ m_glyphs.append(cairoGlyph);
+ m_advances.append(FloatSize(width, 0));
+#elif PLATFORM(QT) || PLATFORM(WX)
+ m_glyphs.append(glyph);
+ m_advances.append(FloatSize(width, 0));
+#endif
+#if PLATFORM(WIN)
+ if (offset)
+ m_offsets.append(*offset);
+ else
+ m_offsets.append(FloatSize());
+#endif
+ }
+
+private:
+ Vector<const SimpleFontData*, 2048> m_fontData;
+ Vector<GlyphBufferGlyph, 2048> m_glyphs;
+ Vector<GlyphBufferAdvance, 2048> m_advances;
+#if PLATFORM(WIN)
+ Vector<FloatSize, 2048> m_offsets;
+#endif
+};
+
+}
+#endif
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
new file mode 100644
index 0000000..53c94b8
--- /dev/null
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 "GlyphPageTreeNode.h"
+
+#include "CharacterNames.h"
+#include "SegmentedFontData.h"
+#include "SimpleFontData.h"
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+using std::max;
+using std::min;
+
+HashMap<int, GlyphPageTreeNode*>* GlyphPageTreeNode::roots = 0;
+GlyphPageTreeNode* GlyphPageTreeNode::pageZeroRoot = 0;
+
+GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber)
+{
+ static bool initialized;
+ if (!initialized) {
+ initialized = true;
+ roots = new HashMap<int, GlyphPageTreeNode*>;
+ pageZeroRoot = new GlyphPageTreeNode;
+ }
+
+ GlyphPageTreeNode* node = pageNumber ? roots->get(pageNumber) : pageZeroRoot;
+ if (!node) {
+ node = new GlyphPageTreeNode;
+#ifndef NDEBUG
+ node->m_pageNumber = pageNumber;
+#endif
+ if (pageNumber)
+ roots->set(pageNumber, node);
+ else
+ pageZeroRoot = node;
+ }
+ return node;
+}
+
+void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData)
+{
+ // Enumerate all the roots and prune any tree that contains our custom font data.
+ if (roots) {
+ HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end();
+ for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it)
+ it->second->pruneCustomFontData(fontData);
+ }
+
+ if (pageZeroRoot)
+ pageZeroRoot->pruneCustomFontData(fontData);
+}
+
+GlyphPageTreeNode::~GlyphPageTreeNode()
+{
+ deleteAllValues(m_children);
+ delete m_systemFallbackChild;
+}
+
+void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber)
+{
+ ASSERT(!m_page);
+
+ // This function must not be called for the root of the tree, because that
+ // level does not contain any glyphs.
+ ASSERT(m_level > 0 && m_parent);
+
+ // The parent's page will be 0 if we are level one or the parent's font data
+ // did not contain any glyphs for that page.
+ GlyphPage* parentPage = m_parent->page();
+
+ // NULL FontData means we're being asked for the system fallback font.
+ if (fontData) {
+ if (m_level == 1) {
+ // Children of the root hold pure pages. These will cover only one
+ // font data's glyphs, and will have glyph index 0 if the font data does not
+ // contain the glyph.
+ unsigned start = pageNumber * GlyphPage::size;
+ UChar buffer[GlyphPage::size * 2 + 2];
+ unsigned bufferLength;
+ unsigned i;
+
+ // Fill in a buffer with the entire "page" of characters that we want to look up glyphs for.
+ if (start < 0x10000) {
+ bufferLength = GlyphPage::size;
+ for (i = 0; i < GlyphPage::size; i++)
+ buffer[i] = start + i;
+
+ if (start == 0) {
+ // Control characters must not render at all.
+ for (i = 0; i < 0x20; ++i)
+ buffer[i] = zeroWidthSpace;
+ for (i = 0x7F; i < 0xA0; i++)
+ buffer[i] = zeroWidthSpace;
+
+ // \n, \t, and nonbreaking space must render as a space.
+ buffer[(int)'\n'] = ' ';
+ buffer[(int)'\t'] = ' ';
+ buffer[noBreakSpace] = ' ';
+ } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) {
+ // LRM, RLM, LRE, RLE and PDF must not render at all.
+ buffer[leftToRightMark - start] = zeroWidthSpace;
+ buffer[rightToLeftMark - start] = zeroWidthSpace;
+ buffer[leftToRightEmbed - start] = zeroWidthSpace;
+ buffer[rightToLeftEmbed - start] = zeroWidthSpace;
+ buffer[leftToRightOverride - start] = zeroWidthSpace;
+ buffer[rightToLeftOverride - start] = zeroWidthSpace;
+ buffer[popDirectionalFormatting - start] = zeroWidthSpace;
+ } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
+ // Object replacement character must not render at all.
+ buffer[objectReplacementCharacter - start] = zeroWidthSpace;
+ }
+ } else {
+ bufferLength = GlyphPage::size * 2;
+ for (i = 0; i < GlyphPage::size; i++) {
+ int c = i + start;
+ buffer[i * 2] = U16_LEAD(c);
+ buffer[i * 2 + 1] = U16_TRAIL(c);
+ }
+ }
+
+ m_page = new GlyphPage(this);
+
+ // Now that we have a buffer full of characters, we want to get back an array
+ // of glyph indices. This part involves calling into the platform-specific
+ // routine of our glyph map for actually filling in the page with the glyphs.
+ // Success is not guaranteed. For example, Times fails to fill page 260, giving glyph data
+ // for only 128 out of 256 characters.
+ bool haveGlyphs;
+ if (fontData->isSegmented()) {
+ haveGlyphs = false;
+
+ const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
+ unsigned numRanges = segmentedFontData->numRanges();
+ bool zeroFilled = false;
+ 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);
+ if (from < static_cast<int>(GlyphPage::size) && to > 0) {
+ if (!zeroFilled) {
+ if (from > 0 || to < static_cast<int>(GlyphPage::size)) {
+ for (unsigned i = 0; i < GlyphPage::size; i++)
+ m_page->setGlyphDataForIndex(i, 0, 0);
+ }
+ zeroFilled = true;
+ }
+ haveGlyphs |= m_page->fill(from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData());
+ }
+ }
+ } else
+ haveGlyphs = m_page->fill(0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData));
+
+ if (!haveGlyphs)
+ m_page = 0;
+ } else if (parentPage && parentPage->owner() != m_parent) {
+ // The page we're overriding may not be owned by our parent node.
+ // This happens when our parent node provides no useful overrides
+ // and just copies the pointer to an already-existing page (see
+ // below).
+ //
+ // We want our override to be shared by all nodes that reference
+ // that page to avoid duplication, and so standardize on having the
+ // page's owner collect all the overrides. Call getChild on the
+ // page owner with the desired font data (this will populate
+ // the page) and then reference it.
+ m_page = parentPage->owner()->getChild(fontData, pageNumber)->page();
+ } else {
+ // Get the pure page for the fallback font (at level 1 with no
+ // overrides). getRootChild will always create a page if one
+ // doesn't exist, but the page doesn't necessarily have glyphs
+ // (this pointer may be 0).
+ GlyphPage* fallbackPage = getRootChild(fontData, pageNumber)->page();
+ if (!parentPage) {
+ // When the parent has no glyphs for this page, we can easily
+ // override it just by supplying the glyphs from our font.
+ m_page = fallbackPage;
+ } else if (!fallbackPage) {
+ // When our font has no glyphs for this page, we can just reference the
+ // parent page.
+ m_page = parentPage;
+ } else {
+ // Combine the parent's glyphs and ours to form a new more complete page.
+ m_page = new GlyphPage(this);
+
+ // Overlay the parent page on the fallback page. Check if the fallback font
+ // has added anything.
+ bool newGlyphs = false;
+ for (unsigned i = 0; i < GlyphPage::size; i++) {
+ if (parentPage->m_glyphs[i].glyph)
+ m_page->m_glyphs[i] = parentPage->m_glyphs[i];
+ else if (fallbackPage->m_glyphs[i].glyph) {
+ m_page->m_glyphs[i] = fallbackPage->m_glyphs[i];
+ newGlyphs = true;
+ } else {
+ const GlyphData data = { 0, 0 };
+ m_page->m_glyphs[i] = data;
+ }
+ }
+
+ if (!newGlyphs)
+ // We didn't override anything, so our override is just the parent page.
+ m_page = parentPage;
+ }
+ }
+ } else {
+ m_page = new GlyphPage(this);
+ // System fallback. Initialized with the parent's page here, as individual
+ // entries may use different fonts depending on character. If the Font
+ // ever finds it needs a glyph out of the system fallback page, it will
+ // ask the system for the best font to use and fill that glyph in for us.
+ if (parentPage)
+ memcpy(m_page->m_glyphs, parentPage->m_glyphs, GlyphPage::size * sizeof(m_page->m_glyphs[0]));
+ else {
+ const GlyphData data = { 0, 0 };
+ for (unsigned i = 0; i < GlyphPage::size; i++)
+ m_page->m_glyphs[i] = data;
+ }
+ }
+}
+
+GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigned pageNumber)
+{
+ ASSERT(fontData || !m_isSystemFallback);
+ ASSERT(pageNumber == m_pageNumber);
+
+ GlyphPageTreeNode* child = fontData ? m_children.get(fontData) : m_systemFallbackChild;
+ if (!child) {
+ child = new GlyphPageTreeNode;
+ child->m_parent = this;
+ child->m_level = m_level + 1;
+ if (fontData && fontData->isCustomFont()) {
+ for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent)
+ curr->m_customFontCount++;
+ }
+
+#ifndef NDEBUG
+ child->m_pageNumber = m_pageNumber;
+#endif
+ if (fontData)
+ m_children.set(fontData, child);
+ else {
+ m_systemFallbackChild = child;
+ child->m_isSystemFallback = true;
+ }
+ child->initializePage(fontData, pageNumber);
+ }
+ return child;
+}
+
+void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData)
+{
+ if (!fontData || !m_customFontCount)
+ return;
+
+ // Prune any branch that contains this FontData.
+ GlyphPageTreeNode* node = m_children.get(fontData);
+ if (node) {
+ m_children.remove(fontData);
+ unsigned fontCount = node->m_customFontCount + 1;
+ delete node;
+ for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent)
+ curr->m_customFontCount -= fontCount;
+ }
+
+ // Check any branches that remain that still have custom fonts underneath them.
+ if (!m_customFontCount)
+ return;
+ HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end();
+ for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it)
+ it->second->pruneCustomFontData(fontData);
+}
+
+}
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.h b/WebCore/platform/graphics/GlyphPageTreeNode.h
new file mode 100644
index 0000000..40b8154
--- /dev/null
+++ b/WebCore/platform/graphics/GlyphPageTreeNode.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Computer, 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.
+ * 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.
+ */
+
+#ifndef GlyphPageTreeNode_h
+#define GlyphPageTreeNode_h
+
+#include <wtf/RefCounted.h>
+#include <wtf/unicode/Unicode.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class FontData;
+class GlyphPageTreeNode;
+class SimpleFontData;
+
+typedef unsigned short Glyph;
+
+// Holds the glyph index and the corresponding SimpleFontData information for a given
+// character.
+struct GlyphData {
+ Glyph glyph;
+ const SimpleFontData* fontData;
+};
+
+// A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
+// range of characters in the Unicode code space. GlyphPages are indexed
+// starting from 0 and incrementing for each 256 glyphs.
+//
+// One page may actually include glyphs from other fonts if the characters are
+// missing in the parimary font. It is owned by exactly one GlyphPageTreeNode,
+// although multiple nodes may reference it as their "page" if they are supposed
+// to be overriding the parent's node, but provide no additional information.
+struct GlyphPage : public RefCounted<GlyphPage> {
+ GlyphPage()
+ : RefCounted<GlyphPage>(0)
+ , m_owner(0)
+ {
+ }
+
+ GlyphPage(GlyphPageTreeNode* owner)
+ : RefCounted<GlyphPage>(0)
+ , m_owner(owner)
+ {
+ }
+
+ static const size_t size = 256; // Covers Latin-1 in a single page.
+ GlyphData m_glyphs[size];
+ GlyphPageTreeNode* m_owner;
+
+ const GlyphData& glyphDataForCharacter(UChar32 c) const { return m_glyphs[c % size]; }
+ void setGlyphDataForCharacter(UChar32 c, Glyph g, const SimpleFontData* f)
+ {
+ setGlyphDataForIndex(c % size, g, f);
+ }
+ void setGlyphDataForIndex(unsigned index, Glyph g, const SimpleFontData* f)
+ {
+ ASSERT(index < size);
+ m_glyphs[index].glyph = g;
+ m_glyphs[index].fontData = f;
+ }
+ GlyphPageTreeNode* owner() const { return m_owner; }
+ // Implemented by the platform.
+ bool fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData* fontData);
+};
+
+// The glyph page tree is a data structure that maps (FontData, glyph page number)
+// to a GlyphPage. Level 0 (the "root") is special. There is one root
+// GlyphPageTreeNode for each glyph page number. The roots do not have a
+// GlyphPage associated with them, and their initializePage() function is never
+// called to fill the glyphs.
+//
+// Each root node maps a FontData pointer to another GlyphPageTreeNode at
+// level 1 (the "root child") that stores the actual glyphs for a specific font data.
+// These nodes will only have a GlyphPage if they have glyphs for that range.
+//
+// Levels greater than one correspond to subsequent levels of the fallback list
+// for that font. These levels override their parent's page of glyphs by
+// filling in holes with the new font (thus making a more complete page).
+//
+// A NULL FontData pointer corresponds to the system fallback
+// font. It is tracked separately from the regular pages and overrides so that
+// the glyph pages do not get polluted with these last-resort glyphs. The
+// system fallback page is not populated at construction like the other pages,
+// but on demand for each glyph, because the system may need to use different
+// fallback fonts for each. This lazy population is done by the Font.
+class GlyphPageTreeNode {
+public:
+ GlyphPageTreeNode()
+ : m_parent(0)
+ , m_level(0)
+ , m_isSystemFallback(false)
+ , m_systemFallbackChild(0)
+ , m_customFontCount(0)
+#ifndef NDEBUG
+ , m_pageNumber(0)
+#endif
+ {
+ }
+
+ ~GlyphPageTreeNode();
+
+ static HashMap<int, GlyphPageTreeNode*>* roots;
+ static GlyphPageTreeNode* pageZeroRoot;
+
+ static GlyphPageTreeNode* getRootChild(const FontData* fontData, unsigned pageNumber)
+ {
+ return getRoot(pageNumber)->getChild(fontData, pageNumber);
+ }
+
+ static void pruneTreeCustomFontData(const FontData*);
+
+ void pruneCustomFontData(const FontData*);
+
+ GlyphPageTreeNode* parent() const { return m_parent; }
+ GlyphPageTreeNode* getChild(const FontData*, unsigned pageNumber);
+
+ // Returns a page of glyphs (or NULL if there are no glyphs in this page's character range).
+ GlyphPage* page() const { return m_page.get(); }
+
+ // Returns the level of this node. See class-level comment.
+ unsigned level() const { return m_level; }
+
+ // The system fallback font has special rules (see above).
+ bool isSystemFallback() const { return m_isSystemFallback; }
+
+private:
+ static GlyphPageTreeNode* getRoot(unsigned pageNumber);
+ void initializePage(const FontData*, unsigned pageNumber);
+
+ GlyphPageTreeNode* m_parent;
+ RefPtr<GlyphPage> m_page;
+ unsigned m_level;
+ bool m_isSystemFallback;
+ HashMap<const FontData*, GlyphPageTreeNode*> m_children;
+ GlyphPageTreeNode* m_systemFallbackChild;
+ unsigned m_customFontCount;
+
+#ifndef NDEBUG
+ unsigned m_pageNumber;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // GlyphPageTreeNode_h
diff --git a/WebCore/platform/graphics/GlyphWidthMap.cpp b/WebCore/platform/graphics/GlyphWidthMap.cpp
new file mode 100644
index 0000000..6e8d68d
--- /dev/null
+++ b/WebCore/platform/graphics/GlyphWidthMap.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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 "GlyphWidthMap.h"
+
+namespace WebCore
+{
+
+float GlyphWidthMap::widthForGlyph(Glyph g)
+{
+ unsigned pageNumber = (g / GlyphWidthPage::size);
+ GlyphWidthPage* page = locatePage(pageNumber);
+ if (page)
+ return page->widthForGlyph(g);
+ return cGlyphWidthUnknown;
+}
+
+void GlyphWidthMap::setWidthForGlyph(Glyph glyph, float width)
+{
+ unsigned pageNumber = (glyph / GlyphWidthPage::size);
+ GlyphWidthPage* page = locatePage(pageNumber);
+ if (page)
+ page->setWidthForGlyph(glyph, width);
+}
+
+inline GlyphWidthMap::GlyphWidthPage* GlyphWidthMap::locatePage(unsigned pageNumber)
+{
+ GlyphWidthPage* page;
+ if (pageNumber == 0) {
+ if (m_filledPrimaryPage)
+ return &m_primaryPage;
+ page = &m_primaryPage;
+ m_filledPrimaryPage = true;
+ } else {
+ if (m_pages) {
+ GlyphWidthPage* result = m_pages->get(pageNumber);
+ if (result)
+ return result;
+ }
+ page = new GlyphWidthPage;
+ if (!m_pages)
+ m_pages = new HashMap<int, GlyphWidthPage*>;
+ m_pages->set(pageNumber, page);
+ }
+
+ // Fill in the whole page with the unknown glyph width value.
+ for (unsigned i = 0; i < GlyphWidthPage::size; i++)
+ page->setWidthForIndex(i, cGlyphWidthUnknown);
+
+ return page;
+}
+
+}
diff --git a/WebCore/platform/graphics/GlyphWidthMap.h b/WebCore/platform/graphics/GlyphWidthMap.h
new file mode 100644
index 0000000..1633769
--- /dev/null
+++ b/WebCore/platform/graphics/GlyphWidthMap.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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.
+ */
+
+#ifndef GlyphWidthMap_h
+#define GlyphWidthMap_h
+
+#include <wtf/unicode/Unicode.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+typedef unsigned short Glyph;
+
+const float cGlyphWidthUnknown = -1;
+
+class GlyphWidthMap : Noncopyable {
+public:
+ GlyphWidthMap() : m_filledPrimaryPage(false), m_pages(0) {}
+ ~GlyphWidthMap() { if (m_pages) { deleteAllValues(*m_pages); delete m_pages; } }
+
+ float widthForGlyph(Glyph);
+ void setWidthForGlyph(Glyph, float);
+
+private:
+ struct GlyphWidthPage {
+ static const size_t size = 256; // Usually covers Latin-1 in a single page.
+ float m_widths[size];
+
+ float widthForGlyph(Glyph g) const { return m_widths[g % size]; }
+ void setWidthForGlyph(Glyph g, float w)
+ {
+ setWidthForIndex(g % size, w);
+ }
+ void setWidthForIndex(unsigned index, float w)
+ {
+ m_widths[index] = w;
+ }
+ };
+
+ GlyphWidthPage* locatePage(unsigned page);
+
+ bool m_filledPrimaryPage;
+ GlyphWidthPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255.
+ HashMap<int, GlyphWidthPage*>* m_pages;
+};
+
+}
+#endif
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
new file mode 100644
index 0000000..2f2f97e
--- /dev/null
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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"
+#include "GraphicsContext.h"
+
+#include "BidiResolver.h"
+#include "Font.h"
+
+using namespace std;
+
+namespace WebCore {
+
+class TextRunIterator {
+public:
+ TextRunIterator()
+ : m_textRun(0)
+ , m_offset(0)
+ {
+ }
+
+ TextRunIterator(const TextRun* textRun, unsigned offset)
+ : m_textRun(textRun)
+ , m_offset(offset)
+ {
+ }
+
+ TextRunIterator(const TextRunIterator& other)
+ : m_textRun(other.m_textRun)
+ , m_offset(other.m_offset)
+ {
+ }
+
+ unsigned offset() const { return m_offset; }
+ void increment(BidiResolver<TextRunIterator, BidiCharacterRun>&) { m_offset++; }
+ bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); }
+ UChar current() const { return (*m_textRun)[m_offset]; }
+ WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); }
+
+ bool operator==(const TextRunIterator& other)
+ {
+ return m_offset == other.m_offset && m_textRun == other.m_textRun;
+ }
+
+ bool operator!=(const TextRunIterator& other) { return !operator==(other); }
+
+private:
+ const TextRun* m_textRun;
+ int m_offset;
+};
+
+struct GraphicsContextState {
+ GraphicsContextState()
+ : strokeStyle(SolidStroke)
+ , strokeThickness(0)
+ , strokeColor(Color::black)
+ , fillColor(Color::black)
+ , textDrawingMode(cTextFill)
+ , paintingDisabled(false)
+ {}
+
+ Font font;
+ StrokeStyle strokeStyle;
+ float strokeThickness;
+ Color strokeColor;
+ Color fillColor;
+ int textDrawingMode;
+ bool paintingDisabled;
+};
+
+class GraphicsContextPrivate {
+public:
+ GraphicsContextPrivate();
+
+ GraphicsContextState state;
+ Vector<GraphicsContextState> stack;
+ Vector<IntRect> m_focusRingRects;
+ int m_focusRingWidth;
+ int m_focusRingOffset;
+ bool m_updatingControlTints;
+};
+
+GraphicsContextPrivate::GraphicsContextPrivate()
+ : m_focusRingWidth(0)
+ , m_focusRingOffset(0)
+ , m_updatingControlTints(false)
+{
+}
+
+GraphicsContextPrivate* GraphicsContext::createGraphicsContextPrivate()
+{
+ return new GraphicsContextPrivate;
+}
+
+void GraphicsContext::destroyGraphicsContextPrivate(GraphicsContextPrivate* deleteMe)
+{
+ delete deleteMe;
+}
+
+void GraphicsContext::save()
+{
+ if (paintingDisabled())
+ return;
+
+ m_common->stack.append(m_common->state);
+
+ savePlatformState();
+}
+
+void GraphicsContext::restore()
+{
+ if (paintingDisabled())
+ return;
+
+ if (m_common->stack.isEmpty()) {
+ LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
+ return;
+ }
+ m_common->state = m_common->stack.last();
+ m_common->stack.removeLast();
+
+ restorePlatformState();
+}
+
+const Font& GraphicsContext::font() const
+{
+ return m_common->state.font;
+}
+
+void GraphicsContext::setFont(const Font& aFont)
+{
+ m_common->state.font = aFont;
+ setPlatformFont(aFont);
+}
+
+void GraphicsContext::setStrokeThickness(float thickness)
+{
+ m_common->state.strokeThickness = thickness;
+ setPlatformStrokeThickness(thickness);
+}
+
+void GraphicsContext::setStrokeStyle(const StrokeStyle& style)
+{
+ m_common->state.strokeStyle = style;
+ setPlatformStrokeStyle(style);
+}
+
+void GraphicsContext::setStrokeColor(const Color& color)
+{
+ m_common->state.strokeColor = color;
+ setPlatformStrokeColor(color);
+}
+
+float GraphicsContext::strokeThickness() const
+{
+ return m_common->state.strokeThickness;
+}
+
+StrokeStyle GraphicsContext::strokeStyle() const
+{
+ return m_common->state.strokeStyle;
+}
+
+Color GraphicsContext::strokeColor() const
+{
+ return m_common->state.strokeColor;
+}
+
+void GraphicsContext::setFillColor(const Color& color)
+{
+ m_common->state.fillColor = color;
+ setPlatformFillColor(color);
+}
+
+Color GraphicsContext::fillColor() const
+{
+ return m_common->state.fillColor;
+}
+
+bool GraphicsContext::updatingControlTints() const
+{
+ return m_common->m_updatingControlTints;
+}
+
+void GraphicsContext::setUpdatingControlTints(bool b)
+{
+ setPaintingDisabled(b);
+ m_common->m_updatingControlTints = b;
+}
+
+void GraphicsContext::setPaintingDisabled(bool f)
+{
+ m_common->state.paintingDisabled = f;
+}
+
+bool GraphicsContext::paintingDisabled() const
+{
+ return m_common->state.paintingDisabled;
+}
+
+void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op)
+{
+ drawImage(image, p, IntRect(0, 0, -1, -1), op);
+}
+
+void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
+{
+ drawImage(image, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
+}
+
+void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
+{
+ drawImage(image, IntRect(dest, srcRect.size()), srcRect, op);
+}
+
+void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
+{
+ drawImage(image, FloatRect(dest), srcRect, op, useLowQualityScale);
+}
+
+void GraphicsContext::drawText(const TextRun& run, const IntPoint& point, int from, int to)
+{
+ if (paintingDisabled())
+ return;
+
+ font().drawText(this, run, point, from, to);
+}
+
+void GraphicsContext::drawBidiText(const TextRun& run, const IntPoint& point)
+{
+ if (paintingDisabled())
+ return;
+
+ BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
+ WTF::Unicode::Direction paragraphDirection = run.ltr() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft;
+
+ bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, new BidiContext(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride())));
+
+ bidiResolver.createBidiRunsForLine(TextRunIterator(&run, 0), TextRunIterator(&run, run.length()));
+
+ if (!bidiResolver.runCount())
+ return;
+
+ FloatPoint currPoint = point;
+ BidiCharacterRun* bidiRun = bidiResolver.firstRun();
+ while (bidiRun) {
+
+ TextRun subrun = run;
+ subrun.setText(run.data(bidiRun->start()), bidiRun->stop() - bidiRun->start());
+ subrun.setRTL(bidiRun->level() % 2);
+ subrun.setDirectionalOverride(bidiRun->dirOverride(false));
+
+ font().drawText(this, subrun, currPoint);
+
+ bidiRun = bidiRun->next();
+ // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
+ if (bidiRun)
+ currPoint.move(font().floatWidth(subrun), 0.f);
+ }
+
+ bidiResolver.deleteRuns();
+}
+
+void GraphicsContext::drawHighlightForText(const TextRun& run, const IntPoint& point, int h, const Color& backgroundColor, int from, int to)
+{
+ if (paintingDisabled())
+ return;
+
+ fillRect(font().selectionRectForText(run, point, h, from, to), backgroundColor);
+}
+
+void GraphicsContext::initFocusRing(int width, int offset)
+{
+ if (paintingDisabled())
+ return;
+ clearFocusRing();
+
+ m_common->m_focusRingWidth = width;
+ m_common->m_focusRingOffset = offset;
+}
+
+void GraphicsContext::clearFocusRing()
+{
+ m_common->m_focusRingRects.clear();
+}
+
+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;
+}
+
+void GraphicsContext::addFocusRingRect(const IntRect& rect)
+{
+ if (paintingDisabled() || rect.isEmpty())
+ return;
+ m_common->m_focusRingRects.append(rect);
+}
+
+int GraphicsContext::focusRingWidth() const
+{
+ return m_common->m_focusRingWidth;
+}
+
+int GraphicsContext::focusRingOffset() const
+{
+ return m_common->m_focusRingOffset;
+}
+
+const Vector<IntRect>& GraphicsContext::focusRingRects() const
+{
+ return m_common->m_focusRingRects;
+}
+
+static const int cInterpolationCutoff = 800 * 800;
+
+void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
+{
+ if (paintingDisabled())
+ return;
+
+ float tsw = src.width();
+ float tsh = src.height();
+ float tw = dest.width();
+ float th = dest.height();
+
+ if (tsw == -1)
+ tsw = image->width();
+ if (tsh == -1)
+ tsh = image->height();
+
+ if (tw == -1)
+ tw = image->width();
+ if (th == -1)
+ th = image->height();
+
+ bool shouldUseLowQualityInterpolation = useLowQualityScale && (tsw != tw || tsh != th) && tsw * tsh > cInterpolationCutoff;
+ if (shouldUseLowQualityInterpolation) {
+ save();
+ setUseLowQualityImageInterpolation(true);
+ }
+ image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op);
+ if (shouldUseLowQualityInterpolation)
+ restore();
+}
+
+void GraphicsContext::drawTiledImage(Image* image, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+
+ image->drawTiled(this, rect, srcPoint, tileSize, op);
+}
+
+void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+
+ if (hRule == Image::StretchTile && vRule == Image::StretchTile)
+ // Just do a scale.
+ return drawImage(image, dest, srcRect);
+
+ image->drawTiled(this, dest, srcRect, hRule, vRule, op);
+}
+
+void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
+ const IntSize& bottomLeft, const IntSize& bottomRight)
+{
+ if (paintingDisabled())
+ return;
+
+ clip(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+}
+
+void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
+ const IntSize& bottomLeft, const IntSize& bottomRight)
+{
+ if (paintingDisabled())
+ return;
+
+ clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+}
+
+int GraphicsContext::textDrawingMode()
+{
+ return m_common->state.textDrawingMode;
+}
+
+void GraphicsContext::setTextDrawingMode(int mode)
+{
+ m_common->state.textDrawingMode = mode;
+ if (paintingDisabled())
+ return;
+ setPlatformTextDrawingMode(mode);
+}
+
+#if !PLATFORM(CG)
+// Implement this if you want to go ahead and push the drawing mode into your native context
+// immediately.
+void GraphicsContext::setPlatformTextDrawingMode(int mode)
+{
+}
+#endif
+
+#if !PLATFORM(QT) && !PLATFORM(CAIRO)
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&)
+{
+}
+#endif
+
+#if !PLATFORM(QT)
+void GraphicsContext::setPlatformFont(const Font&)
+{
+}
+#endif
+
+}
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
new file mode 100644
index 0000000..732c8e3
--- /dev/null
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2003, 2006, 2007 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 GraphicsContext_h
+#define GraphicsContext_h
+
+#include "FloatRect.h"
+#include "Image.h"
+#include "IntRect.h"
+#include "Path.h"
+#include "TextDirection.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGContext PlatformGraphicsContext;
+#elif PLATFORM(CAIRO)
+typedef struct _cairo PlatformGraphicsContext;
+#elif PLATFORM(QT)
+class QPainter;
+typedef QPainter PlatformGraphicsContext;
+#elif PLATFORM(WX)
+class wxGCDC;
+class wxWindowDC;
+
+// 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
+// the linker happy.
+#ifdef __APPLE__
+ class wxDC;
+ typedef wxDC PlatformGraphicsContext;
+#else
+ typedef wxGCDC PlatformGraphicsContext;
+#endif
+#else
+ typedef wxWindowDC PlatformGraphicsContext;
+#endif
+#else
+typedef void PlatformGraphicsContext;
+#endif
+
+#if PLATFORM(GTK)
+typedef struct _GdkDrawable GdkDrawable;
+typedef struct _GdkEventExpose GdkEventExpose;
+#endif
+
+#if PLATFORM(WIN)
+typedef struct HDC__* HDC;
+#endif
+
+namespace WebCore {
+
+ const int cMisspellingLineThickness = 3;
+ const int cMisspellingLinePatternWidth = 4;
+ const int cMisspellingLinePatternGapWidth = 1;
+
+ class AffineTransform;
+ class Font;
+ class GraphicsContextPrivate;
+ class GraphicsContextPlatformPrivate;
+ class ImageBuffer;
+ class KURL;
+ class Path;
+ class TextRun;
+
+ // These bits can be ORed together for a total of 8 possible text drawing modes.
+ const int cTextInvisible = 0;
+ const int cTextFill = 1;
+ const int cTextStroke = 2;
+ const int cTextClip = 4;
+
+ enum StrokeStyle {
+ NoStroke,
+ SolidStroke,
+ DottedStroke,
+ DashedStroke
+ };
+
+ class GraphicsContext : Noncopyable {
+ public:
+ GraphicsContext(PlatformGraphicsContext*);
+ ~GraphicsContext();
+
+ PlatformGraphicsContext* platformContext() const;
+
+ const Font& font() const;
+ void setFont(const Font&);
+
+ float strokeThickness() const;
+ void setStrokeThickness(float);
+ StrokeStyle strokeStyle() const;
+ void setStrokeStyle(const StrokeStyle& style);
+ Color strokeColor() const;
+ void setStrokeColor(const Color&);
+
+ Color fillColor() const;
+ void setFillColor(const Color&);
+
+ void save();
+ void restore();
+
+ // These draw methods will do both stroking and filling.
+ void drawRect(const IntRect&);
+ void drawLine(const IntPoint&, const IntPoint&);
+ void drawEllipse(const IntRect&);
+ void drawConvexPolygon(size_t numPoints, const FloatPoint*, bool shouldAntialias = false);
+
+ // Arc drawing (used by border-radius in CSS) just supports stroking at the moment.
+ void strokeArc(const IntRect&, int startAngle, int angleSpan);
+
+ void fillRect(const IntRect&, const Color&);
+ void fillRect(const FloatRect&, const Color&);
+ void fillRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color&);
+ void clearRect(const FloatRect&);
+ void strokeRect(const FloatRect&, float lineWidth);
+
+ void drawImage(Image*, const IntPoint&, CompositeOperator = CompositeSourceOver);
+ void drawImage(Image*, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
+ void drawImage(Image*, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
+ CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+ void drawImage(ImageBuffer*, const FloatRect& srcRect, const FloatRect& destRect);
+ void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
+ CompositeOperator = CompositeSourceOver);
+ void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect,
+ Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
+ CompositeOperator = CompositeSourceOver);
+
+ void paintBuffer(ImageBuffer*, const IntRect&);
+#if PLATFORM(CG)
+ void setUseLowQualityImageInterpolation(bool = true);
+ bool useLowQualityImageInterpolation() const;
+#else
+ void setUseLowQualityImageInterpolation(bool = true) {}
+ bool useLowQualityImageInterpolation() const { return false; }
+#endif
+
+ void clip(const IntRect&);
+ void addRoundedRectClip(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
+ void addInnerRoundedRectClip(const IntRect&, int thickness);
+ void clipOut(const IntRect&);
+ void clipOutEllipseInRect(const IntRect&);
+ void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
+
+ int textDrawingMode();
+ void setTextDrawingMode(int);
+
+ void drawText(const TextRun&, const IntPoint&, int from = 0, int to = -1);
+ void drawBidiText(const TextRun&, const IntPoint&);
+ void drawHighlightForText(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);
+
+ void beginTransparencyLayer(float opacity);
+ void endTransparencyLayer();
+
+ void setShadow(const IntSize&, int blur, const Color&);
+ void clearShadow();
+
+ void initFocusRing(int width, int offset);
+ void addFocusRingRect(const IntRect&);
+ void drawFocusRing(const Color&);
+ void clearFocusRing();
+ IntRect focusRingBoundingRect();
+
+ void setLineCap(LineCap);
+ void setLineJoin(LineJoin);
+ void setMiterLimit(float);
+
+ void setAlpha(float);
+
+ void setCompositeOperation(CompositeOperator);
+
+ void beginPath();
+ void addPath(const Path&);
+
+ void clip(const Path&);
+ void clipOut(const Path&);
+
+ void scale(const FloatSize&);
+ void rotate(float angleInRadians);
+ void translate(float x, float y);
+ IntPoint origin();
+
+ void setURLForRect(const KURL&, const IntRect&);
+
+ void concatCTM(const AffineTransform&);
+ AffineTransform getCTM() const;
+
+ void setUseAntialiasing(bool = true);
+
+#if PLATFORM(WIN)
+ GraphicsContext(HDC); // FIXME: To be removed.
+ bool inTransparencyLayer() const;
+ HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers.
+ void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true); // The passed in HDC should be the one handed back by getWindowsContext.
+#endif
+
+#if PLATFORM(QT)
+ void setFillRule(WindRule);
+ PlatformPath* currentPath();
+#endif
+
+#if PLATFORM(GTK)
+ void setGdkExposeEvent(GdkEventExpose*);
+ GdkDrawable* gdkDrawable() const;
+ GdkEventExpose* gdkExposeEvent() const;
+ IntPoint translatePoint(const IntPoint&) const;
+#endif
+
+ private:
+ void savePlatformState();
+ void restorePlatformState();
+ void setPlatformTextDrawingMode(int);
+ void setPlatformStrokeColor(const Color&);
+ void setPlatformStrokeStyle(const StrokeStyle&);
+ void setPlatformStrokeThickness(float);
+ void setPlatformFillColor(const Color&);
+ void setPlatformFont(const Font& font);
+
+ int focusRingWidth() const;
+ int focusRingOffset() const;
+ const Vector<IntRect>& focusRingRects() const;
+
+ static GraphicsContextPrivate* createGraphicsContextPrivate();
+ static void destroyGraphicsContextPrivate(GraphicsContextPrivate*);
+
+ GraphicsContextPrivate* m_common;
+ GraphicsContextPlatformPrivate* m_data;
+ };
+
+} // namespace WebCore
+
+#endif // GraphicsContext_h
diff --git a/WebCore/platform/graphics/GraphicsTypes.cpp b/WebCore/platform/graphics/GraphicsTypes.cpp
new file mode 100644
index 0000000..736356f
--- /dev/null
+++ b/WebCore/platform/graphics/GraphicsTypes.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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"
+#include "GraphicsTypes.h"
+
+#include "PlatformString.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+static const char* const compositeOperatorNames[] = {
+ "clear",
+ "copy",
+ "source-over",
+ "source-in",
+ "source-out",
+ "source-atop",
+ "destination-over",
+ "destination-in",
+ "destination-out",
+ "destination-atop",
+ "xor",
+ "darker",
+ "highlight",
+ "lighter"
+};
+const int numCompositeOperatorNames = sizeof(compositeOperatorNames) / sizeof(compositeOperatorNames[0]);
+
+bool parseCompositeOperator(const String& s, CompositeOperator& op)
+{
+ for (int i = 0; i < numCompositeOperatorNames; i++)
+ if (s == compositeOperatorNames[i]) {
+ op = static_cast<CompositeOperator>(i);
+ return true;
+ }
+ return false;
+}
+
+String compositeOperatorName(CompositeOperator op)
+{
+ ASSERT(op >= 0);
+ ASSERT(op < numCompositeOperatorNames);
+ return compositeOperatorNames[op];
+}
+
+bool parseLineCap(const String& s, LineCap& cap)
+{
+ if (s == "butt") {
+ cap = ButtCap;
+ return true;
+ }
+ if (s == "round") {
+ cap = RoundCap;
+ return true;
+ }
+ if (s == "square") {
+ cap = SquareCap;
+ return true;
+ }
+ return false;
+}
+
+String lineCapName(LineCap cap)
+{
+ ASSERT(cap >= 0);
+ ASSERT(cap < 3);
+ const char* const names[3] = { "butt", "round", "square" };
+ return names[cap];
+}
+
+bool parseLineJoin(const String& s, LineJoin& join)
+{
+ if (s == "miter") {
+ join = MiterJoin;
+ return true;
+ }
+ if (s == "round") {
+ join = RoundJoin;
+ return true;
+ }
+ if (s == "bevel") {
+ join = BevelJoin;
+ return true;
+ }
+ return false;
+}
+
+String lineJoinName(LineJoin join)
+{
+ ASSERT(join >= 0);
+ ASSERT(join < 3);
+ const char* const names[3] = { "miter", "round", "bevel" };
+ return names[join];
+}
+
+}
diff --git a/WebCore/platform/graphics/GraphicsTypes.h b/WebCore/platform/graphics/GraphicsTypes.h
new file mode 100644
index 0000000..b3ca99a
--- /dev/null
+++ b/WebCore/platform/graphics/GraphicsTypes.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 GraphicsTypes_h
+#define GraphicsTypes_h
+
+namespace WebCore {
+
+ class String;
+
+ // Note: These constants exactly match the NSCompositeOperator constants of
+ // AppKit on Mac OS X Tiger. If these ever change, we'll need to change the
+ // Mac OS X Tiger platform code to map one to the other.
+ enum CompositeOperator {
+ CompositeClear,
+ CompositeCopy,
+ CompositeSourceOver,
+ CompositeSourceIn,
+ CompositeSourceOut,
+ CompositeSourceAtop,
+ CompositeDestinationOver,
+ CompositeDestinationIn,
+ CompositeDestinationOut,
+ CompositeDestinationAtop,
+ CompositeXOR,
+ CompositePlusDarker,
+ CompositeHighlight,
+ CompositePlusLighter
+ };
+
+ enum LineCap { ButtCap, RoundCap, SquareCap };
+
+ enum LineJoin { MiterJoin, RoundJoin, BevelJoin };
+
+ enum HorizontalAlignment { AlignLeft, AlignRight, AlignHCenter };
+
+ String compositeOperatorName(CompositeOperator);
+ bool parseCompositeOperator(const String&, CompositeOperator&);
+
+ String lineCapName(LineCap);
+ bool parseLineCap(const String&, LineCap&);
+
+ String lineJoinName(LineJoin);
+ bool parseLineJoin(const String&, LineJoin&);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h
new file mode 100644
index 0000000..310c25a
--- /dev/null
+++ b/WebCore/platform/graphics/Icon.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2006, 2007 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.
+ *
+ */
+
+#ifndef Icon_h
+#define Icon_h
+
+#include <wtf/RefCounted.h>
+#include <wtf/Forward.h>
+
+#if PLATFORM(MAC)
+#include <wtf/RetainPtr.h>
+#ifdef __OBJC__
+@class NSImage;
+#else
+class NSImage;
+#endif
+#elif PLATFORM(WIN)
+typedef struct HICON__* HICON;
+#elif PLATFORM(QT)
+#include <QIcon>
+#elif PLATFORM(GTK)
+#include <gdk/gdk.h>
+#endif
+
+namespace WebCore {
+
+class GraphicsContext;
+class IntRect;
+class String;
+
+class Icon : public RefCounted<Icon> {
+public:
+ Icon();
+ ~Icon();
+
+ static PassRefPtr<Icon> newIconForFile(const String& filename);
+
+ void paint(GraphicsContext*, const IntRect&);
+
+#if PLATFORM(WIN)
+ Icon(HICON);
+#endif
+
+private:
+#if PLATFORM(MAC)
+ Icon(NSImage*);
+#endif
+#if PLATFORM(MAC)
+ RetainPtr<NSImage> m_nsImage;
+#elif PLATFORM(WIN)
+ HICON m_hIcon;
+#elif PLATFORM(QT)
+ QIcon m_icon;
+#elif PLATFORM(GTK)
+ GdkPixbuf* m_icon;
+#endif
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp
new file mode 100644
index 0000000..8bf7c68
--- /dev/null
+++ b/WebCore/platform/graphics/Image.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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"
+#include "Image.h"
+
+#include "AffineTransform.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "MIMETypeRegistry.h"
+
+#include <math.h>
+
+#if PLATFORM(CG)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace WebCore {
+
+Image::Image(ImageObserver* observer)
+ : m_imageObserver(observer)
+{
+}
+
+Image::~Image()
+{
+}
+
+bool Image::supportsType(const String& type)
+{
+ return MIMETypeRegistry::isSupportedImageResourceMIMEType(type);
+}
+
+bool Image::isNull() const
+{
+ return size().isEmpty();
+}
+
+bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
+{
+ m_data = data;
+ if (!m_data.get())
+ return true;
+
+ int length = m_data->size();
+ if (!length)
+ return true;
+
+ return dataChanged(allDataReceived);
+}
+
+IntRect Image::rect() const
+{
+ return IntRect(IntPoint(), size());
+}
+
+int Image::width() const
+{
+ return size().width();
+}
+
+int Image::height() const
+{
+ return size().height();
+}
+
+void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
+{
+ if (color.alpha() <= 0)
+ return;
+
+ ctxt->save();
+ ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
+ ctxt->fillRect(dstRect, color);
+ ctxt->restore();
+}
+
+static inline FloatSize calculatePatternScale(const FloatRect& dstRect, const FloatRect& srcRect, Image::TileRule hRule, Image::TileRule vRule)
+{
+ float scaleX = 1.0f, scaleY = 1.0f;
+
+ if (hRule == Image::StretchTile)
+ scaleX = dstRect.width() / srcRect.width();
+ if (vRule == Image::StretchTile)
+ scaleY = dstRect.height() / srcRect.height();
+
+ if (hRule == Image::RepeatTile)
+ scaleX = scaleY;
+ if (vRule == Image::RepeatTile)
+ scaleY = scaleX;
+
+ return FloatSize(scaleX, scaleY);
+}
+
+
+void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op)
+{
+ if (!nativeImageForCurrentFrame())
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(ctxt, destRect, solidColor(), op);
+ return;
+ }
+
+ FloatSize intrinsicTileSize = size();
+ if (hasRelativeWidth())
+ intrinsicTileSize.setWidth(scaledTileSize.width());
+ if (hasRelativeHeight())
+ intrinsicTileSize.setHeight(scaledTileSize.height());
+
+ FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
+ scaledTileSize.height() / intrinsicTileSize.height());
+ AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());
+
+ FloatRect oneTileRect;
+ oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
+ oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
+ oneTileRect.setSize(scaledTileSize);
+
+ // Check and see if a single draw of the image can cover the entire area we are supposed to tile.
+ if (oneTileRect.contains(destRect)) {
+ FloatRect visibleSrcRect;
+ visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
+ visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
+ visibleSrcRect.setWidth(destRect.width() / scale.width());
+ visibleSrcRect.setHeight(destRect.height() / scale.height());
+ draw(ctxt, destRect, visibleSrcRect, op);
+ return;
+ }
+
+ FloatRect tileRect(FloatPoint(), intrinsicTileSize);
+ drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect);
+
+ startAnimation();
+}
+
+// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
+void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator op)
+{
+ if (!nativeImageForCurrentFrame())
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(ctxt, dstRect, solidColor(), op);
+ return;
+ }
+
+ // FIXME: We do not support 'round' yet. For now just map it to 'repeat'.
+ if (hRule == RoundTile)
+ hRule = RepeatTile;
+ if (vRule == RoundTile)
+ vRule = RepeatTile;
+
+ FloatSize scale = calculatePatternScale(dstRect, srcRect, hRule, vRule);
+ AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());
+
+ // We want to construct the phase such that the pattern is centered (when stretch is not
+ // set for a particular rule).
+ float hPhase = scale.width() * srcRect.x();
+ float vPhase = scale.height() * srcRect.y();
+ if (hRule == Image::RepeatTile)
+ hPhase -= fmodf(dstRect.width(), scale.width() * srcRect.width()) / 2.0f;
+ if (vRule == Image::RepeatTile)
+ vPhase -= fmodf(dstRect.height(), scale.height() * srcRect.height()) / 2.0f;
+ FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
+
+ drawPattern(ctxt, srcRect, patternTransform, patternPhase, op, dstRect);
+
+ startAnimation();
+}
+
+
+}
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
new file mode 100644
index 0000000..6ffe163
--- /dev/null
+++ b/WebCore/platform/graphics/Image.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 Image_h
+#define Image_h
+
+#include "Color.h"
+#include "GraphicsTypes.h"
+#include "ImageSource.h"
+#include <wtf/RefPtr.h>
+#include <wtf/PassRefPtr.h>
+#include "SharedBuffer.h"
+
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+@class NSImage;
+#else
+class NSImage;
+#endif
+#endif
+
+#if PLATFORM(CG)
+struct CGContext;
+#endif
+
+#if PLATFORM(WIN)
+typedef struct HBITMAP__ *HBITMAP;
+#endif
+
+#if PLATFORM(QT)
+#include <QPixmap>
+#endif
+
+namespace WebCore {
+
+class AffineTransform;
+class FloatPoint;
+class FloatRect;
+class FloatSize;
+class GraphicsContext;
+class IntRect;
+class IntSize;
+class SharedBuffer;
+class String;
+
+// This class gets notified when an image creates or destroys decoded frames and when it advances animation frames.
+class ImageObserver;
+
+class Image : Noncopyable {
+ friend class GraphicsContext;
+public:
+ Image(ImageObserver* = 0);
+ virtual ~Image();
+
+ static Image* loadPlatformResource(const char* name);
+ static bool supportsType(const String&);
+
+ bool isNull() const;
+
+ // These are only used for SVGImage right now
+ virtual void setContainerSize(const IntSize&) { }
+ virtual bool usesContainerSize() const { return false; }
+ virtual bool hasRelativeWidth() const { return false; }
+ virtual bool hasRelativeHeight() const { return false; }
+
+ virtual IntSize size() const = 0;
+ IntRect rect() const;
+ int width() const;
+ int height() const;
+
+ bool setData(PassRefPtr<SharedBuffer> data, bool allDataReceived);
+ virtual bool dataChanged(bool allDataReceived) { return false; }
+
+ // FIXME: PDF/SVG will be underreporting decoded sizes and will be unable to prune because these functions are not
+ // implemented yet for those image types.
+ virtual void destroyDecodedData(bool incremental = false) {};
+ virtual unsigned decodedSize() const { return 0; }
+
+ SharedBuffer* data() { return m_data.get(); }
+
+ // It may look unusual that there is no start animation call as public API. This is because
+ // we start and stop animating lazily. Animation begins whenever someone draws the image. It will
+ // automatically pause once all observers no longer want to render the image anywhere.
+ virtual void stopAnimation() {}
+ virtual void resetAnimation() {}
+
+ // Typically the CachedImage that owns us.
+ ImageObserver* imageObserver() const { return m_imageObserver; }
+
+ enum TileRule { StretchTile, RoundTile, RepeatTile };
+
+ virtual NativeImagePtr nativeImageForCurrentFrame() { return 0; }
+
+#if PLATFORM(MAC)
+ // Accessors for native image formats.
+ virtual NSImage* getNSImage() { return 0; }
+ virtual CFDataRef getTIFFRepresentation() { return 0; }
+#endif
+
+#if PLATFORM(CG)
+ virtual CGImageRef getCGImageRef() { return 0; }
+#endif
+
+#if PLATFORM(QT)
+ virtual QPixmap* getPixmap() const { return 0; }
+#endif
+
+#if PLATFORM(WIN)
+ virtual bool getHBITMAP(HBITMAP) { return false; }
+ virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE) { return false; }
+#endif
+
+protected:
+ static void fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op);
+
+private:
+#if PLATFORM(WIN)
+ virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator) { }
+#endif
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator) = 0;
+ void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, CompositeOperator);
+ void drawTiled(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator);
+
+ // Supporting tiled drawing
+ virtual bool mayFillWithSolidColor() const { return false; }
+ virtual Color solidColor() const { return Color(); }
+
+ virtual void startAnimation() { }
+
+ virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator, const FloatRect& destRect);
+#if PLATFORM(CG)
+ // These are private to CG. Ideally they would be only in the .cpp file, but the callback requires access
+ // to the private function nativeImageForCurrentFrame()
+ static void drawPatternCallback(void* info, CGContext*);
+#endif
+
+protected:
+ RefPtr<SharedBuffer> m_data; // The encoded raw data for the image.
+ ImageObserver* m_imageObserver;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
new file mode 100644
index 0000000..2ac2b4e
--- /dev/null
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 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 ImageBuffer_h
+#define ImageBuffer_h
+
+#include "IntSize.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <memory>
+
+#if PLATFORM(CG)
+typedef struct CGImage* CGImageRef;
+#endif
+
+#if PLATFORM(QT)
+#include <QPixmap>
+class QPainter;
+#endif
+
+#if PLATFORM(CAIRO)
+typedef struct _cairo_surface cairo_surface_t;
+#endif
+
+namespace WebCore {
+
+ class GraphicsContext;
+ class ImageData;
+ class IntPoint;
+ class IntRect;
+ class RenderObject;
+
+ class ImageBuffer : Noncopyable {
+ public:
+ static std::auto_ptr<ImageBuffer> create(const IntSize&, bool grayScale);
+ ~ImageBuffer();
+
+ IntSize size() const { return m_size; }
+ GraphicsContext* context() const;
+
+#if PLATFORM(CG)
+ CGImageRef cgImage() const;
+#elif PLATFORM(QT)
+ QPixmap* pixmap() const;
+#elif PLATFORM(CAIRO)
+ cairo_surface_t* surface() const;
+#endif
+
+ PassRefPtr<ImageData> getImageData(const IntRect& rect) const;
+ void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint);
+
+ private:
+ void* m_data;
+ IntSize m_size;
+
+ OwnPtr<GraphicsContext> m_context;
+
+#if PLATFORM(CG)
+ ImageBuffer(void* imageData, const IntSize&, std::auto_ptr<GraphicsContext>);
+ mutable CGImageRef m_cgImage;
+#elif PLATFORM(QT)
+ ImageBuffer(const QPixmap &px);
+ mutable QPixmap m_pixmap;
+ mutable QPainter* m_painter;
+#elif PLATFORM(CAIRO)
+ ImageBuffer(cairo_surface_t* surface);
+ mutable cairo_surface_t* m_surface;
+#endif
+ };
+}
+
+#endif
diff --git a/WebCore/platform/graphics/ImageObserver.h b/WebCore/platform/graphics/ImageObserver.h
new file mode 100644
index 0000000..4be83bd
--- /dev/null
+++ b/WebCore/platform/graphics/ImageObserver.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 ImageObserver_h
+#define ImageObserver_h
+
+namespace WebCore {
+
+class Image;
+
+// Interface for notification about changes to an image, including decoding,
+// drawing, and animating.
+class ImageObserver {
+protected:
+ virtual ~ImageObserver() {}
+public:
+ virtual void decodedSizeChanged(const Image*, int delta) = 0;
+ virtual void didDraw(const Image*) = 0;
+
+ virtual bool shouldPauseAnimation(const Image*) = 0;
+ virtual void animationAdvanced(const Image*) = 0;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
new file mode 100644
index 0000000..8db5cd4
--- /dev/null
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 ImageSource_h
+#define ImageSource_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(WX)
+class wxBitmap;
+#elif PLATFORM(CG)
+typedef struct CGImageSource* CGImageSourceRef;
+typedef struct CGImage* CGImageRef;
+typedef const struct __CFData* CFDataRef;
+#elif PLATFORM(QT)
+class QPixmap;
+#elif PLATFORM(CAIRO)
+struct _cairo_surface;
+typedef struct _cairo_surface cairo_surface_t;
+#endif
+
+namespace WebCore {
+
+class IntSize;
+class SharedBuffer;
+
+#if PLATFORM(WX)
+class ImageDecoder;
+typedef ImageDecoder* NativeImageSourcePtr;
+typedef const Vector<char>* NativeBytePtr;
+typedef wxBitmap* NativeImagePtr;
+#elif PLATFORM(CG)
+typedef CGImageSourceRef NativeImageSourcePtr;
+typedef CGImageRef NativeImagePtr;
+#elif PLATFORM(QT)
+class ImageDecoderQt;
+typedef ImageDecoderQt* NativeImageSourcePtr;
+typedef QPixmap* NativeImagePtr;
+#else
+class ImageDecoder;
+typedef ImageDecoder* NativeImageSourcePtr;
+typedef cairo_surface_t* NativeImagePtr;
+#endif
+
+const int cAnimationLoopOnce = -1;
+const int cAnimationNone = -2;
+
+class ImageSource : Noncopyable {
+public:
+ ImageSource();
+ ~ImageSource();
+
+ void clear();
+
+ bool initialized() const;
+
+ void setData(SharedBuffer* data, bool allDataReceived);
+
+ bool isSizeAvailable();
+ IntSize size() const;
+
+ int repetitionCount();
+
+ size_t frameCount() const;
+
+ NativeImagePtr createFrameAtIndex(size_t);
+
+ float frameDurationAtIndex(size_t);
+ bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
+ bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
+
+private:
+ NativeImageSourcePtr m_decoder;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h
new file mode 100644
index 0000000..bd34d2a
--- /dev/null
+++ b/WebCore/platform/graphics/IntPoint.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 IntPoint_h
+#define IntPoint_h
+
+#include "IntSize.h"
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGPoint CGPoint;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+typedef struct CGPoint NSPoint;
+#else
+typedef struct _NSPoint NSPoint;
+#endif
+#endif
+
+#if PLATFORM(WIN)
+typedef struct tagPOINT POINT;
+typedef struct tagPOINTS POINTS;
+#elif PLATFORM(QT)
+class QPoint;
+#elif PLATFORM(GTK)
+typedef struct _GdkPoint GdkPoint;
+#endif
+#if PLATFORM(SYMBIAN)
+class TPoint;
+#endif
+
+#if PLATFORM(WX)
+class wxPoint;
+#endif
+
+namespace WebCore {
+
+class IntPoint {
+public:
+ IntPoint() : m_x(0), m_y(0) { }
+ IntPoint(int x, int y) : m_x(x), m_y(y) { }
+
+ int x() const { return m_x; }
+ int y() const { return m_y; }
+
+ void setX(int x) { m_x = x; }
+ void setY(int y) { m_y = y; }
+
+ void move(int dx, int dy) { m_x += dx; m_y += dy; }
+
+#if PLATFORM(CG)
+ explicit IntPoint(const CGPoint&); // don't do this implicitly since it's lossy
+ operator CGPoint() const;
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+ explicit IntPoint(const NSPoint&); // don't do this implicitly since it's lossy
+ operator NSPoint() const;
+#endif
+
+#if PLATFORM(WIN)
+ IntPoint(const POINT&);
+ operator POINT() const;
+ IntPoint(const POINTS&);
+ operator POINTS() const;
+#elif PLATFORM(QT)
+ IntPoint(const QPoint&);
+ operator QPoint() const;
+#elif PLATFORM(GTK)
+ IntPoint(const GdkPoint&);
+ operator GdkPoint() const;
+#endif
+#if PLATFORM(SYMBIAN)
+ IntPoint(const TPoint&);
+ operator TPoint() const;
+#endif
+
+#if PLATFORM(WX)
+ IntPoint(const wxPoint&);
+ operator wxPoint() const;
+#endif
+
+private:
+ int m_x, m_y;
+};
+
+inline IntPoint& operator+=(IntPoint& a, const IntSize& b)
+{
+ a.move(b.width(), b.height());
+ return a;
+}
+
+inline IntPoint& operator-=(IntPoint& a, const IntSize& b)
+{
+ a.move(-b.width(), -b.height());
+ return a;
+}
+
+inline IntPoint operator+(const IntPoint& a, const IntSize& b)
+{
+ return IntPoint(a.x() + b.width(), a.y() + b.height());
+}
+
+inline IntSize operator-(const IntPoint& a, const IntPoint& b)
+{
+ return IntSize(a.x() - b.x(), a.y() - b.y());
+}
+
+inline IntPoint operator-(const IntPoint& a, const IntSize& b)
+{
+ return IntPoint(a.x() - b.width(), a.y() - b.height());
+}
+
+inline bool operator==(const IntPoint& a, const IntPoint& b)
+{
+ return a.x() == b.x() && a.y() == b.y();
+}
+
+inline bool operator!=(const IntPoint& a, const IntPoint& b)
+{
+ return a.x() != b.x() || a.y() != b.y();
+}
+
+} // namespace WebCore
+
+#endif // IntPoint_h
diff --git a/WebCore/platform/graphics/IntRect.cpp b/WebCore/platform/graphics/IntRect.cpp
new file mode 100644
index 0000000..622e525
--- /dev/null
+++ b/WebCore/platform/graphics/IntRect.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, 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"
+#include "IntRect.h"
+
+#include "FloatRect.h"
+#include <algorithm>
+
+using std::max;
+using std::min;
+
+namespace WebCore {
+
+IntRect::IntRect(const FloatRect& r)
+ : m_location(IntPoint(static_cast<int>(r.x()), static_cast<int>(r.y())))
+ , m_size(IntSize(static_cast<int>(r.width()), static_cast<int>(r.height())))
+{
+}
+
+bool IntRect::intersects(const IntRect& other) const
+{
+ // Checking emptiness handles negative widths as well as zero.
+ return !isEmpty() && !other.isEmpty()
+ && x() < other.right() && other.x() < right()
+ && y() < other.bottom() && other.y() < bottom();
+}
+
+bool IntRect::contains(const IntRect& other) const
+{
+ return x() <= other.x() && right() >= other.right()
+ && y() <= other.y() && bottom() >= other.bottom();
+}
+
+void IntRect::intersect(const IntRect& other)
+{
+ int l = max(x(), other.x());
+ int t = max(y(), other.y());
+ int r = min(right(), other.right());
+ int b = min(bottom(), other.bottom());
+
+ // Return a clean empty rectangle for non-intersecting cases.
+ if (l >= r || t >= b) {
+ l = 0;
+ t = 0;
+ r = 0;
+ b = 0;
+ }
+
+ m_location.setX(l);
+ m_location.setY(t);
+ m_size.setWidth(r - l);
+ m_size.setHeight(b - t);
+}
+
+void IntRect::unite(const IntRect& other)
+{
+ // Handle empty special cases first.
+ if (other.isEmpty())
+ return;
+ if (isEmpty()) {
+ *this = other;
+ return;
+ }
+
+ int l = min(x(), other.x());
+ int t = min(y(), other.y());
+ int r = max(right(), other.right());
+ int b = max(bottom(), other.bottom());
+
+ m_location.setX(l);
+ m_location.setY(t);
+ m_size.setWidth(r - l);
+ m_size.setHeight(b - t);
+}
+
+void IntRect::scale(float s)
+{
+ m_location.setX((int)(x() * s));
+ m_location.setY((int)(y() * s));
+ m_size.setWidth((int)(width() * s));
+ m_size.setHeight((int)(height() * s));
+}
+
+}
diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h
new file mode 100644
index 0000000..84adf20
--- /dev/null
+++ b/WebCore/platform/graphics/IntRect.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, 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 IntRect_h
+#define IntRect_h
+
+#include "IntPoint.h"
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGRect CGRect;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+typedef struct CGRect NSRect;
+#else
+typedef struct _NSRect NSRect;
+#endif
+#endif
+
+#if PLATFORM(WIN)
+typedef struct tagRECT RECT;
+#elif PLATFORM(QT)
+class QRect;
+#elif PLATFORM(GTK)
+typedef struct _GdkRectangle GdkRectangle;
+#endif
+#if PLATFORM(SYMBIAN)
+class TRect;
+#endif
+
+#if PLATFORM(WX)
+class wxRect;
+#endif
+
+namespace WebCore {
+
+class FloatRect;
+
+class IntRect {
+public:
+ IntRect() { }
+ IntRect(const IntPoint& location, const IntSize& size)
+ : m_location(location), m_size(size) { }
+ IntRect(int x, int y, int width, int height)
+ : m_location(IntPoint(x, y)), m_size(IntSize(width, height)) { }
+
+ explicit IntRect(const FloatRect& rect); // don't do this implicitly since it's lossy
+
+ IntPoint location() const { return m_location; }
+ IntSize size() const { return m_size; }
+
+ void setLocation(const IntPoint& location) { m_location = location; }
+ void setSize(const IntSize& size) { m_size = size; }
+
+ int x() const { return m_location.x(); }
+ int y() const { return m_location.y(); }
+ int width() const { return m_size.width(); }
+ int height() const { return m_size.height(); }
+
+ void setX(int x) { m_location.setX(x); }
+ void setY(int y) { m_location.setY(y); }
+ void setWidth(int width) { m_size.setWidth(width); }
+ void setHeight(int height) { m_size.setHeight(height); }
+
+ // Be careful with these functions. The point is considered to be to the right and below. These are not
+ // substitutes for right() and bottom().
+ IntPoint topLeft() const { return m_location; }
+ IntPoint topRight() const { return IntPoint(right() - 1, y()); }
+ IntPoint bottomLeft() const { return IntPoint(x(), bottom() - 1); }
+ IntPoint bottomRight() const { return IntPoint(right() - 1, bottom() - 1); }
+
+ bool isEmpty() const { return m_size.isEmpty(); }
+
+ int right() const { return x() + width(); }
+ int bottom() const { return y() + height(); }
+
+ void move(const IntSize& s) { m_location += s; }
+ void move(int dx, int dy) { m_location.move(dx, dy); }
+
+ bool intersects(const IntRect&) const;
+ bool contains(const IntRect&) const;
+
+ // This checks to see if the rect contains x,y in the traditional sense.
+ // Equivalent to checking if the rect contains a 1x1 rect below and to the right of (px,py).
+ bool contains(int px, int py) const
+ { return px >= x() && px < right() && py >= y() && py < bottom(); }
+ bool contains(const IntPoint& point) const { return contains(point.x(), point.y()); }
+
+ void intersect(const IntRect&);
+ void unite(const IntRect&);
+
+ void inflateX(int dx)
+ {
+ m_location.setX(m_location.x() - dx);
+ m_size.setWidth(m_size.width() + dx + dx);
+ }
+ void inflateY(int dy)
+ {
+ m_location.setY(m_location.y() - dy);
+ m_size.setHeight(m_size.height() + dy + dy);
+ }
+ void inflate(int d) { inflateX(d); inflateY(d); }
+ void scale(float s);
+
+#if PLATFORM(WX)
+ IntRect(const wxRect&);
+ operator wxRect() const;
+#endif
+
+#if PLATFORM(WIN)
+ IntRect(const RECT&);
+ operator RECT() const;
+#elif PLATFORM(QT)
+ IntRect(const QRect&);
+ operator QRect() const;
+#elif PLATFORM(GTK)
+ IntRect(const GdkRectangle&);
+ operator GdkRectangle() const;
+#endif
+#if PLATFORM(SYMBIAN)
+ IntRect(const TRect&);
+ operator TRect() const;
+ TRect Rect() const;
+#endif
+
+#if PLATFORM(CG)
+ operator CGRect() const;
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+ operator NSRect() const;
+#endif
+
+private:
+ IntPoint m_location;
+ IntSize m_size;
+};
+
+inline IntRect intersection(const IntRect& a, const IntRect& b)
+{
+ IntRect c = a;
+ c.intersect(b);
+ return c;
+}
+
+inline IntRect unionRect(const IntRect& a, const IntRect& b)
+{
+ IntRect c = a;
+ c.unite(b);
+ return c;
+}
+
+inline bool operator==(const IntRect& a, const IntRect& b)
+{
+ return a.location() == b.location() && a.size() == b.size();
+}
+
+inline bool operator!=(const IntRect& a, const IntRect& b)
+{
+ return a.location() != b.location() || a.size() != b.size();
+}
+
+#if PLATFORM(CG)
+IntRect enclosingIntRect(const CGRect&);
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+IntRect enclosingIntRect(const NSRect&);
+#endif
+
+} // namespace WebCore
+
+#endif // IntRect_h
diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h
new file mode 100644
index 0000000..faf58c6
--- /dev/null
+++ b/WebCore/platform/graphics/IntSize.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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 IntSize_h
+#define IntSize_h
+
+#include <wtf/Platform.h>
+
+#if PLATFORM(CG)
+typedef struct CGSize CGSize;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+typedef struct CGSize NSSize;
+#else
+typedef struct _NSSize NSSize;
+#endif
+#endif
+
+#if PLATFORM(WIN)
+typedef struct tagSIZE SIZE;
+#elif PLATFORM(QT)
+class QSize;
+#endif
+#if PLATFORM(SYMBIAN)
+class TSize;
+#endif
+
+namespace WebCore {
+
+class IntSize {
+public:
+ IntSize() : m_width(0), m_height(0) { }
+ IntSize(int width, int height) : m_width(width), m_height(height) { }
+
+ int width() const { return m_width; }
+ int height() const { return m_height; }
+
+ void setWidth(int width) { m_width = width; }
+ void setHeight(int height) { m_height = height; }
+
+ bool isEmpty() const { return m_width <= 0 || m_height <= 0; }
+
+ IntSize expandedTo(const IntSize& other) const
+ {
+ return IntSize(m_width > other.m_width ? m_width : other.m_width,
+ m_height > other.m_height ? m_height : other.m_height);
+ }
+
+ IntSize shrunkTo(const IntSize& other) const
+ {
+ return IntSize(m_width < other.m_width ? m_width : other.m_width,
+ m_height < other.m_height ? m_height : other.m_height);
+ }
+
+ void clampNegativeToZero()
+ {
+ *this = expandedTo(IntSize());
+ }
+
+#if PLATFORM(CG)
+ explicit IntSize(const CGSize&); // don't do this implicitly since it's lossy
+ operator CGSize() const;
+#endif
+
+#if PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)
+ explicit IntSize(const NSSize &); // don't do this implicitly since it's lossy
+ operator NSSize() const;
+#endif
+
+#if PLATFORM(WIN)
+ IntSize(const SIZE&);
+ operator SIZE() const;
+#endif
+
+#if PLATFORM(QT)
+ IntSize(const QSize&);
+ operator QSize() const;
+#endif
+#if PLATFORM(SYMBIAN)
+ IntSize(const TSize&);
+ operator TSize() const;
+#endif
+
+
+private:
+ int m_width, m_height;
+};
+
+inline IntSize& operator+=(IntSize& a, const IntSize& b)
+{
+ a.setWidth(a.width() + b.width());
+ a.setHeight(a.height() + b.height());
+ return a;
+}
+
+inline IntSize& operator-=(IntSize& a, const IntSize& b)
+{
+ a.setWidth(a.width() - b.width());
+ a.setHeight(a.height() - b.height());
+ return a;
+}
+
+inline IntSize operator+(const IntSize& a, const IntSize& b)
+{
+ return IntSize(a.width() + b.width(), a.height() + b.height());
+}
+
+inline IntSize operator-(const IntSize& a, const IntSize& b)
+{
+ return IntSize(a.width() - b.width(), a.height() - b.height());
+}
+
+inline IntSize operator-(const IntSize& size)
+{
+ return IntSize(-size.width(), -size.height());
+}
+
+inline bool operator==(const IntSize& a, const IntSize& b)
+{
+ return a.width() == b.width() && a.height() == b.height();
+}
+
+inline bool operator!=(const IntSize& a, const IntSize& b)
+{
+ return a.width() != b.width() || a.height() != b.height();
+}
+
+} // namespace WebCore
+
+#endif // IntSize_h
diff --git a/WebCore/platform/graphics/IntSizeHash.h b/WebCore/platform/graphics/IntSizeHash.h
new file mode 100644
index 0000000..142533e
--- /dev/null
+++ b/WebCore/platform/graphics/IntSizeHash.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef IntSizeHash_h
+#define IntSizeHash_h
+
+#include "IntSize.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+using WebCore::IntSize;
+
+namespace WTF {
+
+ template<> struct IntHash<IntSize> {
+ static unsigned hash(const IntSize& key) { return intHash((static_cast<uint64_t>(key.width()) << 32 | key.height())); }
+ static bool equal(const IntSize& a, const IntSize& b) { return a == b; }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+ template<> struct DefaultHash<IntSize> { typedef IntHash<IntSize> Hash; };
+
+ template<> struct HashTraits<IntSize> : GenericHashTraits<IntSize> {
+ static const bool emptyValueIsZero = true;
+ static const bool needsDestruction = false;
+ static const bool needsRef = false;
+ static IntSize deletedValue() { return IntSize(-1, -1); }
+ };
+} // namespace WTF
+
+#endif
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
new file mode 100644
index 0000000..82e9950
--- /dev/null
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2007 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(VIDEO)
+#include "MediaPlayer.h"
+
+#include "IntRect.h"
+#include "MIMETypeRegistry.h"
+
+#if PLATFORM(MAC)
+#include "MediaPlayerPrivateQTKit.h"
+#elif PLATFORM(WIN)
+#include "MediaPlayerPrivateQuickTimeWin.h"
+#elif PLATFORM(GTK)
+#include "MediaPlayerPrivateGStreamer.h"
+#endif
+
+namespace WebCore {
+
+ MediaPlayer::MediaPlayer(MediaPlayerClient* client)
+ : m_mediaPlayerClient(client)
+ , m_private(new MediaPlayerPrivate(this))
+ , m_parentWidget(0)
+ , m_visible(false)
+ , m_rate(1.0f)
+ , m_volume(0.5f)
+{
+}
+
+MediaPlayer::~MediaPlayer()
+{
+ delete m_private;
+}
+
+void MediaPlayer::load(String url)
+{
+ m_private->load(url);
+}
+
+void MediaPlayer::cancelLoad()
+{
+ m_private->cancelLoad();
+}
+
+void MediaPlayer::play()
+{
+ m_private->play();
+}
+
+void MediaPlayer::pause()
+{
+ m_private->pause();
+}
+
+float MediaPlayer::duration() const
+{
+ return m_private->duration();
+}
+
+float MediaPlayer::currentTime() const
+{
+ return m_private->currentTime();
+}
+
+void MediaPlayer::seek(float time)
+{
+ m_private->seek(time);
+}
+
+bool MediaPlayer::paused() const
+{
+ return m_private->paused();
+}
+
+bool MediaPlayer::seeking() const
+{
+ return m_private->seeking();
+}
+
+IntSize MediaPlayer::naturalSize()
+{
+ return m_private->naturalSize();
+}
+
+bool MediaPlayer::hasVideo()
+{
+ return m_private->hasVideo();
+}
+
+MediaPlayer::NetworkState MediaPlayer::networkState()
+{
+ return m_private->networkState();
+}
+
+MediaPlayer::ReadyState MediaPlayer::readyState()
+{
+ return m_private->readyState();
+}
+
+float MediaPlayer::volume() const
+{
+ return m_volume;
+}
+
+void MediaPlayer::setVolume(float volume)
+{
+ if (volume != m_volume) {
+ m_volume = volume;
+ m_private->setVolume(volume);
+ }
+}
+
+float MediaPlayer::rate() const
+{
+ return m_rate;
+}
+
+void MediaPlayer::setRate(float rate)
+{
+ if (rate == m_rate)
+ return;
+ m_rate = rate;
+ m_private->setRate(rate);
+}
+
+int MediaPlayer::dataRate() const
+{
+ return m_private->dataRate();
+}
+
+void MediaPlayer::setEndTime(float time)
+{
+ m_private->setEndTime(time);
+}
+
+float MediaPlayer::maxTimeBuffered()
+{
+ return m_private->maxTimeBuffered();
+}
+
+float MediaPlayer::maxTimeSeekable()
+{
+ return m_private->maxTimeSeekable();
+}
+
+unsigned MediaPlayer::bytesLoaded()
+{
+ return m_private->bytesLoaded();
+}
+
+bool MediaPlayer::totalBytesKnown()
+{
+ return m_private->totalBytesKnown();
+}
+
+unsigned MediaPlayer::totalBytes()
+{
+ return m_private->totalBytes();
+}
+
+void MediaPlayer::setRect(const IntRect& r)
+{
+ if (m_rect == r)
+ return;
+ m_rect = r;
+ m_private->setRect(r);
+}
+
+bool MediaPlayer::visible() const
+{
+ return m_visible;
+}
+
+void MediaPlayer::setVisible(bool b)
+{
+ if (m_visible == b)
+ return;
+ m_visible = b;
+ m_private->setVisible(b);
+}
+
+void MediaPlayer::paint(GraphicsContext* p, const IntRect& r)
+{
+ m_private->paint(p, r);
+}
+
+void MediaPlayer::getSupportedTypes(HashSet<String>& types)
+{
+ MediaPlayerPrivate::getSupportedTypes(types);
+}
+
+bool MediaPlayer::isAvailable()
+{
+ static bool availabityKnown = false;
+ static bool isAvailable;
+ if (!availabityKnown) {
+ isAvailable = MediaPlayerPrivate::isAvailable();
+ availabityKnown = true;
+ }
+ return isAvailable;
+}
+
+void MediaPlayer::networkStateChanged()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerNetworkStateChanged(this);
+}
+
+void MediaPlayer::readyStateChanged()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerReadyStateChanged(this);
+}
+
+void MediaPlayer::volumeChanged()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerVolumeChanged(this);
+}
+
+void MediaPlayer::timeChanged()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerTimeChanged(this);
+}
+
+void MediaPlayer::repaint()
+{
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerRepaint(this);
+}
+
+}
+#endif
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
new file mode 100644
index 0000000..2c78664
--- /dev/null
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2007 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 MediaPlayer_h
+#define MediaPlayer_h
+
+#if ENABLE(VIDEO)
+
+#include "IntRect.h"
+#include "StringHash.h"
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class IntSize;
+class MediaPlayer;
+class MediaPlayerPrivate;
+class String;
+class Widget;
+
+class MediaPlayerClient
+{
+public:
+ virtual ~MediaPlayerClient() { }
+ virtual void mediaPlayerNetworkStateChanged(MediaPlayer*) { }
+ virtual void mediaPlayerReadyStateChanged(MediaPlayer*) { }
+ virtual void mediaPlayerVolumeChanged(MediaPlayer*) { }
+ virtual void mediaPlayerTimeChanged(MediaPlayer*) { }
+ virtual void mediaPlayerRepaint(MediaPlayer*) { }
+};
+
+class MediaPlayer : Noncopyable {
+public:
+ MediaPlayer(MediaPlayerClient*);
+ virtual ~MediaPlayer();
+
+ static bool isAvailable();
+ static void getSupportedTypes(HashSet<String>&);
+
+ IntSize naturalSize();
+ bool hasVideo();
+
+ Widget* parentWidget() const { return m_parentWidget; }
+ void setParentWidget(Widget* parent) { m_parentWidget = parent; }
+
+ IntRect rect() const { return m_rect; }
+ void setRect(const IntRect& r);
+
+ void load(String url);
+ void cancelLoad();
+
+ bool visible() const;
+ void setVisible(bool);
+
+ void play();
+ void pause();
+
+ bool paused() const;
+ bool seeking() const;
+
+ float duration() const;
+ float currentTime() const;
+ void seek(float time);
+
+ void setEndTime(float time);
+
+ float rate() const;
+ void setRate(float);
+
+ float maxTimeBuffered();
+ float maxTimeSeekable();
+
+ unsigned bytesLoaded();
+ bool totalBytesKnown();
+ unsigned totalBytes();
+
+ float volume() const;
+ void setVolume(float);
+
+ int dataRate() const;
+
+ void paint(GraphicsContext*, const IntRect&);
+
+ enum NetworkState { Empty, LoadFailed, Loading, LoadedMetaData, LoadedFirstFrame, Loaded };
+ NetworkState networkState();
+
+ enum ReadyState { DataUnavailable, CanShowCurrentFrame, CanPlay, CanPlayThrough };
+ ReadyState readyState();
+
+ void networkStateChanged();
+ void readyStateChanged();
+ void volumeChanged();
+ void timeChanged();
+
+ void repaint();
+
+private:
+
+ friend class MediaPlayerPrivate;
+
+ MediaPlayerClient* m_mediaPlayerClient;
+ MediaPlayerPrivate* m_private;
+ Widget* m_parentWidget;
+ IntRect m_rect;
+ bool m_visible;
+ float m_rate;
+ float m_volume;
+};
+
+}
+
+#endif
+#endif
diff --git a/WebCore/platform/graphics/Path.cpp b/WebCore/platform/graphics/Path.cpp
new file mode 100644
index 0000000..f3450be
--- /dev/null
+++ b/WebCore/platform/graphics/Path.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * 2006 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * 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 "FloatPoint.h"
+#include "FloatRect.h"
+#include "PathTraversalState.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
+
+const float QUARTER = 0.552f; // approximation of control point positions on a bezier
+ // to simulate a quarter of a circle.
+namespace WebCore {
+
+static void pathLengthApplierFunction(void* info, const PathElement* element)
+{
+ PathTraversalState& traversalState = *static_cast<PathTraversalState*>(info);
+ if (traversalState.m_success)
+ return;
+ traversalState.m_previous = traversalState.m_current;
+ FloatPoint* points = element->points;
+ float segmentLength = 0.0f;
+ switch (element->type) {
+ case PathElementMoveToPoint:
+ segmentLength = traversalState.moveTo(points[0]);
+ break;
+ case PathElementAddLineToPoint:
+ segmentLength = traversalState.lineTo(points[0]);
+ break;
+ case PathElementAddQuadCurveToPoint:
+ segmentLength = traversalState.quadraticBezierTo(points[0], points[1]);
+ break;
+ case PathElementAddCurveToPoint:
+ segmentLength = traversalState.cubicBezierTo(points[0], points[1], points[2]);
+ break;
+ case PathElementCloseSubpath:
+ segmentLength = traversalState.closeSubpath();
+ break;
+ }
+ traversalState.m_totalLength += segmentLength;
+ if ((traversalState.m_action == PathTraversalState::TraversalPointAtLength ||
+ traversalState.m_action == PathTraversalState::TraversalNormalAngleAtLength) &&
+ (traversalState.m_totalLength >= traversalState.m_desiredLength)) {
+ FloatSize change = traversalState.m_current - traversalState.m_previous;
+ float slope = atan2f(change.height(), change.width());
+
+ if (traversalState.m_action == PathTraversalState::TraversalPointAtLength) {
+ float offset = traversalState.m_desiredLength - traversalState.m_totalLength;
+ traversalState.m_current.move(offset * cosf(slope), offset * sinf(slope));
+ } else {
+ static const float rad2deg = 180.0f / piFloat;
+ traversalState.m_normalAngle = slope * rad2deg;
+ }
+
+ traversalState.m_success = true;
+ }
+}
+
+float Path::length()
+{
+ PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
+ apply(&traversalState, pathLengthApplierFunction);
+ return traversalState.m_totalLength;
+}
+
+FloatPoint Path::pointAtLength(float length, bool& ok)
+{
+ PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
+ traversalState.m_desiredLength = length;
+ apply(&traversalState, pathLengthApplierFunction);
+ ok = traversalState.m_success;
+ return traversalState.m_current;
+}
+
+float Path::normalAngleAtLength(float length, bool& ok)
+{
+ PathTraversalState traversalState(PathTraversalState::TraversalNormalAngleAtLength);
+ traversalState.m_desiredLength = length;
+ apply(&traversalState, pathLengthApplierFunction);
+ ok = traversalState.m_success;
+ return traversalState.m_normalAngle;
+}
+
+Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& roundingRadii)
+{
+ Path path;
+ float x = rectangle.x();
+ float y = rectangle.y();
+ float width = rectangle.width();
+ float height = rectangle.height();
+ float rx = roundingRadii.width();
+ float ry = roundingRadii.height();
+ if (width <= 0.0f || height <= 0.0f)
+ return path;
+
+ float dx = rx, dy = ry;
+ // If rx is greater than half of the width of the rectangle
+ // then set rx to half of the width (required in SVG spec)
+ if (dx > width * 0.5f)
+ dx = width * 0.5f;
+
+ // If ry is greater than half of the height of the rectangle
+ // then set ry to half of the height (required in SVG spec)
+ if (dy > height * 0.5f)
+ dy = height * 0.5f;
+
+ path.moveTo(FloatPoint(x + dx, y));
+
+ if (dx < width * 0.5f)
+ path.addLineTo(FloatPoint(x + width - rx, y));
+
+ path.addBezierCurveTo(FloatPoint(x + width - dx * (1 - QUARTER), y), FloatPoint(x + width, y + dy * (1 - QUARTER)), FloatPoint(x + width, y + dy));
+
+ if (dy < height * 0.5)
+ path.addLineTo(FloatPoint(x + width, y + height - dy));
+
+ path.addBezierCurveTo(FloatPoint(x + width, y + height - dy * (1 - QUARTER)), FloatPoint(x + width - dx * (1 - QUARTER), y + height), FloatPoint(x + width - dx, y + height));
+
+ if (dx < width * 0.5)
+ path.addLineTo(FloatPoint(x + dx, y + height));
+
+ path.addBezierCurveTo(FloatPoint(x + dx * (1 - QUARTER), y + height), FloatPoint(x, y + height - dy * (1 - QUARTER)), FloatPoint(x, y + height - dy));
+
+ if (dy < height * 0.5)
+ path.addLineTo(FloatPoint(x, y + dy));
+
+ path.addBezierCurveTo(FloatPoint(x, y + dy * (1 - QUARTER)), FloatPoint(x + dx * (1 - QUARTER), y), FloatPoint(x + dx, y));
+
+ path.closeSubpath();
+
+ return path;
+}
+
+Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius)
+{
+ Path path;
+
+ float width = rectangle.width();
+ float height = rectangle.height();
+ if (width <= 0.0 || height <= 0.0)
+ return path;
+
+ if (width < topLeftRadius.width() + topRightRadius.width()
+ || width < bottomLeftRadius.width() + bottomRightRadius.width()
+ || height < topLeftRadius.height() + bottomLeftRadius.height()
+ || height < topRightRadius.height() + bottomRightRadius.height())
+ // If all the radii cannot be accommodated, return a rect.
+ return createRectangle(rectangle);
+
+ float x = rectangle.x();
+ float y = rectangle.y();
+
+ path.moveTo(FloatPoint(x + topLeftRadius.width(), y));
+
+ path.addLineTo(FloatPoint(x + width - topRightRadius.width(), y));
+
+ path.addBezierCurveTo(FloatPoint(x + width - topRightRadius.width() * (1 - QUARTER), y), FloatPoint(x + width, y + topRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width, y + topRightRadius.height()));
+
+ path.addLineTo(FloatPoint(x + width, y + height - bottomRightRadius.height()));
+
+ path.addBezierCurveTo(FloatPoint(x + width, y + height - bottomRightRadius.height() * (1 - QUARTER)), FloatPoint(x + width - bottomRightRadius.width() * (1 - QUARTER), y + height), FloatPoint(x + width - bottomRightRadius.width(), y + height));
+
+ path.addLineTo(FloatPoint(x + bottomLeftRadius.width(), y + height));
+
+ path.addBezierCurveTo(FloatPoint(x + bottomLeftRadius.width() * (1 - QUARTER), y + height), FloatPoint(x, y + height - bottomLeftRadius.height() * (1 - QUARTER)), FloatPoint(x, y + height - bottomLeftRadius.height()));
+
+ path.addLineTo(FloatPoint(x, y + topLeftRadius.height()));
+
+ path.addBezierCurveTo(FloatPoint(x, y + topLeftRadius.height() * (1 - QUARTER)), FloatPoint(x + topLeftRadius.width() * (1 - QUARTER), y), FloatPoint(x + topLeftRadius.width(), y));
+
+ path.closeSubpath();
+
+ return path;
+}
+
+Path Path::createRectangle(const FloatRect& rectangle)
+{
+ Path path;
+ float x = rectangle.x();
+ float y = rectangle.y();
+ float width = rectangle.width();
+ float height = rectangle.height();
+ if (width <= 0.0f || height <= 0.0f)
+ return path;
+
+ path.moveTo(FloatPoint(x, y));
+ path.addLineTo(FloatPoint(x + width, y));
+ path.addLineTo(FloatPoint(x + width, y + height));
+ path.addLineTo(FloatPoint(x, y + height));
+ path.closeSubpath();
+
+ return path;
+}
+
+Path Path::createEllipse(const FloatPoint& center, float rx, float ry)
+{
+ float cx = center.x();
+ float cy = center.y();
+ Path path;
+ if (rx <= 0.0f || ry <= 0.0f)
+ return path;
+
+ float x = cx;
+ float y = cy;
+
+ unsigned step = 0, num = 100;
+ bool running = true;
+ while (running)
+ {
+ if (step == num)
+ {
+ running = false;
+ break;
+ }
+
+ float angle = static_cast<float>(step) / static_cast<float>(num) * 2.0f * piFloat;
+ x = cx + cosf(angle) * rx;
+ y = cy + sinf(angle) * ry;
+
+ step++;
+ if (step == 1)
+ path.moveTo(FloatPoint(x, y));
+ else
+ path.addLineTo(FloatPoint(x, y));
+ }
+
+ path.closeSubpath();
+
+ return path;
+}
+
+Path Path::createCircle(const FloatPoint& center, float r)
+{
+ return createEllipse(center, r, r);
+}
+
+Path Path::createLine(const FloatPoint& start, const FloatPoint& end)
+{
+ Path path;
+ if (start.x() == end.x() && start.y() == end.y())
+ return path;
+
+ path.moveTo(start);
+ path.addLineTo(end);
+
+ return path;
+}
+
+}
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
new file mode 100644
index 0000000..5150649
--- /dev/null
+++ b/WebCore/platform/graphics/Path.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * 2006 Rob Buis <buis@kde.org>
+ *
+ * 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 Path_h
+#define Path_h
+
+#if PLATFORM(CG)
+typedef struct CGPath PlatformPath;
+#elif PLATFORM(QT)
+class QPainterPath;
+typedef QPainterPath PlatformPath;
+#elif PLATFORM(WX) && USE(WXGC)
+class wxGraphicsPath;
+typedef wxGraphicsPath PlatformPath;
+#elif PLATFORM(CAIRO)
+namespace WebCore {
+ struct CairoPath;
+}
+typedef WebCore::CairoPath PlatformPath;
+#else
+typedef void PlatformPath;
+#endif
+
+namespace WebCore {
+
+ class AffineTransform;
+ class FloatPoint;
+ class FloatSize;
+ class FloatRect;
+ class String;
+
+ enum WindRule {
+ RULE_NONZERO = 0,
+ RULE_EVENODD = 1
+ };
+
+ enum PathElementType {
+ PathElementMoveToPoint,
+ PathElementAddLineToPoint,
+ PathElementAddQuadCurveToPoint,
+ PathElementAddCurveToPoint,
+ PathElementCloseSubpath
+ };
+
+ struct PathElement {
+ PathElementType type;
+ FloatPoint* points;
+ };
+
+ typedef void (*PathApplierFunction) (void* info, const PathElement*);
+
+ class Path {
+ public:
+ Path();
+ ~Path();
+
+ Path(const Path&);
+ Path& operator=(const Path&);
+
+ bool contains(const FloatPoint&, WindRule rule = RULE_NONZERO) const;
+ FloatRect boundingRect() const;
+
+ float length();
+ FloatPoint pointAtLength(float length, bool& ok);
+ float normalAngleAtLength(float length, bool& ok);
+
+ void clear();
+ bool isEmpty() const;
+
+ 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 addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
+ void addRect(const FloatRect&);
+ void addEllipse(const FloatRect&);
+
+ void translate(const FloatSize&);
+
+ void setWindingRule(WindRule rule) { m_rule = rule; }
+ WindRule windingRule() const { return m_rule; }
+
+ String debugString() const;
+
+ PlatformPath* platformPath() const { return m_path; }
+
+ static Path createRoundedRectangle(const FloatRect&, const FloatSize& roundingRadii);
+ static Path createRoundedRectangle(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
+ static Path createRectangle(const FloatRect&);
+ static Path createEllipse(const FloatPoint& center, float rx, float ry);
+ static Path createCircle(const FloatPoint& center, float r);
+ static Path createLine(const FloatPoint&, const FloatPoint&);
+
+ void apply(void* info, PathApplierFunction) const;
+ void transform(const AffineTransform&);
+
+ private:
+ PlatformPath* m_path;
+ WindRule m_rule;
+ };
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/PathTraversalState.cpp b/WebCore/platform/graphics/PathTraversalState.cpp
new file mode 100644
index 0000000..d202649
--- /dev/null
+++ b/WebCore/platform/graphics/PathTraversalState.cpp
@@ -0,0 +1,207 @@
+/*
+ * This file is part of the WebKit open source project.
+ *
+ * Copyright (C) 2006, 2007 Eric Seidel (eric@webkit.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * 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 "PathTraversalState.h"
+
+#include "Path.h"
+
+#include <math.h>
+
+namespace WebCore {
+
+static const float kPathSegmentLengthTolerance = 0.00001f;
+
+static inline FloatPoint midPoint(const FloatPoint& first, const FloatPoint& second)
+{
+ return FloatPoint((first.x() + second.x()) / 2.0f, (first.y() + second.y()) / 2.0f);
+}
+
+static inline float distanceLine(const FloatPoint& start, const FloatPoint& end)
+{
+ return sqrtf((end.x() - start.x()) * (end.x() - start.x()) + (end.y() - start.y()) * (end.y() - start.y()));
+}
+
+struct QuadraticBezier {
+ QuadraticBezier() { }
+ QuadraticBezier(const FloatPoint& s, const FloatPoint& c, const FloatPoint& e)
+ : start(s)
+ , control(c)
+ , end(e)
+ {
+ }
+
+ float approximateDistance() const
+ {
+ return distanceLine(start, control) + distanceLine(control, end);
+ }
+
+ void split(QuadraticBezier& left, QuadraticBezier& right) const
+ {
+ left.control = midPoint(start, control);
+ right.control = midPoint(control, end);
+
+ FloatPoint leftControlToRightControl = midPoint(left.control, right.control);
+ left.end = leftControlToRightControl;
+ right.start = leftControlToRightControl;
+
+ left.start = start;
+ right.end = end;
+ }
+
+ FloatPoint start;
+ FloatPoint control;
+ FloatPoint end;
+};
+
+struct CubicBezier {
+ CubicBezier() { }
+ CubicBezier(const FloatPoint& s, const FloatPoint& c1, const FloatPoint& c2, const FloatPoint& e)
+ : start(s)
+ , control1(c1)
+ , control2(c2)
+ , end(e)
+ {
+ }
+
+ float approximateDistance() const
+ {
+ return distanceLine(start, control1) + distanceLine(control1, control2) + distanceLine(control2, end);
+ }
+
+ void split(CubicBezier& left, CubicBezier& right) const
+ {
+ FloatPoint startToControl1 = midPoint(control1, control2);
+
+ left.start = start;
+ left.control1 = midPoint(start, control1);
+ left.control2 = midPoint(left.control1, startToControl1);
+
+ right.control2 = midPoint(control2, end);
+ right.control1 = midPoint(right.control2, startToControl1);
+ right.end = end;
+
+ FloatPoint leftControl2ToRightControl1 = midPoint(left.control2, right.control1);
+ left.end = leftControl2ToRightControl1;
+ right.start = leftControl2ToRightControl1;
+ }
+
+ FloatPoint start;
+ FloatPoint control1;
+ FloatPoint control2;
+ FloatPoint end;
+};
+
+// FIXME: This function is possibly very slow due to the ifs required for proper path measuring
+// A simple speed-up would be to use an additional boolean template parameter to control whether
+// to use the "fast" version of this function with no PathTraversalState updating, vs. the slow
+// version which does update the PathTraversalState. We'll have to shark it to see if that's necessary.
+// Another check which is possible up-front (to send us down the fast path) would be to check if
+// approximateDistance() + current total distance > desired distance
+template<class CurveType>
+static float curveLength(PathTraversalState& traversalState, CurveType curve)
+{
+ Vector<CurveType> curveStack;
+ curveStack.append(curve);
+
+ float totalLength = 0.0f;
+ do {
+ float length = curve.approximateDistance();
+ if ((length - distanceLine(curve.start, curve.end)) > kPathSegmentLengthTolerance) {
+ CurveType left, right;
+ curve.split(left, right);
+ curve = left;
+ curveStack.append(right);
+ } else {
+ totalLength += length;
+ if (traversalState.m_action == PathTraversalState::TraversalPointAtLength
+ || traversalState.m_action == PathTraversalState::TraversalNormalAngleAtLength) {
+ traversalState.m_previous = curve.start;
+ traversalState.m_current = curve.end;
+ if (traversalState.m_totalLength + totalLength > traversalState.m_desiredLength)
+ return totalLength;
+ }
+ curve = curveStack.last();
+ curveStack.removeLast();
+ }
+ } while (!curveStack.isEmpty());
+
+ return totalLength;
+}
+
+PathTraversalState::PathTraversalState(PathTraversalAction action)
+ : m_action(action)
+ , m_success(false)
+ , m_totalLength(0.0f)
+ , m_segmentIndex(0)
+ , m_desiredLength(0.0f)
+ , m_normalAngle(0.0f)
+{
+}
+
+float PathTraversalState::closeSubpath()
+{
+ float distance = distanceLine(m_current, m_start);
+ m_start = m_control1 = m_control2 = m_current;
+ return distance;
+}
+
+float PathTraversalState::moveTo(const FloatPoint& point)
+{
+ m_current = m_start = m_control1 = m_control2 = point;
+ return 0.0f;
+}
+
+float PathTraversalState::lineTo(const FloatPoint& point)
+{
+ float distance = distanceLine(m_current, point);
+ m_current = m_control1 = m_control2 = point;
+ return distance;
+}
+
+float PathTraversalState::quadraticBezierTo(const FloatPoint& newControl, const FloatPoint& newEnd)
+{
+ float distance = curveLength<QuadraticBezier>(*this, QuadraticBezier(m_current, newControl, newEnd));
+
+ m_control1 = newControl;
+ m_control2 = newEnd;
+
+ if (m_action != TraversalPointAtLength && m_action != TraversalNormalAngleAtLength)
+ m_current = newEnd;
+
+ return distance;
+}
+
+float PathTraversalState::cubicBezierTo(const FloatPoint& newControl1, const FloatPoint& newControl2, const FloatPoint& newEnd)
+{
+ float distance = curveLength<CubicBezier>(*this, CubicBezier(m_current, newControl1, newControl2, newEnd));
+
+ m_control1 = newEnd;
+ m_control2 = newControl2;
+
+ if (m_action != TraversalPointAtLength && m_action != TraversalNormalAngleAtLength)
+ m_current = newEnd;
+
+ return distance;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/PathTraversalState.h b/WebCore/platform/graphics/PathTraversalState.h
new file mode 100644
index 0000000..5b75767
--- /dev/null
+++ b/WebCore/platform/graphics/PathTraversalState.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006, 2007 Eric Seidel <eric@webkit.org>
+ *
+ * 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 PathTraversalState_h
+#define PathTraversalState_h
+
+#include "FloatPoint.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+ class Path;
+
+ class PathTraversalState {
+ public:
+ enum PathTraversalAction {
+ TraversalTotalLength,
+ TraversalPointAtLength,
+ TraversalSegmentAtLength,
+ TraversalNormalAngleAtLength
+ };
+
+ PathTraversalState(PathTraversalAction);
+
+ float closeSubpath();
+ float moveTo(const FloatPoint&);
+ float lineTo(const FloatPoint&);
+ float quadraticBezierTo(const FloatPoint& newControl, const FloatPoint& newEnd);
+ float cubicBezierTo(const FloatPoint& newControl1, const FloatPoint& newControl2, const FloatPoint& newEnd);
+
+ public:
+ PathTraversalAction m_action;
+ bool m_success;
+
+ FloatPoint m_current;
+ FloatPoint m_start;
+ FloatPoint m_control1;
+ FloatPoint m_control2;
+
+ float m_totalLength;
+ unsigned m_segmentIndex;
+ float m_desiredLength;
+
+ // For normal calculations
+ FloatPoint m_previous;
+ float m_normalAngle; // degrees
+ };
+}
+
+#endif
diff --git a/WebCore/platform/graphics/Pen.cpp b/WebCore/platform/graphics/Pen.cpp
new file mode 100644
index 0000000..a3dcb86
--- /dev/null
+++ b/WebCore/platform/graphics/Pen.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2003 Apple Computer, 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"
+#include "Pen.h"
+
+namespace WebCore {
+
+Pen::Pen(const Color &color, unsigned width, PenStyle style) : m_style(style), m_width(width), m_color(color)
+{
+}
+
+const Color &Pen::color() const
+{
+ return m_color;
+}
+
+unsigned Pen::width() const
+{
+ return m_width;
+}
+
+Pen::PenStyle Pen::style() const
+{
+ return m_style;
+}
+
+void Pen::setColor(const Color &color)
+{
+ m_color = color;
+}
+
+void Pen::setWidth(unsigned width)
+{
+ m_width = width;
+}
+
+void Pen::setStyle(PenStyle style)
+{
+ m_style = style;
+}
+
+bool Pen::operator==(const Pen &compareTo) const
+{
+ return (m_width == compareTo.m_width) &&
+ (m_style == compareTo.m_style) &&
+ (m_color == compareTo.m_color);
+}
+
+bool Pen::operator!=(const Pen &compareTo) const
+{
+ return !(*this == compareTo);
+}
+
+}
diff --git a/WebCore/platform/graphics/Pen.h b/WebCore/platform/graphics/Pen.h
new file mode 100644
index 0000000..cb45a2e
--- /dev/null
+++ b/WebCore/platform/graphics/Pen.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2003-6 Apple Computer, 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 Pen_h
+#define Pen_h
+
+#include "Color.h"
+
+#if PLATFORM(WX)
+class wxPen;
+#endif
+
+namespace WebCore {
+
+class Pen {
+public:
+ enum PenStyle {
+ NoPen,
+ SolidLine,
+ DotLine,
+ DashLine
+ };
+
+ Pen(const Color &c = Color::black, unsigned w = 0, PenStyle ps = SolidLine);
+
+ const Color &color() const;
+ unsigned width() const;
+ PenStyle style() const;
+
+ void setColor(const Color &);
+ void setWidth(unsigned);
+ void setStyle(PenStyle);
+
+ bool operator==(const Pen &) const;
+ bool operator!=(const Pen &) const;
+
+#if PLATFORM(WX)
+ Pen(const wxPen&);
+ operator wxPen() const;
+#endif
+
+private:
+ PenStyle m_style;
+ unsigned m_width;
+ Color m_color;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/SegmentedFontData.cpp b/WebCore/platform/graphics/SegmentedFontData.cpp
new file mode 100644
index 0000000..ceefe4f
--- /dev/null
+++ b/WebCore/platform/graphics/SegmentedFontData.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "SegmentedFontData.h"
+
+#include "SimpleFontData.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+SegmentedFontData::~SegmentedFontData()
+{
+}
+
+const SimpleFontData* SegmentedFontData::fontDataForCharacter(UChar32 c) const
+{
+ Vector<FontDataRange>::const_iterator end = m_ranges.end();
+ for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) {
+ if (it->from() <= c && it->to() >= c)
+ return it->fontData();
+ }
+ return m_ranges[0].fontData();
+}
+
+bool SegmentedFontData::containsCharacters(const UChar* characters, int length) const
+{
+ Vector<FontDataRange>::const_iterator end = m_ranges.end();
+ for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) {
+ if (it->from() <= characters[0] && it->to() >= characters[0])
+ return true;
+ }
+ return false;
+}
+
+bool SegmentedFontData::isCustomFont() const
+{
+ // All segmented fonts are custom fonts.
+ return true;
+}
+
+bool SegmentedFontData::isLoading() const
+{
+ Vector<FontDataRange>::const_iterator end = m_ranges.end();
+ for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) {
+ if (it->fontData()->isLoading())
+ return true;
+ }
+ return false;
+}
+
+bool SegmentedFontData::isSegmented() const
+{
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/SegmentedFontData.h b/WebCore/platform/graphics/SegmentedFontData.h
new file mode 100644
index 0000000..1adec15
--- /dev/null
+++ b/WebCore/platform/graphics/SegmentedFontData.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 SegmentedFontData_h
+#define SegmentedFontData_h
+
+#include "FontData.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class SimpleFontData;
+
+struct FontDataRange {
+ FontDataRange(UChar32 from, UChar32 to, const SimpleFontData* fontData)
+ : m_from(from)
+ , m_to(to)
+ , m_fontData(fontData)
+ {
+ }
+
+ UChar32 from() const { return m_from; }
+ UChar32 to() const { return m_to; }
+ const SimpleFontData* fontData() const { return m_fontData; }
+
+private:
+ UChar32 m_from;
+ UChar32 m_to;
+ const SimpleFontData* m_fontData;
+};
+
+class SegmentedFontData : public FontData {
+public:
+ virtual ~SegmentedFontData();
+
+ virtual const SimpleFontData* fontDataForCharacter(UChar32) const;
+ virtual bool containsCharacters(const UChar*, int length) const;
+
+ virtual bool isCustomFont() const;
+ virtual bool isLoading() const;
+ virtual bool isSegmented() const;
+
+ void appendRange(const FontDataRange& range) { m_ranges.append(range); }
+ unsigned numRanges() const { return m_ranges.size(); }
+ const FontDataRange& rangeAt(unsigned i) const { return m_ranges[i]; }
+
+private:
+ Vector<FontDataRange, 1> m_ranges;
+};
+
+} // namespace WebCore
+
+#endif // SegmentedFontData_h
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
new file mode 100644
index 0000000..24812f7
--- /dev/null
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2005, 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov
+ *
+ * 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"
+
+#if ENABLE(SVG_FONTS)
+#include "SVGFontData.h"
+#include "SVGFontFaceElement.h"
+#endif
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool loading, SVGFontData* svgFontData)
+ : m_font(f)
+ , m_treatAsFixedPitch(false)
+#if ENABLE(SVG_FONTS)
+ , m_svgFontData(svgFontData)
+#endif
+ , m_isCustomFont(customFont)
+ , m_isLoading(loading)
+ , m_smallCapsFontData(0)
+{
+#if ENABLE(SVG_FONTS) && !PLATFORM(QT)
+ if (SVGFontFaceElement* svgFontFaceElement = svgFontData ? svgFontData->svgFontFaceElement() : 0) {
+ m_unitsPerEm = svgFontFaceElement->unitsPerEm();
+
+ double scale = f.size();
+ if (m_unitsPerEm)
+ scale /= m_unitsPerEm;
+
+ m_ascent = static_cast<int>(svgFontFaceElement->ascent() * scale);
+ m_descent = static_cast<int>(svgFontFaceElement->descent() * scale);
+ m_xHeight = static_cast<int>(svgFontFaceElement->xHeight() * scale);
+ m_lineGap = 0.1f * f.size();
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ m_spaceGlyph = 0;
+ m_spaceWidth = 0;
+ m_adjustedSpaceWidth = 0;
+ determinePitch();
+ m_missingGlyphData.fontData = this;
+ m_missingGlyphData.glyph = 0;
+ return;
+ }
+#endif
+
+ platformInit();
+
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ if (!glyphPageZero) {
+ LOG_ERROR("Failed to get glyph page zero.");
+ m_spaceGlyph = 0;
+ m_spaceWidth = 0;
+ m_adjustedSpaceWidth = 0;
+ determinePitch();
+ m_missingGlyphData.fontData = this;
+ m_missingGlyphData.glyph = 0;
+ return;
+ }
+
+ // Nasty hack to determine if we should round or ceil space widths.
+ // If the font is monospace or fake monospace we ceil to ensure that
+ // every character and the space are the same width. Otherwise we round.
+ m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
+ float width = widthForGlyph(m_spaceGlyph);
+ m_spaceWidth = width;
+ determinePitch();
+ m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
+
+ // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE.
+ // Helvetica is an example of a non-zero width ZERO WIDTH SPACE glyph.
+ // See <http://bugs.webkit.org/show_bug.cgi?id=13178>
+ // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
+ // are mapped to the ZERO WIDTH SPACE glyph.
+ Glyph zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
+ if (zeroWidthSpaceGlyph) {
+ if (zeroWidthSpaceGlyph != m_spaceGlyph)
+ m_glyphToWidthMap.setWidthForGlyph(zeroWidthSpaceGlyph, 0);
+ else
+ LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width not overridden.");
+ }
+
+ m_missingGlyphData.fontData = this;
+ m_missingGlyphData.glyph = 0;
+}
+
+SimpleFontData::~SimpleFontData()
+{
+#if ENABLE(SVG_FONTS) && !PLATFORM(QT)
+ if (!m_svgFontData || !m_svgFontData->svgFontFaceElement())
+#endif
+ platformDestroy();
+
+ // We only get deleted when the cache gets cleared. Since the smallCapsRenderer is also in that cache,
+ // it will be deleted then, so we don't need to do anything here.
+}
+
+float SimpleFontData::widthForGlyph(Glyph glyph) const
+{
+ float width = m_glyphToWidthMap.widthForGlyph(glyph);
+ if (width != cGlyphWidthUnknown)
+ return width;
+
+ width = platformWidthForGlyph(glyph);
+ m_glyphToWidthMap.setWidthForGlyph(glyph, width);
+
+ return width;
+}
+
+const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
+{
+ return this;
+}
+
+bool SimpleFontData::isSegmented() const
+{
+ return false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
new file mode 100644
index 0000000..c444a6f
--- /dev/null
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -0,0 +1,184 @@
+/*
+ * This file is part of the internal font implementation.
+ *
+ * Copyright (C) 2006, 2008 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SimpleFontData_h
+#define SimpleFontData_h
+
+#include "FontData.h"
+#include "FontPlatformData.h"
+#include "GlyphPageTreeNode.h"
+#include "GlyphWidthMap.h"
+#include <wtf/OwnPtr.h>
+
+#if PLATFORM(MAC)
+typedef struct OpaqueATSUStyle* ATSUStyle;
+#endif
+
+#if PLATFORM(WIN)
+#include <usp10.h>
+#endif
+
+#if PLATFORM(CAIRO)
+#include <cairo.h>
+#endif
+
+namespace WebCore {
+
+class FontDescription;
+class FontPlatformData;
+class SharedBuffer;
+class SVGFontData;
+class WidthMap;
+
+enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
+
+class SimpleFontData : public FontData {
+public:
+ SimpleFontData(const FontPlatformData&, bool customFont = false, bool loading = false, SVGFontData* data = 0);
+ virtual ~SimpleFontData();
+
+public:
+ const FontPlatformData& platformData() const { return m_font; }
+ SimpleFontData* smallCapsFontData(const FontDescription& fontDescription) const;
+
+ // vertical metrics
+ int ascent() const { return m_ascent; }
+ int descent() const { return m_descent; }
+ int lineSpacing() const { return m_lineSpacing; }
+ int lineGap() const { return m_lineGap; }
+ float xHeight() const { return m_xHeight; }
+ unsigned unitsPerEm() const { return m_unitsPerEm; }
+
+ float widthForGlyph(Glyph) const;
+ float platformWidthForGlyph(Glyph) const;
+
+ virtual const SimpleFontData* fontDataForCharacter(UChar32) const;
+ virtual bool containsCharacters(const UChar*, int length) const;
+
+ void determinePitch();
+ Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
+
+#if ENABLE(SVG_FONTS)
+ SVGFontData* svgFontData() const { return m_svgFontData.get(); }
+ bool isSVGFont() const { return m_svgFontData; }
+#else
+ bool isSVGFont() const { return false; }
+#endif
+
+ virtual bool isCustomFont() const { return m_isCustomFont; }
+ virtual bool isLoading() const { return m_isLoading; }
+ virtual bool isSegmented() const;
+
+ const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
+
+#if PLATFORM(MAC)
+ NSFont* getNSFont() const { return m_font.font(); }
+ void checkShapesArabic() const;
+ bool shapesArabic() const
+ {
+ if (!m_checkedShapesArabic)
+ checkShapesArabic();
+ return m_shapesArabic;
+ }
+#endif
+
+#if PLATFORM(WIN)
+ bool isSystemFont() const { return m_isSystemFont; }
+ SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
+ SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
+
+ 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_font.font(); }
+#endif
+
+private:
+ void platformInit();
+ void platformDestroy();
+
+ void commonInit();
+
+#if PLATFORM(WIN)
+ void initGDIFont();
+ void platformCommonDestroy();
+ float widthForGDIGlyph(Glyph glyph) const;
+#endif
+
+public:
+ int m_ascent;
+ int m_descent;
+ int m_lineSpacing;
+ int m_lineGap;
+ float m_xHeight;
+ unsigned m_unitsPerEm;
+
+ FontPlatformData m_font;
+
+ mutable GlyphWidthMap m_glyphToWidthMap;
+
+ bool m_treatAsFixedPitch;
+
+#if ENABLE(SVG_FONTS)
+ OwnPtr<SVGFontData> m_svgFontData;
+#endif
+
+ bool m_isCustomFont; // Whether or not we are custom font loaded via @font-face
+ bool m_isLoading; // Whether or not this custom font is still in the act of loading.
+
+ Glyph m_spaceGlyph;
+ float m_spaceWidth;
+ float m_adjustedSpaceWidth;
+
+ GlyphData m_missingGlyphData;
+
+ mutable SimpleFontData* m_smallCapsFontData;
+
+#if PLATFORM(CG)
+ float m_syntheticBoldOffset;
+#endif
+
+#if PLATFORM(MAC)
+ void* m_styleGroup;
+ mutable ATSUStyle m_ATSUStyle;
+ mutable bool m_ATSUStyleInitialized;
+ mutable bool m_ATSUMirrors;
+ mutable bool m_checkedShapesArabic;
+ mutable bool m_shapesArabic;
+#endif
+
+#if PLATFORM(WIN)
+ bool m_isSystemFont;
+ mutable SCRIPT_CACHE m_scriptCache;
+ mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // SimpleFontData_h
diff --git a/WebCore/platform/graphics/StringTruncator.cpp b/WebCore/platform/graphics/StringTruncator.cpp
new file mode 100644
index 0000000..0490a9f
--- /dev/null
+++ b/WebCore/platform/graphics/StringTruncator.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 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.
+ * 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 "StringTruncator.h"
+
+#include "CharacterNames.h"
+#include "Font.h"
+#include "FontPlatformData.h"
+#include "TextBreakIterator.h"
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+#define STRING_BUFFER_SIZE 2048
+
+typedef unsigned TruncationFunction(const String&, unsigned length, unsigned keepCount, UChar* buffer);
+
+static inline int textBreakAtOrPreceding(TextBreakIterator* it, int offset)
+{
+ if (isTextBreak(it, offset))
+ return offset;
+
+ int result = textBreakPreceding(it, offset);
+ return result == TextBreakDone ? 0 : result;
+}
+
+static inline int boundedTextBreakFollowing(TextBreakIterator* it, int offset, int length)
+{
+ int result = textBreakFollowing(it, offset);
+ return result == TextBreakDone ? length : result;
+}
+
+static unsigned centerTruncateToBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer)
+{
+ ASSERT(keepCount < length);
+ ASSERT(keepCount < STRING_BUFFER_SIZE);
+
+ unsigned omitStart = (keepCount + 1) / 2;
+ TextBreakIterator* it = characterBreakIterator(string.characters(), length);
+ unsigned omitEnd = boundedTextBreakFollowing(it, omitStart + (length - keepCount) - 1, length);
+ omitStart = textBreakAtOrPreceding(it, omitStart);
+
+ unsigned truncatedLength = omitStart + 1 + (length - omitEnd);
+ ASSERT(truncatedLength <= length);
+
+ memcpy(buffer, string.characters(), sizeof(UChar) * omitStart);
+ buffer[omitStart] = horizontalEllipsis;
+ memcpy(&buffer[omitStart + 1], &string.characters()[omitEnd], sizeof(UChar) * (length - omitEnd));
+
+ return truncatedLength;
+}
+
+static unsigned rightTruncateToBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer)
+{
+ ASSERT(keepCount < length);
+ ASSERT(keepCount < STRING_BUFFER_SIZE);
+
+ TextBreakIterator* it = characterBreakIterator(string.characters(), length);
+ unsigned keepLength = textBreakAtOrPreceding(it, keepCount);
+ unsigned truncatedLength = keepLength + 1;
+
+ memcpy(buffer, string.characters(), sizeof(UChar) * keepLength);
+ buffer[keepLength] = horizontalEllipsis;
+
+ return truncatedLength;
+}
+
+static float stringWidth(const Font& renderer, const UChar* characters, unsigned length, bool disableRoundingHacks)
+{
+ TextRun run(characters, length);
+ if (disableRoundingHacks)
+ run.disableRoundingHacks();
+ return renderer.floatWidth(run);
+}
+
+static String truncateString(const String& string, float maxWidth, const Font& font, TruncationFunction truncateToBuffer, bool disableRoundingHacks)
+{
+ if (string.isEmpty())
+ return string;
+
+ ASSERT(maxWidth >= 0);
+
+ float currentEllipsisWidth = stringWidth(font, &horizontalEllipsis, 1, disableRoundingHacks);
+
+ UChar stringBuffer[STRING_BUFFER_SIZE];
+ unsigned truncatedLength;
+ unsigned keepCount;
+ unsigned length = string.length();
+
+ if (length > STRING_BUFFER_SIZE) {
+ keepCount = STRING_BUFFER_SIZE - 1; // need 1 character for the ellipsis
+ truncatedLength = centerTruncateToBuffer(string, length, keepCount, stringBuffer);
+ } else {
+ keepCount = length;
+ memcpy(stringBuffer, string.characters(), sizeof(UChar) * length);
+ truncatedLength = length;
+ }
+
+ float width = stringWidth(font, stringBuffer, truncatedLength, disableRoundingHacks);
+ if (width <= maxWidth)
+ return string;
+
+ unsigned keepCountForLargestKnownToFit = 0;
+ float widthForLargestKnownToFit = currentEllipsisWidth;
+
+ unsigned keepCountForSmallestKnownToNotFit = keepCount;
+ float widthForSmallestKnownToNotFit = width;
+
+ if (currentEllipsisWidth >= maxWidth) {
+ keepCountForLargestKnownToFit = 1;
+ keepCountForSmallestKnownToNotFit = 2;
+ }
+
+ while (keepCountForLargestKnownToFit + 1 < keepCountForSmallestKnownToNotFit) {
+ ASSERT(widthForLargestKnownToFit <= maxWidth);
+ ASSERT(widthForSmallestKnownToNotFit > maxWidth);
+
+ float ratio = (keepCountForSmallestKnownToNotFit - keepCountForLargestKnownToFit)
+ / (widthForSmallestKnownToNotFit - widthForLargestKnownToFit);
+ keepCount = static_cast<unsigned>(maxWidth * ratio);
+
+ if (keepCount <= keepCountForLargestKnownToFit) {
+ keepCount = keepCountForLargestKnownToFit + 1;
+ } else if (keepCount >= keepCountForSmallestKnownToNotFit) {
+ keepCount = keepCountForSmallestKnownToNotFit - 1;
+ }
+
+ ASSERT(keepCount < length);
+ ASSERT(keepCount > 0);
+ ASSERT(keepCount < keepCountForSmallestKnownToNotFit);
+ ASSERT(keepCount > keepCountForLargestKnownToFit);
+
+ truncatedLength = truncateToBuffer(string, length, keepCount, stringBuffer);
+
+ width = stringWidth(font, stringBuffer, truncatedLength, disableRoundingHacks);
+ if (width <= maxWidth) {
+ keepCountForLargestKnownToFit = keepCount;
+ widthForLargestKnownToFit = width;
+ } else {
+ keepCountForSmallestKnownToNotFit = keepCount;
+ widthForSmallestKnownToNotFit = width;
+ }
+ }
+
+ if (keepCountForLargestKnownToFit == 0) {
+ keepCountForLargestKnownToFit = 1;
+ }
+
+ if (keepCount != keepCountForLargestKnownToFit) {
+ keepCount = keepCountForLargestKnownToFit;
+ truncatedLength = truncateToBuffer(string, length, keepCount, stringBuffer);
+ }
+
+ return String(stringBuffer, truncatedLength);
+}
+
+String StringTruncator::centerTruncate(const String& string, float maxWidth, const Font& font, bool disableRoundingHacks)
+{
+ return truncateString(string, maxWidth, font, centerTruncateToBuffer, disableRoundingHacks);
+}
+
+String StringTruncator::rightTruncate(const String& string, float maxWidth, const Font& font, bool disableRoundingHacks)
+{
+ return truncateString(string, maxWidth, font, rightTruncateToBuffer, disableRoundingHacks);
+}
+
+float StringTruncator::width(const String& string, const Font& font, bool disableRoundingHacks)
+{
+ return stringWidth(font, string.characters(), string.length(), disableRoundingHacks);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/StringTruncator.h b/WebCore/platform/graphics/StringTruncator.h
new file mode 100644
index 0000000..0a8532b
--- /dev/null
+++ b/WebCore/platform/graphics/StringTruncator.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 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.
+ * 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.
+ */
+
+#ifndef StringTruncator_h
+#define StringTruncator_h
+
+namespace WebCore {
+
+ class Font;
+ class String;
+
+ class StringTruncator {
+ public:
+ static String centerTruncate(const String&, float maxWidth, const Font&, bool disableRoundingHacks = true);
+ static String rightTruncate(const String&, float maxWidth, const Font&, bool disableRoundingHacks = true);
+ static float width(const String&, const Font&, bool disableRoundingHacks = true);
+ };
+
+} // namespace WebCore
+
+#endif // !defined(StringTruncator_h)
diff --git a/WebCore/platform/graphics/cairo/AffineTransformCairo.cpp b/WebCore/platform/graphics/cairo/AffineTransformCairo.cpp
new file mode 100644
index 0000000..1080d2d
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/AffineTransformCairo.cpp
@@ -0,0 +1,281 @@
+/*
+ *
+ * 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 "AffineTransform.h"
+
+#include "IntRect.h"
+#include "FloatRect.h"
+
+#include <cairo.h>
+
+namespace WebCore {
+
+static const double deg2rad = 0.017453292519943295769; // pi/180
+
+AffineTransform::AffineTransform()
+{
+ cairo_matrix_init_identity(&m_transform);
+}
+
+AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+{
+ cairo_matrix_init(&m_transform, a, c, b, d, tx, ty);
+}
+
+AffineTransform::AffineTransform(const cairo_matrix_t &matrix)
+{
+ m_transform = matrix;
+}
+
+void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+{
+ cairo_matrix_init(&m_transform, a, c, b, d, tx, ty);
+}
+
+void AffineTransform::map(double x, double y, double* x2, double* y2) const
+{
+ *x2 = x;
+ *y2 = y;
+ cairo_matrix_transform_point(&m_transform, x2, y2);
+}
+
+IntRect AffineTransform::mapRect(const IntRect &rect) const
+{
+ FloatRect floatRect(rect);
+ FloatRect enclosingFloatRect = this->mapRect(floatRect);
+
+ return enclosingIntRect(enclosingFloatRect);
+}
+
+FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+{
+ double rectMinX = rect.x();
+ double rectMaxX = rect.x() + rect.width();
+ double rectMinY = rect.y();
+ double rectMaxY = rect.y() + rect.height();
+
+ double px = rectMinX;
+ double py = rectMinY;
+ cairo_matrix_transform_point(&m_transform, &px, &py);
+
+ double enclosingRectMinX = px;
+ double enclosingRectMinY = py;
+ double enclosingRectMaxX = px;
+ double enclosingRectMaxY = py;
+
+ px = rectMaxX;
+ py = rectMinY;
+ cairo_matrix_transform_point(&m_transform, &px, &py);
+ if (px < enclosingRectMinX)
+ enclosingRectMinX = px;
+ else if (px > enclosingRectMaxX)
+ enclosingRectMaxX = px;
+ if (py < enclosingRectMinY)
+ enclosingRectMinY = py;
+ else if (py > enclosingRectMaxY)
+ enclosingRectMaxY = py;
+
+ px = rectMaxX;
+ py = rectMaxY;
+ cairo_matrix_transform_point(&m_transform, &px, &py);
+ if (px < enclosingRectMinX)
+ enclosingRectMinX = px;
+ else if (px > enclosingRectMaxX)
+ enclosingRectMaxX = px;
+ if (py < enclosingRectMinY)
+ enclosingRectMinY = py;
+ else if (py > enclosingRectMaxY)
+ enclosingRectMaxY = py;
+
+ px = rectMinX;
+ py = rectMaxY;
+ cairo_matrix_transform_point(&m_transform, &px, &py);
+ if (px < enclosingRectMinX)
+ enclosingRectMinX = px;
+ else if (px > enclosingRectMaxX)
+ enclosingRectMaxX = px;
+ if (py < enclosingRectMinY)
+ enclosingRectMinY = py;
+ else if (py > enclosingRectMaxY)
+ enclosingRectMaxY = py;
+
+
+ double enclosingRectWidth = enclosingRectMaxX - enclosingRectMinX;
+ double enclosingRectHeight = enclosingRectMaxY - enclosingRectMinY;
+
+ return FloatRect(enclosingRectMinX, enclosingRectMinY, enclosingRectWidth, enclosingRectHeight);
+}
+
+bool AffineTransform::isIdentity() const
+{
+ return ((m_transform.xx == 1) && (m_transform.yy == 1)
+ && (m_transform.xy == 0) && (m_transform.yx == 0)
+ && (m_transform.x0 == 0) && (m_transform.y0 == 0));
+}
+
+double AffineTransform::a() const
+{
+ return m_transform.xx;
+}
+
+void AffineTransform::setA(double a)
+{
+ m_transform.xx = a;
+}
+
+double AffineTransform::b() const
+{
+ return m_transform.xy;
+}
+
+void AffineTransform::setB(double b)
+{
+ m_transform.xy = b;
+}
+
+double AffineTransform::c() const
+{
+ return m_transform.yx;
+}
+
+void AffineTransform::setC(double c)
+{
+ m_transform.yx = c;
+}
+
+double AffineTransform::d() const
+{
+ return m_transform.yy;
+}
+
+void AffineTransform::setD(double d)
+{
+ m_transform.yy = d;
+}
+
+double AffineTransform::e() const
+{
+ return m_transform.x0;
+}
+
+void AffineTransform::setE(double e)
+{
+ m_transform.x0 = e;
+}
+
+double AffineTransform::f() const
+{
+ return m_transform.y0;
+}
+
+void AffineTransform::setF(double f)
+{
+ m_transform.y0 = f;
+}
+
+void AffineTransform::reset()
+{
+ cairo_matrix_init_identity(&m_transform);
+}
+
+AffineTransform &AffineTransform::scale(double sx, double sy)
+{
+ cairo_matrix_scale(&m_transform, sx, sy);
+ return *this;
+}
+
+AffineTransform &AffineTransform::rotate(double d)
+{
+ cairo_matrix_rotate(&m_transform, d * deg2rad);
+ return *this;
+}
+
+AffineTransform &AffineTransform::translate(double tx, double ty)
+{
+ cairo_matrix_translate(&m_transform, tx, ty);
+ return *this;
+}
+
+AffineTransform &AffineTransform::shear(double sx, double sy)
+{
+ cairo_matrix_t shear;
+ cairo_matrix_init(&shear, 1, sy, sx, 1, 0, 0);
+
+ cairo_matrix_t result;
+ cairo_matrix_multiply(&result, &shear, &m_transform);
+ m_transform = result;
+
+ return *this;
+}
+
+double AffineTransform::det() const
+{
+ return m_transform.xx * m_transform.yy - m_transform.xy * m_transform.yx;
+}
+
+AffineTransform AffineTransform::inverse() const
+{
+ if (!isInvertible()) return AffineTransform();
+
+ cairo_matrix_t result = m_transform;
+ cairo_matrix_invert(&result);
+ return AffineTransform(result);
+}
+
+AffineTransform::operator cairo_matrix_t() const
+{
+ return m_transform;
+}
+
+bool AffineTransform::operator== (const AffineTransform &m2) const
+{
+ return ((m_transform.xx == m2.m_transform.xx)
+ && (m_transform.yy == m2.m_transform.yy)
+ && (m_transform.xy == m2.m_transform.xy)
+ && (m_transform.yx == m2.m_transform.yx)
+ && (m_transform.x0 == m2.m_transform.x0)
+ && (m_transform.y0 == m2.m_transform.y0));
+
+}
+
+AffineTransform &AffineTransform::operator*= (const AffineTransform &m2)
+{
+ cairo_matrix_t result;
+ cairo_matrix_multiply(&result, &m_transform, &m2.m_transform);
+ m_transform = result;
+
+ return *this;
+}
+
+AffineTransform AffineTransform::operator* (const AffineTransform &m2)
+{
+ cairo_matrix_t result;
+ cairo_matrix_multiply(&result, &m_transform, &m2.m_transform);
+ return result;
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/cairo/CairoPath.h b/WebCore/platform/graphics/cairo/CairoPath.h
new file mode 100644
index 0000000..b761ce6
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/CairoPath.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef CairoPath_h
+#define CairoPath_h
+
+#include <cairo.h>
+
+namespace WebCore {
+
+ // This is necessary since cairo_path_fixed_t isn't exposed in Cairo's public API.
+ struct CairoPath {
+ cairo_t* m_cr;
+
+ CairoPath()
+ {
+ static cairo_surface_t* pathSurface = cairo_image_surface_create(CAIRO_FORMAT_A8, 1, 1);
+ m_cr = cairo_create(pathSurface);
+ }
+
+ ~CairoPath()
+ {
+ cairo_destroy(m_cr);
+ }
+ };
+
+} // namespace WebCore
+
+#endif // CairoPath_h
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
new file mode 100644
index 0000000..06e926f
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.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 "Font.h"
+
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs, const FloatPoint& point) const
+{
+ cairo_t* cr = graphicsContext->platformContext();
+ cairo_save(cr);
+
+ // Set the text color to use for drawing.
+ float red, green, blue, alpha;
+ Color penColor = graphicsContext->fillColor();
+ penColor.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(cr, red, green, blue, alpha);
+
+ font->setFont(cr);
+
+ GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
+
+ float offset = point.x();
+
+ for (int i = 0; i < numGlyphs; i++) {
+ glyphs[i].x = offset;
+ glyphs[i].y = point.y();
+ offset += glyphBuffer.advanceAt(from + i);
+ }
+ cairo_show_glyphs(cr, glyphs, numGlyphs);
+
+ cairo_restore(cr);
+}
+
+}
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
new file mode 100644
index 0000000..90e34e9
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -0,0 +1,930 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.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 "GraphicsContext.h"
+
+#if PLATFORM(CAIRO)
+
+#include "AffineTransform.h"
+#include "CairoPath.h"
+#include "FloatRect.h"
+#include "Font.h"
+#include "ImageBuffer.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "Path.h"
+#include "SimpleFontData.h"
+#include <cairo.h>
+#include <math.h>
+#include <stdio.h>
+#include <wtf/MathExtras.h>
+
+#if PLATFORM(GTK)
+#include <gdk/gdk.h>
+#include <pango/pango.h>
+#elif PLATFORM(WIN)
+#include <cairo-win32.h>
+#endif
+#include "GraphicsContextPlatformPrivateCairo.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace WebCore {
+
+static inline void setColor(cairo_t* cr, const Color& col)
+{
+ float red, green, blue, alpha;
+ col.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(cr, red, green, blue, alpha);
+}
+
+// A fillRect helper
+static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col)
+{
+ setColor(cr, col);
+ cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+ cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+ cairo_fill(cr);
+}
+
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate)
+{
+ m_data->cr = cairo_reference(cr);
+ setPaintingDisabled(!cr);
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ destroyGraphicsContextPrivate(m_common);
+ delete m_data;
+}
+
+AffineTransform GraphicsContext::getCTM() const
+{
+ cairo_t* cr = platformContext();
+ cairo_matrix_t m;
+ cairo_get_matrix(cr, &m);
+ return m;
+}
+
+cairo_t* GraphicsContext::platformContext() const
+{
+ return m_data->cr;
+}
+
+void GraphicsContext::savePlatformState()
+{
+ cairo_save(m_data->cr);
+ m_data->save();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ cairo_restore(m_data->cr);
+ m_data->restore();
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+
+ if (fillColor().alpha())
+ fillRectSourceOver(cr, rect, fillColor());
+
+ if (strokeStyle() != NoStroke) {
+ setColor(cr, strokeColor());
+ FloatRect r(rect);
+ r.inflate(-.5f);
+ cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
+ cairo_set_line_width(cr, 1.0);
+ cairo_stroke(cr);
+ }
+
+ 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)
+{
+ if (paintingDisabled())
+ return;
+
+ StrokeStyle style = strokeStyle();
+ if (style == NoStroke)
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+
+ float width = strokeThickness();
+ if (width < 1)
+ width = 1;
+
+ FloatPoint p1 = point1;
+ FloatPoint p2 = point2;
+ bool isVerticalLine = (p1.x() == p2.x());
+
+ adjustLineToPixelBoundaries(p1, p2, width, style);
+ cairo_set_line_width(cr, width);
+
+ int patWidth = 0;
+ switch (style) {
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = static_cast<int>(width);
+ break;
+ case DashedStroke:
+ patWidth = 3*static_cast<int>(width);
+ break;
+ }
+
+ setColor(cr, strokeColor());
+
+ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
+
+ if (patWidth) {
+ // 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.
+ if (isVerticalLine) {
+ fillRectSourceOver(cr, FloatRect(p1.x() - width/2, p1.y() - width, width, width), strokeColor());
+ fillRectSourceOver(cr, FloatRect(p2.x() - width/2, p2.y(), width, width), strokeColor());
+ } else {
+ fillRectSourceOver(cr, FloatRect(p1.x() - width, p1.y() - width/2, width, width), strokeColor());
+ fillRectSourceOver(cr, FloatRect(p2.x(), p2.y() - width/2, width, width), strokeColor());
+ }
+
+ // Example: 80 pixels with a width of 30 pixels.
+ // Remainder is 20. The maximum pixels of line we could paint
+ // will be 50 pixels.
+ int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*static_cast<int>(width);
+ int remainder = distance%patWidth;
+ int coverage = distance-remainder;
+ int numSegments = coverage/patWidth;
+
+ float patternOffset = 0;
+ // Special case 1px dotted borders for speed.
+ if (patWidth == 1)
+ patternOffset = 1.0;
+ else {
+ bool evenNumberOfSegments = numSegments%2 == 0;
+ if (remainder)
+ evenNumberOfSegments = !evenNumberOfSegments;
+ if (evenNumberOfSegments) {
+ if (remainder) {
+ patternOffset += patWidth - remainder;
+ patternOffset += remainder/2;
+ }
+ else
+ patternOffset = patWidth/2;
+ }
+ else if (!evenNumberOfSegments) {
+ if (remainder)
+ patternOffset = (patWidth - remainder)/2;
+ }
+ }
+
+ double dash = patWidth;
+ cairo_set_dash(cr, &dash, 1, patternOffset);
+ }
+
+ cairo_move_to(cr, p1.x(), p1.y());
+ cairo_line_to(cr, p2.x(), p2.y());
+
+ cairo_stroke(cr);
+ cairo_restore(cr);
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+ float yRadius = .5 * rect.height();
+ float xRadius = .5 * rect.width();
+ cairo_translate(cr, rect.x() + xRadius, rect.y() + yRadius);
+ cairo_scale(cr, xRadius, yRadius);
+ cairo_arc(cr, 0., 0., 1., 0., 2 * M_PI);
+ cairo_restore(cr);
+
+ if (fillColor().alpha()) {
+ setColor(cr, fillColor());
+ cairo_fill_preserve(cr);
+ }
+
+ if (strokeStyle() != NoStroke) {
+ setColor(cr, strokeColor());
+ cairo_set_line_width(cr, strokeThickness());
+ cairo_stroke(cr);
+ }
+
+ cairo_new_path(cr);
+}
+
+// FIXME: This function needs to be adjusted to match the functionality on the Mac side.
+void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
+{
+ if (paintingDisabled())
+ return;
+
+ if (strokeStyle() == NoStroke)
+ return;
+
+ int x = rect.x();
+ int y = rect.y();
+ float w = rect.width();
+#if 0 // FIXME: unused so far
+ float h = rect.height();
+ float scaleFactor = h / w;
+ float reverseScaleFactor = w / h;
+#endif
+ float r = w / 2;
+ float fa = startAngle;
+ float falen = fa + angleSpan;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+ cairo_arc_negative(cr, x + r, y + r, r, -fa * M_PI/180, -falen * M_PI/180);
+ setColor(cr, strokeColor());
+ cairo_set_line_width(cr, strokeThickness());
+ cairo_stroke(cr);
+ cairo_restore(cr);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ if (npoints <= 1)
+ return;
+
+ cairo_t* cr = m_data->cr;
+
+ cairo_save(cr);
+ cairo_set_antialias(cr, shouldAntialias ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
+ cairo_move_to(cr, points[0].x(), points[0].y());
+ for (size_t i = 1; i < npoints; i++)
+ cairo_line_to(cr, points[i].x(), points[i].y());
+ cairo_close_path(cr);
+
+ if (fillColor().alpha()) {
+ setColor(cr, fillColor());
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_fill_preserve(cr);
+ }
+
+ if (strokeStyle() != NoStroke) {
+ setColor(cr, strokeColor());
+ cairo_set_line_width(cr, strokeThickness());
+ cairo_stroke(cr);
+ }
+
+ cairo_new_path(cr);
+ cairo_restore(cr);
+}
+
+void GraphicsContext::fillRect(const IntRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ if (color.alpha())
+ fillRectSourceOver(m_data->cr, rect, color);
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ if (color.alpha())
+ fillRectSourceOver(m_data->cr, rect, color);
+}
+
+void GraphicsContext::clip(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
+ cairo_clip(cr);
+ cairo_set_fill_rule(cr, savedFillRule);
+ m_data->clip(rect);
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ int radius = (focusRingWidth() - 1) / 2;
+ int offset = radius + focusRingOffset();
+
+ const Vector<IntRect>& rects = focusRingRects();
+ unsigned rectCount = rects.size();
+ IntRect finalFocusRect;
+ for (unsigned i = 0; i < rectCount; i++) {
+ IntRect focusRect = rects[i];
+ focusRect.inflate(offset);
+ finalFocusRect.unite(focusRect);
+ }
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+ // FIXME: These rects should be rounded
+ cairo_rectangle(cr, finalFocusRect.x(), finalFocusRect.y(), finalFocusRect.width(), finalFocusRect.height());
+
+ // Force the alpha to 50%. This matches what the Mac does with outline rings.
+ Color ringColor(color.red(), color.green(), color.blue(), 127);
+ setColor(cr, ringColor);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+}
+
+void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
+{
+ if (paintingDisabled())
+ return;
+
+ // This is a workaround for http://bugs.webkit.org/show_bug.cgi?id=15659
+ StrokeStyle savedStrokeStyle = strokeStyle();
+ setStrokeStyle(SolidStroke);
+
+ IntPoint endPoint = origin + IntSize(width, 0);
+ drawLine(origin, endPoint);
+
+ setStrokeStyle(savedStrokeStyle);
+}
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+
+ // Convention is green for grammar, red for spelling
+ // These need to become configurable
+ if (grammar)
+ cairo_set_source_rgb(cr, 0, 1, 0);
+ else
+ cairo_set_source_rgb(cr, 1, 0, 0);
+
+#if PLATFORM(GTK)
+ // We ignore most of the provided constants in favour of the platform style
+ pango_cairo_show_error_underline(cr, origin.x(), origin.y(), width, cMisspellingLineThickness);
+#else
+ notImplemented();
+#endif
+
+ cairo_restore(cr);
+}
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
+{
+ FloatRect result;
+ double x = frect.x();
+ double y = frect.y();
+ cairo_t* cr = m_data->cr;
+ cairo_user_to_device(cr, &x, &y);
+ x = round(x);
+ y = round(y);
+ cairo_device_to_user(cr, &x, &y);
+ result.setX(static_cast<float>(x));
+ result.setY(static_cast<float>(y));
+ x = frect.width();
+ y = frect.height();
+ cairo_user_to_device_distance(cr, &x, &y);
+ x = round(x);
+ y = round(y);
+ cairo_device_to_user_distance(cr, &x, &y);
+ result.setWidth(static_cast<float>(x));
+ result.setHeight(static_cast<float>(y));
+ return result;
+}
+
+void GraphicsContext::translate(float x, float y)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_translate(cr, x, y);
+ m_data->translate(x, y);
+}
+
+IntPoint GraphicsContext::origin()
+{
+ cairo_matrix_t matrix;
+ cairo_t* cr = m_data->cr;
+ cairo_get_matrix(cr, &matrix);
+ return IntPoint(static_cast<int>(matrix.x0), static_cast<int>(matrix.y0));
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& col)
+{
+ // FIXME: this is probably a no-op but I'm not sure
+ // notImplemented(); // commented-out because it's chatty and clutters output
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& col)
+{
+ // FIXME: this is probably a no-op but I'm not sure
+ //notImplemented(); // commented-out because it's chatty and clutters output
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float strokeThickness)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_set_line_width(m_data->cr, strokeThickness);
+}
+
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
+{
+ static double dashPattern[] = {5.0, 5.0};
+ static double dotPattern[] = {1.0, 1.0};
+
+ if (paintingDisabled())
+ return;
+
+ switch (strokeStyle) {
+ case NoStroke:
+ // FIXME: is it the right way to emulate NoStroke?
+ cairo_set_line_width(m_data->cr, 0);
+ break;
+ case SolidStroke:
+ cairo_set_dash(m_data->cr, 0, 0, 0);
+ break;
+ case DottedStroke:
+ cairo_set_dash(m_data->cr, dotPattern, 2, 0);
+ break;
+ case DashedStroke:
+ cairo_set_dash(m_data->cr, dashPattern, 2, 0);
+ break;
+ default:
+ notImplemented();
+ break;
+ }
+}
+
+void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+{
+ notImplemented();
+}
+
+void GraphicsContext::concatCTM(const AffineTransform& transform)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ const cairo_matrix_t* matrix = reinterpret_cast<const cairo_matrix_t*>(&transform);
+ cairo_transform(cr, matrix);
+ m_data->concatCTM(transform);
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ clip(rect);
+
+ Path p;
+ FloatRect r(rect);
+ // Add outer ellipse
+ p.addEllipse(r);
+ // Add inner ellipse
+ r.inflate(-thickness);
+ p.addEllipse(r);
+ addPath(p);
+
+ cairo_t* cr = m_data->cr;
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_clip(cr);
+ cairo_set_fill_rule(cr, savedFillRule);
+}
+
+
+void GraphicsContext::setShadow(IntSize const&, int, Color const&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clearShadow()
+{
+ notImplemented();
+}
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_push_group(cr);
+ m_data->layers.append(opacity);
+ m_data->beginTransparencyLayer();
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+
+ cairo_pop_group_to_source(cr);
+ cairo_paint_with_alpha(cr, m_data->layers.last());
+ m_data->layers.removeLast();
+ m_data->endTransparencyLayer();
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+
+ cairo_save(cr);
+ cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+ cairo_fill(cr);
+ cairo_restore(cr);
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect, float width)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+ cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+ setColor(cr, strokeColor());
+ cairo_set_line_width(cr, width);
+ cairo_stroke(cr);
+ cairo_restore(cr);
+}
+
+void GraphicsContext::setLineCap(LineCap lineCap)
+{
+ if (paintingDisabled())
+ return;
+
+ 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;
+ }
+ cairo_set_line_cap(m_data->cr, cairoCap);
+}
+
+void GraphicsContext::setLineJoin(LineJoin lineJoin)
+{
+ if (paintingDisabled())
+ return;
+
+ 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;
+ }
+ cairo_set_line_join(m_data->cr, cairoJoin);
+}
+
+void GraphicsContext::setMiterLimit(float miter)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_set_miter_limit(m_data->cr, miter);
+}
+
+void GraphicsContext::setAlpha(float)
+{
+ notImplemented();
+}
+
+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;
+ }
+}
+
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_set_operator(m_data->cr, toCairoOperator(op));
+}
+
+void GraphicsContext::beginPath()
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_new_path(cr);
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
+ cairo_append_path(cr, p);
+ cairo_path_destroy(p);
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_path_t* p = cairo_copy_path(path.platformPath()->m_cr);
+ cairo_append_path(cr, p);
+ cairo_path_destroy(p);
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
+ cairo_clip(cr);
+ cairo_set_fill_rule(cr, savedFillRule);
+ m_data->clip(path);
+}
+
+void GraphicsContext::clipOut(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ double x1, y1, x2, y2;
+ cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
+ cairo_rectangle(cr, x1, y1, x2 - x1, y2 - y1);
+ addPath(path);
+
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_clip(cr);
+ cairo_set_fill_rule(cr, savedFillRule);
+}
+
+void GraphicsContext::rotate(float radians)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_rotate(m_data->cr, radians);
+ m_data->rotate(radians);
+}
+
+void GraphicsContext::scale(const FloatSize& size)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_scale(m_data->cr, size.width(), size.height());
+ m_data->scale(size);
+}
+
+void GraphicsContext::clipOut(const IntRect& r)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ double x1, y1, x2, y2;
+ cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
+ cairo_rectangle(cr, x1, x2, x2 - x1, y2 - y1);
+ cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
+ cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
+ cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_clip(cr);
+ cairo_set_fill_rule(cr, savedFillRule);
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& r)
+{
+ if (paintingDisabled())
+ return;
+
+ Path p;
+ p.addEllipse(r);
+ clipOut(p);
+}
+
+void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+ beginPath();
+ addPath(Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight));
+ setColor(cr, color);
+ cairo_fill(cr);
+ cairo_restore(cr);
+}
+
+#if PLATFORM(GTK)
+void GraphicsContext::setGdkExposeEvent(GdkEventExpose* expose)
+{
+ m_data->expose = expose;
+}
+
+GdkEventExpose* GraphicsContext::gdkExposeEvent() const
+{
+ return m_data->expose;
+}
+
+GdkDrawable* GraphicsContext::gdkDrawable() const
+{
+ if (!m_data->expose)
+ return 0;
+
+ return GDK_DRAWABLE(m_data->expose->window);
+}
+
+IntPoint GraphicsContext::translatePoint(const IntPoint& point) const
+{
+ cairo_matrix_t tm;
+ cairo_get_matrix(m_data->cr, &tm);
+ double x = point.x();
+ double y = point.y();
+
+ cairo_matrix_transform_point(&tm, &x, &y);
+ return IntPoint(x, y);
+}
+#endif
+
+void GraphicsContext::setUseAntialiasing(bool enable)
+{
+ if (paintingDisabled())
+ return;
+
+ // When true, use the default Cairo backend antialias mode (usually this
+ // enables standard 'grayscale' antialiasing); false to explicitly disable
+ // antialiasing. This is the same strategy as used in drawConvexPolygon().
+ cairo_set_antialias(m_data->cr, enable ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE);
+}
+
+void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
+{
+ if (paintingDisabled())
+ return;
+ cairo_surface_t* image = buffer->surface();
+ if (!image)
+ return;
+ cairo_surface_flush(image);
+ cairo_surface_reference(image);
+ cairo_t* cr = platformContext();
+ cairo_save(cr);
+ cairo_translate(cr, r.x(), r.y());
+ cairo_set_source_surface(cr, image, 0, 0);
+ cairo_surface_destroy(image);
+ cairo_rectangle(cr, 0, 0, r.width(), r.height());
+ cairo_fill(cr);
+ cairo_restore(cr);
+}
+
+void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& dstRect)
+{
+ cairo_surface_flush(buffer->surface());
+ cairo_save(platformContext());
+ cairo_set_source_surface(platformContext(), buffer->surface(), srcRect.x(), srcRect.y());
+ cairo_rectangle(platformContext(), dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height());
+ cairo_fill(platformContext());
+ cairo_restore(platformContext());
+}
+
+} // namespace WebCore
+
+#endif // PLATFORM(CAIRO)
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
new file mode 100644
index 0000000..26db336
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Brent Fulgham <bfulgham@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 "GraphicsContext.h"
+
+#include <cairo.h>
+#include <math.h>
+#include <stdio.h>
+#include <wtf/MathExtras.h>
+
+#if PLATFORM(GTK)
+#include <gdk/gdk.h>
+#include <pango/pango.h>
+#elif PLATFORM(WIN)
+#include <cairo-win32.h>
+#endif
+
+namespace WebCore {
+
+class GraphicsContextPlatformPrivate {
+public:
+ GraphicsContextPlatformPrivate()
+ : cr(0)
+#if PLATFORM(GTK)
+ , expose(0)
+#elif PLATFORM(WIN)
+ // NOTE: These may note be needed: review and remove once Cairo implementation is complete
+ , m_hdc(0)
+ , m_transparencyCount(0)
+#endif
+ {
+ }
+
+ ~GraphicsContextPlatformPrivate()
+ {
+ cairo_destroy(cr);
+ }
+
+#if PLATFORM(WIN)
+ // On Windows, we need to update the HDC for form controls to draw in the right place.
+ void save();
+ void restore();
+ void clip(const IntRect&);
+ void clip(const Path&);
+ void scale(const FloatSize&);
+ void rotate(float);
+ void translate(float, float);
+ void concatCTM(const AffineTransform&);
+ void beginTransparencyLayer() { m_transparencyCount++; }
+ void endTransparencyLayer() { m_transparencyCount--; }
+#else
+ // On everything else, we do nothing.
+ void save() {}
+ void restore() {}
+ void clip(const IntRect&) {}
+ void clip(const Path&) {}
+ void scale(const FloatSize&) {}
+ void rotate(float) {}
+ void translate(float, float) {}
+ void concatCTM(const AffineTransform&) {}
+ void beginTransparencyLayer() {}
+ void endTransparencyLayer() {}
+#endif
+
+ cairo_t* cr;
+ Vector<float> layers;
+
+#if PLATFORM(GTK)
+ GdkEventExpose* expose;
+#elif PLATFORM(WIN)
+ HDC m_hdc;
+ unsigned m_transparencyCount;
+#endif
+};
+
+} // namespace WebCore
+
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
new file mode 100644
index 0000000..392e9df
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Holger Hans Peter Freyther <zecke@selfish.org>
+ *
+ * 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"
+
+#include <cairo.h>
+
+using namespace std;
+
+namespace WebCore {
+
+auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool)
+{
+ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ size.width(), size.height());
+ if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
+ return auto_ptr<ImageBuffer>();
+
+ return auto_ptr<ImageBuffer>(new ImageBuffer(surface));
+}
+
+ImageBuffer::ImageBuffer(_cairo_surface* surface)
+ : m_surface(surface)
+{
+ cairo_t* cr = cairo_create(m_surface);
+ m_context.set(new GraphicsContext(cr));
+
+ /*
+ * The context is now owned by the GraphicsContext
+ */
+ cairo_destroy(cr);
+}
+
+ImageBuffer::~ImageBuffer()
+{
+ cairo_surface_destroy(m_surface);
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ return m_context.get();
+}
+
+cairo_surface_t* ImageBuffer::surface() const
+{
+ return m_surface;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&)
+{
+ notImplemented();
+}
+
+}
diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp
new file mode 100644
index 0000000..4faa512
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.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 "BitmapImage.h"
+
+#if PLATFORM(CAIRO)
+
+#include "AffineTransform.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "ImageObserver.h"
+#include <cairo.h>
+#include <math.h>
+
+namespace WebCore {
+
+void FrameData::clear()
+{
+ if (m_frame) {
+ cairo_surface_destroy(m_frame);
+ m_frame = 0;
+ m_duration = 0.;
+ m_hasAlpha = true;
+ }
+}
+
+void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+{
+ if (!m_source.initialized())
+ return;
+
+ FloatRect srcRect(src);
+ FloatRect dstRect(dst);
+
+ cairo_surface_t* image = frameAtIndex(m_currentFrame);
+ if (!image) // If it's too early we won't have an image yet.
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(context, dstRect, solidColor(), op);
+ return;
+ }
+
+ IntSize selfSize = size();
+
+ cairo_t* cr = context->platformContext();
+ cairo_save(cr);
+
+ // Set the compositing operation.
+ if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame))
+ context->setCompositeOperation(CompositeCopy);
+ else
+ context->setCompositeOperation(op);
+
+ // If we're drawing a sub portion of the image or scaling then create
+ // a pattern transformation on the image and draw the transformed pattern.
+ // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
+
+ // To avoid the unwanted gradient effect (#14017) we use
+ // CAIRO_FILTER_NEAREST now, but the real fix will be to have
+ // CAIRO_EXTEND_PAD implemented for surfaces in Cairo allowing us to still
+ // use bilinear filtering
+ cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+
+ float scaleX = srcRect.width() / dstRect.width();
+ float scaleY = srcRect.height() / dstRect.height();
+ cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() };
+ cairo_pattern_set_matrix(pattern, &matrix);
+
+ // Draw the image.
+ cairo_translate(cr, dstRect.x(), dstRect.y());
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, 0, 0, dstRect.width(), dstRect.height());
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+
+ startAnimation();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ cairo_surface_t* image = nativeImageForCurrentFrame();
+ if (!image) // If it's too early we won't have an image yet.
+ return;
+
+ cairo_t* cr = context->platformContext();
+ context->save();
+
+ // TODO: Make use of tileRect.
+
+ cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image);
+ cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+
+ // Workaround to avoid the unwanted gradient effect (#14017)
+ cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
+
+ cairo_matrix_t pattern_matrix = cairo_matrix_t(patternTransform);
+ cairo_matrix_t phase_matrix = {1, 0, 0, 1, phase.x(), phase.y()};
+ cairo_matrix_t combined;
+ cairo_matrix_multiply(&combined, &pattern_matrix, &phase_matrix);
+ cairo_matrix_invert(&combined);
+ cairo_pattern_set_matrix(pattern, &combined);
+
+ context->setCompositeOperation(op);
+ cairo_set_source(cr, pattern);
+ cairo_pattern_destroy(pattern);
+ cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height());
+ cairo_fill(cr);
+
+ context->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+void BitmapImage::checkForSolidColor()
+{
+ // FIXME: It's easy to implement this optimization. Just need to check the RGBA32 buffer to see if it is 1x1.
+ m_isSolidColor = false;
+}
+
+}
+
+#endif // PLATFORM(CAIRO)
diff --git a/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp b/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
new file mode 100644
index 0000000..66e39ba
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+ *
+ * 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"
+
+#if PLATFORM(CAIRO)
+
+#include "BMPImageDecoder.h"
+#include "GIFImageDecoder.h"
+#include "ICOImageDecoder.h"
+#include "JPEGImageDecoder.h"
+#include "PNGImageDecoder.h"
+#include "SharedBuffer.h"
+#include <cairo.h>
+
+#if !PLATFORM(WIN)
+#include "XBMImageDecoder.h"
+#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();
+
+#if !PLATFORM(WIN)
+ // XBMs require 8 bytes of info.
+ if (length >= 8 && strncmp(contents, "#define ", 8) == 0)
+ return new XBMImageDecoder();
+#endif
+
+ // Give up. We don't know what the heck this is.
+ return 0;
+}
+
+ImageSource::ImageSource()
+ : m_decoder(0)
+{
+}
+
+ImageSource::~ImageSource()
+{
+ clear();
+}
+
+void ImageSource::clear()
+{
+ delete m_decoder;
+ m_decoder = 0;
+}
+
+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());
+
+ 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();
+}
+
+int ImageSource::repetitionCount()
+{
+ if (!m_decoder)
+ return cAnimationNone;
+
+ return m_decoder->repetitionCount();
+}
+
+size_t ImageSource::frameCount() const
+{
+ return m_decoder ? m_decoder->frameCount() : 0;
+}
+
+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;
+
+ // Cairo does not like zero height images.
+ // If we have a zero height image, just pretend we don't have enough data yet.
+ if (!buffer->height())
+ return 0;
+
+ return cairo_image_surface_create_for_data((unsigned char*)buffer->bytes().data(),
+ CAIRO_FORMAT_ARGB32,
+ size().width(),
+ buffer->height(),
+ size().width()*4);
+}
+
+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)
+{
+ // 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();
+}
+
+}
+
+#endif // PLATFORM(CAIRO)
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
new file mode 100644
index 0000000..8d17567
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -0,0 +1,280 @@
+/*
+ Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
+ Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <wildfox@kde.org>
+ 2004, 2005, 2006 Rob Buis <buis@kde.org>
+ 2005, 2007 Apple Inc. All Rights reserved.
+ 2007 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
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "Path.h"
+
+#include "AffineTransform.h"
+#include "CairoPath.h"
+#include "FloatRect.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+#include <cairo.h>
+#include <math.h>
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(new CairoPath())
+{
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path::Path(const Path& other)
+ : m_path(new CairoPath())
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_path_t* p = cairo_copy_path(other.platformPath()->m_cr);
+ cairo_append_path(cr, p);
+ cairo_path_destroy(p);
+}
+
+Path& Path::operator=(const Path& other)
+{
+ if (&other == this)
+ return *this;
+
+ clear();
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_path_t* p = cairo_copy_path(other.platformPath()->m_cr);
+ cairo_append_path(cr, p);
+ cairo_path_destroy(p);
+ return *this;
+}
+
+void Path::clear()
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_new_path(cr);
+}
+
+bool Path::isEmpty() const
+{
+ cairo_t* cr = platformPath()->m_cr;
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,10)
+ return !cairo_has_current_point(cr);
+#else
+ cairo_path_t* p = cairo_copy_path(cr);
+ bool hasData = p->num_data;
+ cairo_path_destroy(p);
+ return !hasData;
+#endif
+}
+
+void Path::translate(const FloatSize& p)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_translate(cr, p.width(), p.height());
+}
+
+void Path::moveTo(const FloatPoint& p)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_move_to(cr, p.x(), p.y());
+}
+
+void Path::addLineTo(const FloatPoint& p)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_line_to(cr, p.x(), p.y());
+}
+
+void Path::addRect(const FloatRect& rect)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+/*
+ * inspired by libsvg-cairo
+ */
+void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& point)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ double x, y;
+ double x1 = controlPoint.x();
+ double y1 = controlPoint.y();
+ double x2 = point.x();
+ double y2 = point.y();
+ cairo_get_current_point(cr, &x, &y);
+ cairo_curve_to(cr,
+ x + 2.0 / 3.0 * (x1 - x), y + 2.0 / 3.0 * (y1 - y),
+ x2 + 2.0 / 3.0 * (x1 - x2), y2 + 2.0 / 3.0 * (y1 - y2),
+ x2, y2);
+}
+
+void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& controlPoint3)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_curve_to(cr, controlPoint1.x(), controlPoint1.y(),
+ controlPoint2.x(), controlPoint2.y(),
+ controlPoint3.x(), controlPoint3.y());
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool anticlockwise)
+{
+ // http://bugs.webkit.org/show_bug.cgi?id=16449
+ // cairo_arc() functions hang or crash when passed inf as radius or start/end angle
+ if (!isfinite(r) || !isfinite(sa) || !isfinite(ea))
+ return;
+
+ cairo_t* cr = platformPath()->m_cr;
+ if (anticlockwise)
+ cairo_arc_negative(cr, p.x(), p.y(), r, sa, ea);
+ else
+ cairo_arc(cr, p.x(), p.y(), r, sa, ea);
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ // FIXME: cairo_arc_to not yet in cairo see cairo.h
+ // cairo_arc_to(m_cr, p1.x(), p1.y(), p2.x(), p2.y());
+ notImplemented();
+}
+
+void Path::addEllipse(const FloatRect& rect)
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_save(cr);
+ float yRadius = .5 * rect.height();
+ float xRadius = .5 * rect.width();
+ cairo_translate(cr, rect.x() + xRadius, rect.y() + yRadius);
+ cairo_scale(cr, xRadius, yRadius);
+ cairo_arc(cr, 0., 0., 1., 0., 2 * piDouble);
+ cairo_restore(cr);
+}
+
+void Path::closeSubpath()
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_close_path(cr);
+}
+
+FloatRect Path::boundingRect() const
+{
+ cairo_t* cr = platformPath()->m_cr;
+ double x0, x1, y0, y1;
+ cairo_fill_extents(cr, &x0, &y0, &x1, &y1);
+ return FloatRect(x0, y0, x1 - x0, y1 - y0);
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ if (!boundingRect().contains(point))
+ return false;
+
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_fill_rule_t cur = cairo_get_fill_rule(cr);
+ cairo_set_fill_rule(cr, rule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
+ bool contains = cairo_in_fill(cr, point.x(), point.y());
+ cairo_set_fill_rule(cr, cur);
+ return contains;
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ cairo_t* cr = platformPath()->m_cr;
+ cairo_path_t* path = cairo_copy_path(cr);
+ cairo_path_data_t* data;
+ PathElement pelement;
+ FloatPoint points[3];
+ pelement.points = points;
+
+ for (int i = 0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ pelement.type = PathElementMoveToPoint;
+ pelement.points[0] = FloatPoint(data[1].point.x,data[1].point.y);
+ function(info, &pelement);
+ break;
+ case CAIRO_PATH_LINE_TO:
+ pelement.type = PathElementAddLineToPoint;
+ pelement.points[0] = FloatPoint(data[1].point.x,data[1].point.y);
+ function(info, &pelement);
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ pelement.type = PathElementAddCurveToPoint;
+ pelement.points[0] = FloatPoint(data[1].point.x,data[1].point.y);
+ pelement.points[1] = FloatPoint(data[2].point.x,data[2].point.y);
+ pelement.points[2] = FloatPoint(data[3].point.x,data[3].point.y);
+ function(info, &pelement);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ pelement.type = PathElementCloseSubpath;
+ function(info, &pelement);
+ break;
+ }
+ }
+ cairo_path_destroy(path);
+}
+
+void Path::transform(const AffineTransform& trans)
+{
+ cairo_t* m_cr = platformPath()->m_cr;
+ cairo_matrix_t c_matrix = cairo_matrix_t(trans);
+ cairo_transform(m_cr, &c_matrix);
+}
+
+String Path::debugString() const
+{
+ String string = "";
+ cairo_path_t* path = cairo_copy_path(platformPath()->m_cr);
+ cairo_path_data_t* data;
+
+ if (!path->num_data )
+ string = "EMPTY";
+
+ for (int i = 0; i < path->num_data; i += path->data[i].header.length) {
+ data = &path->data[i];
+ switch (data->header.type) {
+ case CAIRO_PATH_MOVE_TO:
+ string += String::format("M %.2f,%.2f",
+ data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_LINE_TO:
+ string += String::format("L %.2f,%.2f",
+ data[1].point.x, data[1].point.y);
+ break;
+ case CAIRO_PATH_CURVE_TO:
+ string += String::format("C %.2f,%.2f,%.2f,%.2f,%.2f,%.2f",
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
+ break;
+ case CAIRO_PATH_CLOSE_PATH:
+ string += "X";
+ break;
+ }
+ }
+ cairo_path_destroy(path);
+ return string;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/cairo/rgb24-hacks.txt b/WebCore/platform/graphics/cairo/rgb24-hacks.txt
new file mode 100644
index 0000000..59f8070
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/rgb24-hacks.txt
@@ -0,0 +1,32 @@
+Index: cairo/src/cairo-win32-surface.c
+===================================================================
+--- cairo/src/cairo-win32-surface.c (revision 14498)
++++ cairo/src/cairo-win32-surface.c (working copy)
+@@ -824,8 +824,13 @@
+ * to figure out when we can use GDI. We don't have that checking
+ * anywhere at the moment, so just bail and use the fallback
+ * paths. */
+- if (surface->format != CAIRO_FORMAT_RGB24)
+- return CAIRO_INT_STATUS_UNSUPPORTED;
++ //if (surface->format != CAIRO_FORMAT_RGB24)
++ // return CAIRO_INT_STATUS_UNSUPPORTED;
++ // FIXME: We'll go ahead and optimize this now and just assume we're ok if
++ // the color has no alpha. Probably need to check various composite operators to
++ // get this exactly right.
++ if (color->alpha != 1.0)
++ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
+ * surfaces with alpha.)
+@@ -1016,8 +1021,9 @@
+
+ /* We can only handle operator SOURCE or OVER with the destination
+ * having no alpha */
+- if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
+- (dst->format != CAIRO_FORMAT_RGB24))
++ if ((op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER))
++ // FIXME: It's not clear why ExtTextOut can't be called when the
++ // destination has alpha. Remove the RGB24 restriction. || (dst->format != CAIRO_FORMAT_RGB24))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* If we have a fallback mask clip set on the dst, we have
diff --git a/WebCore/platform/graphics/cairo/scale-removal.txt b/WebCore/platform/graphics/cairo/scale-removal.txt
new file mode 100644
index 0000000..47c0d70
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/scale-removal.txt
@@ -0,0 +1,13 @@
+Index: cairo/src/cairo-win32-private.h
+===================================================================
+--- cairo/src/cairo-win32-private.h (revision 14582)
++++ cairo/src/cairo-win32-private.h (working copy)
+@@ -39,7 +39,7 @@
+ #include <cairo-win32.h>
+ #include <cairoint.h>
+
+-#define WIN32_FONT_LOGICAL_SCALE 32
++#define WIN32_FONT_LOGICAL_SCALE 1
+
+ typedef struct _cairo_win32_surface {
+ cairo_surface_t base;
diff --git a/WebCore/platform/graphics/cg/AffineTransformCG.cpp b/WebCore/platform/graphics/cg/AffineTransformCG.cpp
new file mode 100644
index 0000000..8fdd1e6
--- /dev/null
+++ b/WebCore/platform/graphics/cg/AffineTransformCG.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 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"
+#include "AffineTransform.h"
+
+#if PLATFORM(CG)
+
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "IntRect.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+AffineTransform::AffineTransform()
+{
+ m_transform = CGAffineTransformIdentity;
+}
+
+AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+{
+ m_transform = CGAffineTransformMake(narrowPrecisionToCGFloat(a),
+ narrowPrecisionToCGFloat(b),
+ narrowPrecisionToCGFloat(c),
+ narrowPrecisionToCGFloat(d),
+ narrowPrecisionToCGFloat(tx),
+ narrowPrecisionToCGFloat(ty));
+}
+
+AffineTransform::AffineTransform(CGAffineTransform t)
+{
+ m_transform = t;
+}
+
+void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+{
+ m_transform = CGAffineTransformMake(narrowPrecisionToCGFloat(a),
+ narrowPrecisionToCGFloat(b),
+ narrowPrecisionToCGFloat(c),
+ narrowPrecisionToCGFloat(d),
+ narrowPrecisionToCGFloat(tx),
+ narrowPrecisionToCGFloat(ty));
+}
+
+void AffineTransform::map(double x, double y, double *x2, double *y2) const
+{
+ CGPoint result = CGPointApplyAffineTransform(CGPointMake(narrowPrecisionToCGFloat(x), narrowPrecisionToCGFloat(y)), m_transform);
+ *x2 = result.x;
+ *y2 = result.y;
+}
+
+IntRect AffineTransform::mapRect(const IntRect &rect) const
+{
+ return enclosingIntRect(CGRectApplyAffineTransform(CGRect(rect), m_transform));
+}
+
+FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+{
+ return FloatRect(CGRectApplyAffineTransform(CGRect(rect), m_transform));
+}
+
+bool AffineTransform::isIdentity() const
+{
+ return CGAffineTransformIsIdentity(m_transform);
+}
+
+double AffineTransform::a() const
+{
+ return m_transform.a;
+}
+
+void AffineTransform::setA(double a)
+{
+ m_transform.a = narrowPrecisionToCGFloat(a);
+}
+
+double AffineTransform::b() const
+{
+ return m_transform.b;
+}
+
+void AffineTransform::setB(double b)
+{
+ m_transform.b = narrowPrecisionToCGFloat(b);
+}
+
+double AffineTransform::c() const
+{
+ return m_transform.c;
+}
+
+void AffineTransform::setC(double c)
+{
+ m_transform.c = narrowPrecisionToCGFloat(c);
+}
+
+double AffineTransform::d() const
+{
+ return m_transform.d;
+}
+
+void AffineTransform::setD(double d)
+{
+ m_transform.d = narrowPrecisionToCGFloat(d);
+}
+
+double AffineTransform::e() const
+{
+ return m_transform.tx;
+}
+
+void AffineTransform::setE(double e)
+{
+ m_transform.tx = narrowPrecisionToCGFloat(e);
+}
+
+double AffineTransform::f() const
+{
+ return m_transform.ty;
+}
+
+void AffineTransform::setF(double f)
+{
+ m_transform.ty = narrowPrecisionToCGFloat(f);
+}
+
+void AffineTransform::reset()
+{
+ m_transform = CGAffineTransformIdentity;
+}
+
+AffineTransform &AffineTransform::scale(double sx, double sy)
+{
+ m_transform = CGAffineTransformScale(m_transform, narrowPrecisionToCGFloat(sx), narrowPrecisionToCGFloat(sy));
+ return *this;
+}
+
+AffineTransform &AffineTransform::rotate(double d)
+{
+ m_transform = CGAffineTransformRotate(m_transform, narrowPrecisionToCGFloat(deg2rad(d)));
+ return *this;
+}
+
+AffineTransform &AffineTransform::translate(double tx, double ty)
+{
+ m_transform = CGAffineTransformTranslate(m_transform, narrowPrecisionToCGFloat(tx), narrowPrecisionToCGFloat(ty));
+ return *this;
+}
+
+AffineTransform &AffineTransform::shear(double sx, double sy)
+{
+ CGAffineTransform shear = CGAffineTransformMake(1.0f, narrowPrecisionToCGFloat(sy), narrowPrecisionToCGFloat(sx), 1.0f, 0.0f, 0.0f);
+ m_transform = CGAffineTransformConcat(shear, m_transform);
+ return *this;
+}
+
+double AffineTransform::det() const
+{
+ return m_transform.a * m_transform.d - m_transform.b * m_transform.c;
+}
+
+AffineTransform AffineTransform::inverse() const
+{
+ if (isInvertible())
+ return AffineTransform(CGAffineTransformInvert(m_transform));
+ return AffineTransform();
+}
+
+AffineTransform::operator CGAffineTransform() const
+{
+ return m_transform;
+}
+
+bool AffineTransform::operator== (const AffineTransform &m2) const
+{
+ return CGAffineTransformEqualToTransform(m_transform, CGAffineTransform(m2));
+}
+
+AffineTransform &AffineTransform::operator*= (const AffineTransform &m2)
+{
+ m_transform = CGAffineTransformConcat(m_transform, CGAffineTransform(m2));
+ return *this;
+}
+
+AffineTransform AffineTransform::operator* (const AffineTransform &m2)
+{
+ return CGAffineTransformConcat(m_transform, CGAffineTransform(m2));
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/ColorCG.cpp b/WebCore/platform/graphics/cg/ColorCG.cpp
new file mode 100644
index 0000000..48ce9f2
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ColorCG.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 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"
+#include "Color.h"
+
+#if PLATFORM(CG)
+
+#include <wtf/Assertions.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+Color::Color(CGColorRef color)
+{
+ if (!color) {
+ m_color = 0;
+ m_valid = false;
+ return;
+ }
+
+ size_t numComponents = CGColorGetNumberOfComponents(color);
+ const CGFloat* components = CGColorGetComponents(color);
+
+ float r = 0;
+ float g = 0;
+ float b = 0;
+ float a = 0;
+
+ switch (numComponents) {
+ case 2:
+ r = g = b = components[0];
+ a = components[1];
+ break;
+ case 4:
+ r = components[0];
+ g = components[1];
+ b = components[2];
+ a = components[3];
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ m_color = makeRGBA(r * 255, g * 255, b * 255, a * 255);
+}
+
+#if !PLATFORM(MAC)
+
+CGColorRef cgColor(const Color& c)
+{
+ CGColorRef color = NULL;
+ CMProfileRef prof = NULL;
+ CMGetSystemProfile(&prof);
+
+ CGColorSpaceRef rgbSpace = 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);
+ }
+
+ CMCloseProfile(prof);
+
+ return color;
+}
+
+#endif // !PLATFORM(MAC)
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/FloatPointCG.cpp b/WebCore/platform/graphics/cg/FloatPointCG.cpp
new file mode 100644
index 0000000..f9c3353
--- /dev/null
+++ b/WebCore/platform/graphics/cg/FloatPointCG.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const CGPoint& p) : m_x(p.x), m_y(p.y)
+{
+}
+
+FloatPoint::operator CGPoint() const
+{
+ return CGPointMake(m_x, m_y);
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/FloatRectCG.cpp b/WebCore/platform/graphics/cg/FloatRectCG.cpp
new file mode 100644
index 0000000..a1ce367
--- /dev/null
+++ b/WebCore/platform/graphics/cg/FloatRectCG.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+FloatRect::FloatRect(const CGRect& r) : m_location(r.origin), m_size(r.size)
+{
+}
+
+FloatRect::operator CGRect() const
+{
+ return CGRectMake(x(), y(), width(), height());
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/FloatSizeCG.cpp b/WebCore/platform/graphics/cg/FloatSizeCG.cpp
new file mode 100644
index 0000000..383af21
--- /dev/null
+++ b/WebCore/platform/graphics/cg/FloatSizeCG.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 "FloatSize.h"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+FloatSize::FloatSize(const CGSize& s) : m_width(s.width), m_height(s.height)
+{
+}
+
+FloatSize::operator CGSize() const
+{
+ return CGSizeMake(m_width, m_height);
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
new file mode 100644
index 0000000..de546ac
--- /dev/null
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -0,0 +1,976 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007 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.
+ */
+
+#define _USE_MATH_DEFINES 1
+#include "config.h"
+#include "GraphicsContext.h"
+
+#include "AffineTransform.h"
+#include "FloatConversion.h"
+#include "GraphicsContextPlatformPrivateCG.h"
+#include "ImageBuffer.h"
+#include "KURL.h"
+#include "Path.h"
+#include <CoreGraphics/CGBitmapContext.h>
+#include <CoreGraphics/CGPDFContext.h>
+#include <wtf/MathExtras.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/RetainPtr.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static void setCGFillColor(CGContextRef context, const Color& color)
+{
+ CGFloat red, green, blue, alpha;
+ color.getRGBA(red, green, blue, alpha);
+ CGContextSetRGBFillColor(context, red, green, blue, alpha);
+}
+
+static void setCGStrokeColor(CGContextRef context, const Color& color)
+{
+ CGFloat red, green, blue, alpha;
+ color.getRGBA(red, green, blue, alpha);
+ CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
+}
+
+GraphicsContext::GraphicsContext(CGContextRef cgContext)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate(cgContext))
+{
+ setPaintingDisabled(!cgContext);
+ if (cgContext) {
+ // Make sure the context starts in sync with our state.
+ setPlatformFillColor(fillColor());
+ setPlatformStrokeColor(strokeColor());
+ }
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ destroyGraphicsContextPrivate(m_common);
+ delete m_data;
+}
+
+CGContextRef GraphicsContext::platformContext() const
+{
+ ASSERT(!paintingDisabled());
+ ASSERT(m_data->m_cgContext);
+ return m_data->m_cgContext;
+}
+
+void GraphicsContext::savePlatformState()
+{
+ // Note: Do not use this function within this class implementation, since we want to avoid the extra
+ // save of the secondary context (in GraphicsContextPlatformPrivateCG.h).
+ CGContextSaveGState(platformContext());
+ m_data->save();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ // Note: Do not use this function within this class implementation, since we want to avoid the extra
+ // restore of the secondary context (in GraphicsContextPlatformPrivateCG.h).
+ CGContextRestoreGState(platformContext());
+ m_data->restore();
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextRef context = platformContext();
+
+ if (fillColor().alpha())
+ CGContextFillRect(context, rect);
+
+ if (strokeStyle() != NoStroke && strokeColor().alpha()) {
+ // We do a fill of four rects to simulate the stroke of a border.
+ Color oldFillColor = fillColor();
+ if (oldFillColor != strokeColor())
+ setCGFillColor(context, strokeColor());
+ CGRect rects[4] = {
+ FloatRect(rect.x(), rect.y(), rect.width(), 1),
+ FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),
+ FloatRect(rect.x(), rect.y() + 1, 1, rect.height() - 2),
+ FloatRect(rect.right() - 1, rect.y() + 1, 1, rect.height() - 2)
+ };
+ CGContextFillRects(context, rects, 4);
+ if (oldFillColor != strokeColor())
+ setCGFillColor(context, oldFillColor);
+ }
+}
+
+// This is only used to draw borders.
+void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
+{
+ if (paintingDisabled())
+ return;
+
+ if (strokeStyle() == NoStroke || !strokeColor().alpha())
+ return;
+
+ float width = strokeThickness();
+
+ FloatPoint p1 = point1;
+ FloatPoint p2 = point2;
+ bool isVerticalLine = (p1.x() == p2.x());
+
+ // 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 (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) {
+ if (isVerticalLine) {
+ p1.move(0, width);
+ p2.move(0, -width);
+ } else {
+ p1.move(width, 0);
+ p2.move(-width, 0);
+ }
+ }
+
+ if (((int)width) % 2) {
+ if (isVerticalLine) {
+ // We're a vertical line. Adjust our x.
+ p1.move(0.5f, 0.0f);
+ p2.move(0.5f, 0.0f);
+ } else {
+ // We're a horizontal line. Adjust our y.
+ p1.move(0.0f, 0.5f);
+ p2.move(0.0f, 0.5f);
+ }
+ }
+
+ int patWidth = 0;
+ switch (strokeStyle()) {
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = (int)width;
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)width;
+ break;
+ }
+
+ CGContextRef context = platformContext();
+ CGContextSaveGState(context);
+
+ CGContextSetShouldAntialias(context, false);
+
+ if (patWidth) {
+ // Do a rect fill of our endpoints. This ensures we always have the
+ // appearance of being a border. We then draw the actual dotted/dashed line.
+ setCGFillColor(context, strokeColor()); // The save/restore make it safe to mutate the fill color here without setting it back to the old color.
+ if (isVerticalLine) {
+ CGContextFillRect(context, FloatRect(p1.x() - width / 2, p1.y() - width, width, width));
+ CGContextFillRect(context, FloatRect(p2.x() - width / 2, p2.y(), width, width));
+ } else {
+ CGContextFillRect(context, FloatRect(p1.x() - width, p1.y() - width / 2, width, width));
+ CGContextFillRect(context, FloatRect(p2.x(), p2.y() - width / 2, width, width));
+ }
+
+ // Example: 80 pixels with a width of 30 pixels.
+ // Remainder is 20. The maximum pixels of line we could paint
+ // will be 50 pixels.
+ int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*(int)width;
+ int remainder = distance % patWidth;
+ int coverage = distance - remainder;
+ int numSegments = coverage / patWidth;
+
+ float patternOffset = 0.0f;
+ // Special case 1px dotted borders for speed.
+ if (patWidth == 1)
+ patternOffset = 1.0f;
+ else {
+ bool evenNumberOfSegments = numSegments % 2 == 0;
+ if (remainder)
+ evenNumberOfSegments = !evenNumberOfSegments;
+ if (evenNumberOfSegments) {
+ if (remainder) {
+ patternOffset += patWidth - remainder;
+ patternOffset += remainder / 2;
+ } else
+ patternOffset = patWidth / 2;
+ } else {
+ if (remainder)
+ patternOffset = (patWidth - remainder)/2;
+ }
+ }
+
+ const CGFloat dottedLine[2] = { patWidth, patWidth };
+ CGContextSetLineDash(context, patternOffset, dottedLine, 2);
+ }
+
+ CGContextBeginPath(context);
+ CGContextMoveToPoint(context, p1.x(), p1.y());
+ CGContextAddLineToPoint(context, p2.x(), p2.y());
+
+ CGContextStrokePath(context);
+
+ CGContextRestoreGState(context);
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+ // FIXME: CG added CGContextAddEllipseinRect in Tiger, so we should be able to quite easily draw an ellipse.
+ // This code can only handle circles, not ellipses. But khtml only
+ // uses it for circles.
+ ASSERT(rect.width() == rect.height());
+
+ if (paintingDisabled())
+ return;
+
+ CGContextRef context = platformContext();
+ CGContextBeginPath(context);
+ float r = (float)rect.width() / 2;
+ CGContextAddArc(context, rect.x() + r, rect.y() + r, r, 0.0f, 2.0f * piFloat, 0);
+ CGContextClosePath(context);
+
+ if (fillColor().alpha()) {
+ if (strokeStyle() != NoStroke)
+ // stroke and fill
+ CGContextDrawPath(context, kCGPathFillStroke);
+ else
+ CGContextFillPath(context);
+ } else if (strokeStyle() != NoStroke)
+ CGContextStrokePath(context);
+}
+
+
+void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
+{
+ if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())
+ 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;
+ float falen = fa + angleSpan;
+ float start = -fa * piFloat / 180.0f;
+ float end = -falen * piFloat / 180.0f;
+ CGContextAddArc(context, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, start, end, true);
+
+ 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;
+ }
+
+ if (patWidth) {
+ // Example: 80 pixels with a width of 30 pixels.
+ // Remainder is 20. The maximum pixels of line we could paint
+ // will be 50 pixels.
+ int distance;
+ if (hRadius == vRadius)
+ 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;
+
+ float patternOffset = 0.0f;
+ // Special case 1px dotted borders for speed.
+ if (patWidth == 1)
+ patternOffset = 1.0f;
+ else {
+ bool evenNumberOfSegments = numSegments % 2 == 0;
+ if (remainder)
+ evenNumberOfSegments = !evenNumberOfSegments;
+ if (evenNumberOfSegments) {
+ if (remainder) {
+ patternOffset += patWidth - remainder;
+ patternOffset += remainder / 2.0f;
+ } else
+ patternOffset = patWidth / 2.0f;
+ } else {
+ if (remainder)
+ patternOffset = (patWidth - remainder) / 2.0f;
+ }
+ }
+
+ const CGFloat dottedLine[2] = { patWidth, patWidth };
+ CGContextSetLineDash(context, patternOffset, dottedLine, 2);
+ }
+
+ CGContextStrokePath(context);
+
+ CGContextRestoreGState(context);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
+{
+ if (paintingDisabled() || !fillColor().alpha() && (strokeThickness() <= 0 || strokeStyle() == NoStroke))
+ return;
+
+ if (npoints <= 1)
+ return;
+
+ CGContextRef context = platformContext();
+
+ CGContextSaveGState(context);
+
+ CGContextSetShouldAntialias(context, shouldAntialias);
+
+ CGContextBeginPath(context);
+ CGContextMoveToPoint(context, points[0].x(), points[0].y());
+ for (size_t i = 1; i < npoints; i++)
+ CGContextAddLineToPoint(context, points[i].x(), points[i].y());
+ CGContextClosePath(context);
+
+ if (fillColor().alpha()) {
+ if (strokeStyle() != NoStroke)
+ CGContextDrawPath(context, kCGPathEOFillStroke);
+ else
+ CGContextEOFillPath(context);
+ } else
+ CGContextStrokePath(context);
+
+ CGContextRestoreGState(context);
+}
+
+void GraphicsContext::fillRect(const IntRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ if (color.alpha()) {
+ CGContextRef context = platformContext();
+ Color oldFillColor = fillColor();
+ if (oldFillColor != color)
+ setCGFillColor(context, color);
+ CGContextFillRect(context, rect);
+ if (oldFillColor != color)
+ setCGFillColor(context, oldFillColor);
+ }
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ if (color.alpha()) {
+ CGContextRef context = platformContext();
+ Color oldFillColor = fillColor();
+ if (oldFillColor != color)
+ setCGFillColor(context, color);
+ CGContextFillRect(context, rect);
+ if (oldFillColor != color)
+ setCGFillColor(context, oldFillColor);
+ }
+}
+
+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;
+
+ CGContextRef context = platformContext();
+ Color oldFillColor = fillColor();
+ if (oldFillColor != color)
+ setCGFillColor(context, color);
+
+ addPath(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+ CGContextFillPath(context);
+
+ if (oldFillColor != color)
+ setCGFillColor(context, oldFillColor);
+}
+
+
+void GraphicsContext::clip(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+ CGContextClipToRect(platformContext(), rect);
+ m_data->clip(rect);
+}
+
+void GraphicsContext::clipOut(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ CGRect rects[2] = { CGContextGetClipBoundingBox(platformContext()), rect };
+ CGContextBeginPath(platformContext());
+ CGContextAddRects(platformContext(), rects, 2);
+ CGContextEOClip(platformContext());
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextBeginPath(platformContext());
+ CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
+ CGContextAddEllipseInRect(platformContext(), rect);
+ CGContextEOClip(platformContext());
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ 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);
+}
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+ CGContextRef context = platformContext();
+ CGContextSaveGState(context);
+ CGContextSetAlpha(context, opacity);
+ CGContextBeginTransparencyLayer(context, 0);
+ m_data->beginTransparencyLayer();
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+ CGContextRef context = platformContext();
+ CGContextEndTransparencyLayer(context);
+ CGContextRestoreGState(context);
+ m_data->endTransparencyLayer();
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color)
+{
+ // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp
+ blur = min(blur, 1000);
+
+ if (paintingDisabled())
+ return;
+ CGContextRef context = platformContext();
+
+ CGFloat width = size.width();
+ CGFloat height = size.height();
+
+#ifdef BUILDING_ON_TIGER
+ // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated
+ // to the desired integer.
+ static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128);
+ if (width > 0)
+ width += extraShadowOffset;
+ else if (width < 0)
+ width -= extraShadowOffset;
+
+ if (height > 0)
+ height += extraShadowOffset;
+ else if (height < 0)
+ height -= extraShadowOffset;
+#endif
+
+ // Check for an invalid color, as this means that the color was not set for the shadow
+ // and we should therefore just use the default shadow color.
+ if (!color.isValid())
+ CGContextSetShadow(context, CGSizeMake(width, -height), blur); // y is flipped.
+ else {
+ CGColorRef colorCG = cgColor(color);
+ CGContextSetShadowWithColor(context,
+ CGSizeMake(width, -height), // y is flipped.
+ blur,
+ colorCG);
+ CGColorRelease(colorCG);
+ }
+}
+
+void GraphicsContext::clearShadow()
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+}
+
+void GraphicsContext::setMiterLimit(float limit)
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetMiterLimit(platformContext(), limit);
+}
+
+void GraphicsContext::setAlpha(float alpha)
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetAlpha(platformContext(), alpha);
+}
+
+void GraphicsContext::clearRect(const FloatRect& r)
+{
+ if (paintingDisabled())
+ return;
+ CGContextClearRect(platformContext(), r);
+}
+
+void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
+{
+ if (paintingDisabled())
+ return;
+ CGContextStrokeRectWithWidth(platformContext(), r, lineWidth);
+}
+
+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;
+ }
+}
+
+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;
+ }
+}
+
+void GraphicsContext::beginPath()
+{
+ CGContextBeginPath(platformContext());
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ CGContextAddPath(platformContext(), path.platformPath());
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+ CGContextRef context = platformContext();
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path.platformPath());
+ CGContextClip(context);
+ m_data->clip(path);
+}
+
+void GraphicsContext::clipOut(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextBeginPath(platformContext());
+ CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
+ CGContextAddPath(platformContext(), path.platformPath());
+ CGContextEOClip(platformContext());
+}
+
+void GraphicsContext::scale(const FloatSize& size)
+{
+ if (paintingDisabled())
+ return;
+ CGContextScaleCTM(platformContext(), size.width(), size.height());
+ m_data->scale(size);
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+void GraphicsContext::rotate(float angle)
+{
+ if (paintingDisabled())
+ return;
+ CGContextRotateCTM(platformContext(), angle);
+ m_data->rotate(angle);
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+void GraphicsContext::translate(float x, float y)
+{
+ if (paintingDisabled())
+ return;
+ CGContextTranslateCTM(platformContext(), x, y);
+ m_data->translate(x, y);
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+void GraphicsContext::concatCTM(const AffineTransform& transform)
+{
+ if (paintingDisabled())
+ return;
+ CGContextConcatCTM(platformContext(), transform);
+ m_data->concatCTM(transform);
+ m_data->m_userToDeviceTransformKnownToBeIdentity = false;
+}
+
+AffineTransform GraphicsContext::getCTM() const
+{
+ return CGContextGetCTM(platformContext());
+}
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
+{
+ // 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
+ // we get the affine transform matrix and extract the scale.
+
+ if (m_data->m_userToDeviceTransformKnownToBeIdentity)
+ return rect;
+
+ CGAffineTransform deviceMatrix = CGContextGetUserSpaceToDeviceSpaceTransform(platformContext());
+ if (CGAffineTransformIsIdentity(deviceMatrix)) {
+ m_data->m_userToDeviceTransformKnownToBeIdentity = true;
+ return rect;
+ }
+
+ float deviceScaleX = sqrtf(deviceMatrix.a * deviceMatrix.a + deviceMatrix.b * deviceMatrix.b);
+ float deviceScaleY = sqrtf(deviceMatrix.c * deviceMatrix.c + deviceMatrix.d * deviceMatrix.d);
+
+ CGPoint deviceOrigin = CGPointMake(rect.x() * deviceScaleX, rect.y() * deviceScaleY);
+ CGPoint deviceLowerRight = CGPointMake((rect.x() + rect.width()) * deviceScaleX,
+ (rect.y() + rect.height()) * deviceScaleY);
+
+ deviceOrigin.x = roundf(deviceOrigin.x);
+ 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)
+ deviceLowerRight.y += 1;
+ if (deviceOrigin.x == deviceLowerRight.x && rect.width() != 0)
+ deviceLowerRight.x += 1;
+
+ FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x / deviceScaleX, deviceOrigin.y / deviceScaleY);
+ FloatPoint roundedLowerRight = FloatPoint(deviceLowerRight.x / deviceScaleX, deviceLowerRight.y / deviceScaleY);
+ return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
+}
+
+void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool printing)
+{
+ if (paintingDisabled())
+ return;
+
+ if (width <= 0)
+ return;
+
+ CGContextSaveGState(platformContext());
+
+ float x = point.x();
+ float y = point.y();
+ float lineLength = width;
+
+ // Use a minimum thickness of 0.5 in user space.
+ // See http://bugs.webkit.org/show_bug.cgi?id=4255 for details of why 0.5 is the right minimum thickness to use.
+ float thickness = max(strokeThickness(), 0.5f);
+
+ if (!printing) {
+ // On screen, use a minimum thickness of 1.0 in user space (later rounded to an integral number in device space).
+ float adjustedThickness = max(thickness, 1.0f);
+
+ // FIXME: This should be done a better way.
+ // We try to round all parameters to integer boundaries in device space. If rounding pixels in device space
+ // makes our thickness more than double, then there must be a shrinking-scale factor and rounding to pixels
+ // in device space will make the underlines too thick.
+ CGRect lineRect = roundToDevicePixels(FloatRect(x, y, lineLength, adjustedThickness));
+ if (lineRect.size.height < thickness * 2.0) {
+ x = lineRect.origin.x;
+ y = lineRect.origin.y;
+ lineLength = lineRect.size.width;
+ thickness = lineRect.size.height;
+ CGContextSetShouldAntialias(platformContext(), false);
+ }
+ }
+
+ if (fillColor() != strokeColor())
+ setCGFillColor(platformContext(), strokeColor());
+ CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
+
+ CGContextRestoreGState(platformContext());
+}
+
+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);
+ }
+}
+
+void GraphicsContext::setUseLowQualityImageInterpolation(bool lowQualityMode)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextSetInterpolationQuality(platformContext(), lowQualityMode ? kCGInterpolationNone : kCGInterpolationDefault);
+}
+
+bool GraphicsContext::useLowQualityImageInterpolation() const
+{
+ if (paintingDisabled())
+ return false;
+
+ return CGContextGetInterpolationQuality(platformContext());
+}
+
+void GraphicsContext::setPlatformTextDrawingMode(int mode)
+{
+ if (paintingDisabled())
+ return;
+
+ // 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;
+ }
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ setCGStrokeColor(platformContext(), color);
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetLineWidth(platformContext(), thickness);
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ setCGFillColor(platformContext(), color);
+}
+
+void GraphicsContext::setUseAntialiasing(bool enable)
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetShouldAntialias(platformContext(), enable);
+}
+
+#ifndef BUILDING_ON_TIGER // Tiger's setCompositeOperation() is defined in GraphicsContextMac.mm.
+void GraphicsContext::setCompositeOperation(CompositeOperator mode)
+{
+ if (paintingDisabled())
+ return;
+
+ 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;
+ }
+ CGContextSetBlendMode(platformContext(), target);
+}
+#endif
+
+void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
+{
+ CGContextRef context = buffer->context()->platformContext();
+ if (!context)
+ return;
+ CGContextFlush(context);
+ if (CGImageRef image = CGBitmapContextCreateImage(context)) {
+ CGContextDrawImage(platformContext(), roundToDevicePixels(r), image);
+ CGImageRelease(image);
+ }
+}
+
+void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& destRect)
+{
+ CGContextRef context = buffer->context()->platformContext();
+ CGContextFlush(context);
+ RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context));
+ float iw = CGImageGetWidth(image.get());
+ float ih = CGImageGetHeight(image.get());
+ if (srcRect.x() == 0 && srcRect.y() == 0 && iw == srcRect.width() && ih == srcRect.height()) {
+ // Fast path, yay!
+ CGContextDrawImage(platformContext(), destRect, image.get());
+ } else {
+ // Slow path, boo!
+ // FIXME: We can do this without creating a separate image
+
+ size_t csw = static_cast<size_t>(ceilf(srcRect.width()));
+ size_t csh = static_cast<size_t>(ceilf(srcRect.height()));
+
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ size_t bytesPerRow = csw * 4;
+ OwnArrayPtr<char> buffer(new char[csh * bytesPerRow]);
+ RetainPtr<CGContextRef> clippedSourceContext(AdoptCF, CGBitmapContextCreate(buffer.get(), csw, csh,
+ 8, bytesPerRow, colorSpace.get(), kCGImageAlphaPremultipliedLast));
+ CGContextTranslateCTM(clippedSourceContext.get(), -srcRect.x(), -srcRect.y());
+ CGContextDrawImage(clippedSourceContext.get(), CGRectMake(0, 0, iw, ih), image.get());
+
+ RetainPtr<CGImageRef> clippedSourceImage(AdoptCF, CGBitmapContextCreateImage(clippedSourceContext.get()));
+
+ CGContextDrawImage(platformContext(), destRect, clippedSourceImage.get());
+ }
+}
+
+}
+
diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
new file mode 100644
index 0000000..937481b
--- /dev/null
+++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006, 2007 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 <CoreGraphics/CGContext.h>
+
+namespace WebCore {
+
+class GraphicsContextPlatformPrivate {
+public:
+ GraphicsContextPlatformPrivate(CGContextRef cgContext)
+ : m_cgContext(cgContext)
+#if PLATFORM(WIN)
+ , m_hdc(0)
+ , m_transparencyCount(0)
+#endif
+ , m_userToDeviceTransformKnownToBeIdentity(false)
+ {
+ CGContextRetain(m_cgContext);
+ }
+
+ ~GraphicsContextPlatformPrivate()
+ {
+ CGContextRelease(m_cgContext);
+ }
+
+#if PLATFORM(MAC)
+ // These methods do nothing on Mac.
+ void save() {}
+ void restore() {}
+ void clip(const IntRect&) {}
+ void clip(const Path&) {}
+ void scale(const FloatSize&) {}
+ void rotate(float) {}
+ void translate(float, float) {}
+ void concatCTM(const AffineTransform&) {}
+ void beginTransparencyLayer() {}
+ void endTransparencyLayer() {}
+#endif
+
+#if PLATFORM(WIN)
+ // On Windows, we need to update the HDC for form controls to draw in the right place.
+ void save();
+ void restore();
+ void clip(const IntRect&);
+ void clip(const Path&);
+ void scale(const FloatSize&);
+ void rotate(float);
+ void translate(float, float);
+ void concatCTM(const AffineTransform&);
+ void beginTransparencyLayer() { m_transparencyCount++; }
+ void endTransparencyLayer() { m_transparencyCount--; }
+#endif
+
+#if PLATFORM(WIN)
+ HDC m_hdc;
+ unsigned m_transparencyCount;
+#endif
+
+ CGContextRef m_cgContext;
+ bool m_userToDeviceTransformKnownToBeIdentity;
+};
+
+}
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
new file mode 100644
index 0000000..2e48ceb
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Apple, Inc
+ *
+ * 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 <ApplicationServices/ApplicationServices.h>
+#include <wtf/Assertions.h>
+
+using namespace std;
+
+namespace WebCore {
+
+auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool grayScale)
+{
+ if (size.width() < 0 || size.height() < 0)
+ return auto_ptr<ImageBuffer>();
+ unsigned int bytesPerRow = size.width();
+ if (!grayScale) {
+ // Protect against overflow
+ if (bytesPerRow > 0x3FFFFFFF)
+ return auto_ptr<ImageBuffer>();
+ bytesPerRow *= 4;
+ }
+
+ void* imageBuffer = fastCalloc(size.height(), bytesPerRow);
+ if (!imageBuffer)
+ return auto_ptr<ImageBuffer>();
+
+ CGColorSpaceRef colorSpace = grayScale ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
+ CGContextRef cgContext = CGBitmapContextCreate(imageBuffer, size.width(), size.height(), 8, bytesPerRow,
+ colorSpace, grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast);
+ CGColorSpaceRelease(colorSpace);
+ if (!cgContext) {
+ fastFree(imageBuffer);
+ return auto_ptr<ImageBuffer>();
+ }
+
+ auto_ptr<GraphicsContext> context(new GraphicsContext(cgContext));
+ CGContextRelease(cgContext);
+
+ return auto_ptr<ImageBuffer>(new ImageBuffer(imageBuffer, size, context));
+}
+
+
+ImageBuffer::ImageBuffer(void* imageData, const IntSize& size, auto_ptr<GraphicsContext> context)
+ : m_data(imageData)
+ , m_size(size)
+ , m_context(context.release())
+ , m_cgImage(0)
+{
+ ASSERT((reinterpret_cast<size_t>(imageData) & 2) == 0);
+}
+
+ImageBuffer::~ImageBuffer()
+{
+ fastFree(m_data);
+ CGImageRelease(m_cgImage);
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ return m_context.get();
+}
+
+CGImageRef ImageBuffer::cgImage() const
+{
+ // It's assumed that if cgImage() is called, the actual rendering to the
+ // contained GraphicsContext must be done, as we create the CGImageRef here.
+ if (!m_cgImage) {
+ ASSERT(context());
+ m_cgImage = CGBitmapContextCreateImage(context()->platformContext());
+ }
+
+ return m_cgImage;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+{
+ if (!m_data)
+ return 0;
+
+ 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())
+ memset(data, 0, result->data()->length());
+
+ int originx = rect.x();
+ int destx = 0;
+ if (originx < 0) {
+ destx = -originx;
+ originx = 0;
+ }
+ int endx = rect.x() + rect.width();
+ if (endx > m_size.width())
+ endx = m_size.width();
+ int numColumns = endx - originx;
+
+ int originy = rect.y();
+ int desty = 0;
+ if (originy < 0) {
+ desty = -originy;
+ originy = 0;
+ }
+ int endy = rect.y() + rect.height();
+ if (endy > m_size.height())
+ endy = m_size.height();
+ int numRows = endy - originy;
+
+ unsigned srcBytesPerRow = 4 * m_size.width();
+ unsigned destBytesPerRow = 4 * rect.width();
+
+ // m_size.height() - originy to handle the accursed flipped y axis in CG backing store
+ unsigned char* srcRows = reinterpret_cast<unsigned char*>(m_data) + (m_size.height() - originy - 1) * 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++) {
+ if (unsigned char alpha = srcRows[3]) {
+ destRows[0] = (srcRows[0] * 255) / alpha;
+ destRows[1] = (srcRows[1] * 255) / alpha;
+ destRows[2] = (srcRows[2] * 255) / alpha;
+ destRows[3] = alpha;
+ } else {
+ reinterpret_cast<uint32_t*>(destRows)[0] = reinterpret_cast<uint32_t*>(srcRows)[0];
+ }
+ destRows += 4;
+ }
+ srcRows -= srcBytesPerRow;
+ }
+ return result;
+}
+
+void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ ASSERT(sourceRect.width() > 0);
+ ASSERT(sourceRect.height() > 0);
+
+ int originx = sourceRect.x();
+ int destx = destPoint.x() + sourceRect.x();
+ ASSERT(destx >= 0);
+ ASSERT(destx < m_size.width());
+ ASSERT(originx >= 0);
+ ASSERT(originx <= sourceRect.right());
+
+ int endx = destPoint.x() + sourceRect.right();
+ ASSERT(endx <= m_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(originy >= 0);
+ ASSERT(originy <= sourceRect.bottom());
+
+ int endy = destPoint.y() + sourceRect.bottom();
+ ASSERT(endx <= m_size.height());
+ int numRows = endy - desty;
+
+ unsigned srcBytesPerRow = 4 * source->width();
+ unsigned destBytesPerRow = 4 * m_size.width();
+
+ unsigned char* srcRows = source->data()->data().data() + originy * srcBytesPerRow + originx * 4;
+
+ // -desty to handle the accursed flipped y axis
+ unsigned char* destRows = reinterpret_cast<unsigned char*>(m_data) + (m_size.height() - desty - 1) * destBytesPerRow + destx * 4;
+ for (int y = 0; y < numRows; ++y) {
+ for (int x = 0; x < numColumns; x++) {
+ unsigned char alpha = srcRows[x * 4 + 3];
+ if (alpha != 255) {
+ destRows[x * 4 + 0] = (srcRows[0] * alpha) / 255;
+ destRows[x * 4 + 1] = (srcRows[1] * alpha) / 255;
+ destRows[x * 4 + 2] = (srcRows[2] * alpha) / 255;
+ destRows[x * 4 + 3] = alpha;
+ } else {
+ reinterpret_cast<uint32_t*>(destRows + x * 4)[0] = reinterpret_cast<uint32_t*>(srcRows + x * 4)[0];
+ }
+ }
+ destRows -= destBytesPerRow;
+ srcRows += srcBytesPerRow;
+ }
+}
+
+}
diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp
new file mode 100644
index 0000000..5958d86
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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"
+#include "BitmapImage.h"
+
+#if PLATFORM(CG)
+
+#include "AffineTransform.h"
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "ImageObserver.h"
+#include "PDFDocumentImage.h"
+#include "PlatformString.h"
+#include <ApplicationServices/ApplicationServices.h>
+
+#if PLATFORM(MAC)
+#include "WebCoreSystemInterface.h"
+#endif
+
+#if PLATFORM(WIN)
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
+
+namespace WebCore {
+
+void FrameData::clear()
+{
+ if (m_frame) {
+ CGImageRelease(m_frame);
+ m_frame = 0;
+ m_duration = 0.0f;
+ m_hasAlpha = true;
+ }
+}
+
+// ================================================
+// Image Class
+// ================================================
+
+// Drawing Routines
+
+void BitmapImage::checkForSolidColor()
+{
+ 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);
+ }
+ }
+}
+
+CGImageRef BitmapImage::getCGImageRef()
+{
+ return frameAtIndex(0);
+}
+
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
+{
+ if (!m_source.initialized())
+ return;
+
+ CGRect fr = ctxt->roundToDevicePixels(srcRect);
+ CGRect ir = ctxt->roundToDevicePixels(dstRect);
+
+ CGImageRef image = frameAtIndex(m_currentFrame);
+ if (!image) // If it's too early we won't have an image yet.
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(ctxt, ir, solidColor(), compositeOp);
+ return;
+ }
+
+ // Get the height (in adjusted, i.e. scaled, coords) of the portion of the image
+ // that is currently decoded. This could be less that the actual height.
+ CGSize selfSize = size(); // full image size, in pixels
+ float curHeight = CGImageGetHeight(image); // height of loaded portion, in pixels
+
+ CGSize adjustedSize = selfSize;
+ if (curHeight < selfSize.height) {
+ adjustedSize.height *= curHeight / selfSize.height;
+
+ // Is the amount of available bands less than what we need to draw? If so,
+ // we may have to clip 'fr' if it goes outside the available bounds.
+ if (CGRectGetMaxY(fr) > adjustedSize.height) {
+ float frHeight = adjustedSize.height - fr.origin.y; // clip fr to available bounds
+ if (frHeight <= 0)
+ return; // clipped out entirely
+ ir.size.height *= (frHeight / fr.size.height); // scale ir proportionally to fr
+ fr.size.height = frHeight;
+ }
+ }
+
+ CGContextRef context = ctxt->platformContext();
+ ctxt->save();
+
+ // Flip the coords.
+ ctxt->setCompositeOperation(compositeOp);
+ CGContextTranslateCTM(context, ir.origin.x, ir.origin.y);
+ CGContextScaleCTM(context, 1, -1);
+ CGContextTranslateCTM(context, 0, -ir.size.height);
+
+ // Translated to origin, now draw at 0,0.
+ ir.origin.x = ir.origin.y = 0;
+
+ // If we're drawing a sub portion of the image then create
+ // a image for the sub portion and draw that.
+ // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ if (fr.size.width != adjustedSize.width || fr.size.height != adjustedSize.height) {
+ // Convert ft to image pixel coords:
+ float xscale = adjustedSize.width / selfSize.width;
+ float yscale = adjustedSize.height / curHeight; // yes, curHeight, not selfSize.height!
+ fr.origin.x /= xscale;
+ fr.origin.y /= yscale;
+ fr.size.width /= xscale;
+ fr.size.height /= yscale;
+
+ image = CGImageCreateWithImageInRect(image, fr);
+ if (image) {
+ CGContextDrawImage(context, ir, image);
+ CFRelease(image);
+ }
+ } else // Draw the whole image.
+ CGContextDrawImage(context, ir, image);
+
+ ctxt->restore();
+
+ startAnimation();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+void Image::drawPatternCallback(void* info, CGContextRef context)
+{
+ CGImageRef image = (CGImageRef)info;
+ CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(0, 0, CGImageGetWidth(image), CGImageGetHeight(image))), image);
+}
+
+void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ ASSERT(patternTransform.isInvertible());
+ if (!patternTransform.isInvertible())
+ // Avoid a hang under CGContextDrawTiledImage on release builds.
+ return;
+
+ CGContextRef context = ctxt->platformContext();
+ ctxt->save();
+ CGContextClipToRect(context, destRect);
+ ctxt->setCompositeOperation(op);
+ CGContextTranslateCTM(context, destRect.x(), destRect.y());
+ CGContextScaleCTM(context, 1, -1);
+ CGContextTranslateCTM(context, 0, -destRect.height());
+
+ // Compute the scaled tile size.
+ float scaledTileHeight = tileRect.height() * narrowPrecisionToFloat(patternTransform.d());
+
+ // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being
+ // the origin).
+ float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out.
+ float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight);
+
+ CGImageRef tileImage = nativeImageForCurrentFrame();
+ float h = CGImageGetHeight(tileImage);
+
+ 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);
+ }
+
+#ifndef BUILDING_ON_TIGER
+ // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
+ // its buffer is the same size as the overall image. Because a partially decoded CGImageRef with a smaller width or height than the
+ // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.
+ // FIXME: Could create WebKitSystemInterface SPI for CGCreatePatternWithImage2 and probably make Tiger tile faster as well.
+ float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
+ float w = CGImageGetWidth(tileImage);
+ if (w == size().width() && h == size().height())
+ CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage);
+ else {
+#endif
+
+ // On Leopard, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
+ // On Tiger this code runs all the time. This code is suboptimal because the pattern does not reference the image directly, and the
+ // pattern is destroyed before exiting the function. This means any decoding the pattern does doesn't end up cached anywhere, so we
+ // redecode every time we paint.
+ static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL };
+ CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
+ 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);
+ ctxt->restore();
+ return;
+ }
+
+ CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+
+ CGFloat alpha = 1;
+ CGColorRef color = CGColorCreateWithPattern(patternSpace, pattern, &alpha);
+ CGContextSetFillColorSpace(context, patternSpace);
+ CGColorSpaceRelease(patternSpace);
+ CGPatternRelease(pattern);
+
+ // FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
+ wkSetPatternBaseCTM(context, CGAffineTransformIdentity);
+ CGContextSetPatternPhase(context, CGSizeZero);
+
+ CGContextSetFillColorWithColor(context, color);
+ CGContextFillRect(context, CGContextGetClipBoundingBox(context));
+
+ CGColorRelease(color);
+
+#ifndef BUILDING_ON_TIGER
+ }
+#endif
+
+ if (subImage != tileImage)
+ CGImageRelease(subImage);
+ ctxt->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
new file mode 100644
index 0000000..08e8172
--- /dev/null
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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"
+
+#if PLATFORM(CG)
+
+#include "IntSize.h"
+#include "SharedBuffer.h"
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+static const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
+
+ImageSource::ImageSource()
+ : m_decoder(0)
+{
+}
+
+ImageSource::~ImageSource()
+{
+ clear();
+}
+
+void ImageSource::clear()
+{
+ if (m_decoder) {
+ CFRelease(m_decoder);
+ m_decoder = 0;
+ }
+}
+
+CFDictionaryRef imageSourceOptions()
+{
+ static CFDictionaryRef options;
+
+ if (!options) {
+ const void* keys[2] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32 };
+ const void* values[2] = { kCFBooleanTrue, kCFBooleanTrue };
+ options = CFDictionaryCreate(NULL, keys, values, 2,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ }
+ return options;
+}
+
+bool ImageSource::initialized() const
+{
+ return m_decoder;
+}
+
+void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
+{
+ if (!m_decoder)
+ m_decoder = CGImageSourceCreateIncremental(NULL);
+#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();
+#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 cfData = CFDataCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data->data()), data->size(), kCFAllocatorNull);
+#endif
+ CGImageSourceUpdateData(m_decoder, cfData, allDataReceived);
+ CFRelease(cfData);
+}
+
+bool ImageSource::isSizeAvailable()
+{
+ bool result = false;
+ CGImageSourceStatus imageSourceStatus = CGImageSourceGetStatus(m_decoder);
+
+ // Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
+ if (imageSourceStatus >= kCGImageStatusIncomplete) {
+ CFDictionaryRef image0Properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions());
+ if (image0Properties) {
+ CFNumberRef widthNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties, kCGImagePropertyPixelWidth);
+ CFNumberRef heightNumber = (CFNumberRef)CFDictionaryGetValue(image0Properties, kCGImagePropertyPixelHeight);
+ result = widthNumber && heightNumber;
+ CFRelease(image0Properties);
+ }
+ }
+
+ return result;
+}
+
+IntSize ImageSource::size() const
+{
+ IntSize result;
+ CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions());
+ if (properties) {
+ int w = 0, h = 0;
+ CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth);
+ if (num)
+ CFNumberGetValue(num, kCFNumberIntType, &w);
+ num = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight);
+ if (num)
+ CFNumberGetValue(num, kCFNumberIntType, &h);
+ result = IntSize(w, h);
+ CFRelease(properties);
+ }
+ return result;
+}
+
+int ImageSource::repetitionCount()
+{
+ int result = cAnimationLoopOnce; // No property means loop once.
+
+ // A property with value 0 means loop forever.
+ CFDictionaryRef properties = CGImageSourceCopyProperties(m_decoder, imageSourceOptions());
+ if (properties) {
+ CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties, 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;
+}
+
+size_t ImageSource::frameCount() const
+{
+ return m_decoder ? CGImageSourceGetCount(m_decoder) : 0;
+}
+
+CGImageRef ImageSource::createFrameAtIndex(size_t index)
+{
+ CGImageRef image = 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;
+
+ // 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);
+ if (!maskedImage)
+ return image;
+
+ CGImageRelease(image);
+ return maskedImage;
+}
+
+bool ImageSource::frameIsCompleteAtIndex(size_t index)
+{
+ return CGImageSourceGetStatusAtIndex(m_decoder, index) == kCGImageStatusComplete;
+}
+
+float ImageSource::frameDurationAtIndex(size_t index)
+{
+ float duration = 0;
+ CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions());
+ if (properties) {
+ CFDictionaryRef typeProperties = (CFDictionaryRef)CFDictionaryGetValue(properties, 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.
+ // 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.
+ if (duration < 0.051f)
+ return 0.100f;
+ return duration;
+}
+
+bool ImageSource::frameHasAlphaAtIndex(size_t index)
+{
+ // Might be interesting to do this optimization on Mac some day, but for now we're just using this
+ // for the Cairo source, since it uses our decoders, and our decoders can answer this question.
+ // FIXME: Could return false for JPEG and other non-transparent image formats.
+ // FIXME: Could maybe return false for a GIF Frame if we have enough info in the GIF properties dictionary
+ // to determine whether or not a transparent color was defined.
+ return true;
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/IntPointCG.cpp b/WebCore/platform/graphics/cg/IntPointCG.cpp
new file mode 100644
index 0000000..95dbe5f
--- /dev/null
+++ b/WebCore/platform/graphics/cg/IntPointCG.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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"
+#include "IntPoint.h"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+IntPoint::IntPoint(const CGPoint& p) : m_x(static_cast<int>(p.x)), m_y(static_cast<int>(p.y))
+{
+}
+
+IntPoint::operator CGPoint() const
+{
+ return CGPointMake(m_x, m_y);
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/IntRectCG.cpp b/WebCore/platform/graphics/cg/IntRectCG.cpp
new file mode 100644
index 0000000..73fd63f
--- /dev/null
+++ b/WebCore/platform/graphics/cg/IntRectCG.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, 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"
+#include "IntRect.h"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+IntRect::operator CGRect() const
+{
+ return CGRectMake(x(), y(), width(), height());
+}
+
+IntRect enclosingIntRect(const CGRect& rect)
+{
+ int l = static_cast<int>(floorf(rect.origin.x));
+ int t = static_cast<int>(floorf(rect.origin.y));
+ int r = static_cast<int>(ceilf(CGRectGetMaxX(rect)));
+ int b = static_cast<int>(ceilf(CGRectGetMaxY(rect)));
+ return IntRect(l, t, r - l, b - t);
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/IntSizeCG.cpp b/WebCore/platform/graphics/cg/IntSizeCG.cpp
new file mode 100644
index 0000000..d8e8c83
--- /dev/null
+++ b/WebCore/platform/graphics/cg/IntSizeCG.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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"
+#include "IntSize.h"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+IntSize::IntSize(const CGSize& s) : m_width(static_cast<int>(s.width)), m_height(static_cast<int>(s.height))
+{
+}
+
+IntSize::operator CGSize() const
+{
+ return CGSizeMake(m_width, m_height);
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
new file mode 100644
index 0000000..2578f08
--- /dev/null
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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.
+ */
+
+#define _USE_MATH_DEFINES 1
+#include "config.h"
+#include "PDFDocumentImage.h"
+
+#if PLATFORM(CG)
+
+#include "GraphicsContext.h"
+#include "ImageObserver.h"
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+PDFDocumentImage::PDFDocumentImage()
+ : Image(0) // PDFs don't animate
+ , m_document(0)
+ , m_rotation(0.0f)
+ , m_currentPage(-1)
+{
+}
+
+PDFDocumentImage::~PDFDocumentImage()
+{
+ CGPDFDocumentRelease(m_document);
+}
+
+IntSize PDFDocumentImage::size() const
+{
+ const float sina = sinf(-m_rotation);
+ const float cosa = cosf(-m_rotation);
+ const float width = m_mediaBox.size().width();
+ const float height = m_mediaBox.size().height();
+ const float rotWidth = width * cosa - height * sina;
+ const float rotHeight = width * sina + height * cosa;
+
+ return IntSize((int)(fabsf(rotWidth) + 0.5f), (int)(fabsf(rotHeight) + 0.5f));
+}
+
+bool PDFDocumentImage::dataChanged(bool allDataReceived)
+{
+ if (allDataReceived && !m_document) {
+#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 = m_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*>(m_data->data()), m_data->size(), kCFAllocatorNull);
+#endif
+ CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data);
+ CFRelease(data);
+ m_document = CGPDFDocumentCreateWithProvider(dataProvider);
+ CGDataProviderRelease(dataProvider);
+ setCurrentPage(0);
+ }
+ return m_document; // return true if size is available
+}
+
+void PDFDocumentImage::adjustCTM(GraphicsContext* context) const
+{
+ // rotate the crop box and calculate bounding box
+ float sina = sinf(-m_rotation);
+ float cosa = cosf(-m_rotation);
+ float width = m_cropBox.width();
+ float height = m_cropBox.height();
+
+ // calculate rotated x and y edges of the corp box. if they're negative, it means part of the image has
+ // been rotated outside of the bounds and we need to shift over the image so it lies inside the bounds again
+ CGPoint rx = CGPointMake(width * cosa, width * sina);
+ CGPoint ry = CGPointMake(-height * sina, height * cosa);
+
+ // adjust so we are at the crop box origin
+ const CGFloat zero = 0;
+ CGContextTranslateCTM(context->platformContext(), floorf(-min(zero, min(rx.x, ry.x))), floorf(-min(zero, min(rx.y, ry.y))));
+
+ // rotate -ve to remove rotation
+ CGContextRotateCTM(context->platformContext(), -m_rotation);
+
+ // shift so we are completely within media box
+ CGContextTranslateCTM(context->platformContext(), m_mediaBox.x() - m_cropBox.x(), m_mediaBox.y() - m_cropBox.y());
+}
+
+void PDFDocumentImage::setCurrentPage(int page)
+{
+ if (!m_document)
+ return;
+
+ if (page == m_currentPage)
+ return;
+
+ if (!(page >= 0 && page < pageCount()))
+ return;
+
+ m_currentPage = page;
+
+ CGPDFPageRef cgPage = CGPDFDocumentGetPage(m_document, page + 1);
+
+ // get media box (guaranteed)
+ m_mediaBox = CGPDFPageGetBoxRect(cgPage, kCGPDFMediaBox);
+
+ // get crop box (not always there). if not, use media box
+ CGRect r = CGPDFPageGetBoxRect(cgPage, kCGPDFCropBox);
+ if (!CGRectIsEmpty(r))
+ m_cropBox = r;
+ else
+ m_cropBox = m_mediaBox;
+
+ // get page rotation angle
+ m_rotation = CGPDFPageGetRotationAngle(cgPage) * piFloat / 180.0f; // to radians
+}
+
+int PDFDocumentImage::pageCount() const
+{
+ return m_document ? CGPDFDocumentGetNumberOfPages(m_document) : 0;
+}
+
+void PDFDocumentImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op)
+{
+ if (!m_document || m_currentPage == -1)
+ return;
+
+ context->save();
+
+ context->setCompositeOperation(op);
+
+ float hScale = dstRect.width() / srcRect.width();
+ float vScale = dstRect.height() / srcRect.height();
+
+ // Scale and translate so the document is rendered in the correct location,
+ // including accounting for the fact that a GraphicsContext is always flipped
+ // and doing appropriate flipping.
+ CGContextTranslateCTM(context->platformContext(), dstRect.x() - srcRect.x() * hScale, dstRect.y() - srcRect.y() * vScale);
+ CGContextScaleCTM(context->platformContext(), hScale, vScale);
+ CGContextScaleCTM(context->platformContext(), 1, -1);
+ CGContextTranslateCTM(context->platformContext(), 0, -srcRect.height());
+ CGContextClipToRect(context->platformContext(), CGRectIntegral(srcRect));
+
+ // Rotate translate image into position according to doc properties.
+ adjustCTM(context);
+
+ CGContextTranslateCTM(context->platformContext(), -m_mediaBox.x(), -m_mediaBox.y());
+ CGContextDrawPDFPage(context->platformContext(), CGPDFDocumentGetPage(m_document, m_currentPage + 1));
+
+ context->restore();
+
+ if (imageObserver())
+ imageObserver()->didDraw(this);
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h
new file mode 100644
index 0000000..caddc05
--- /dev/null
+++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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 "Image.h"
+
+#include "FloatRect.h"
+#include "GraphicsTypes.h"
+
+#if PLATFORM(CG)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+ class GraphicsContext;
+
+ class PDFDocumentImage : public Image {
+ public:
+ PDFDocumentImage();
+ ~PDFDocumentImage();
+
+ virtual bool dataChanged(bool allDataReceived);
+
+ virtual IntSize size() const;
+
+ private:
+ virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator);
+
+ void setCurrentPage(int);
+ int pageCount() const;
+ void adjustCTM(GraphicsContext*) const;
+
+ CGPDFDocumentRef m_document;
+ FloatRect m_mediaBox;
+ FloatRect m_cropBox;
+ float m_rotation;
+ int m_currentPage;
+ };
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp
new file mode 100644
index 0000000..c0a0caf
--- /dev/null
+++ b/WebCore/platform/graphics/cg/PathCG.cpp
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * 2006 Rob Buis <buis@kde.org>
+ *
+ * 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"
+
+#if PLATFORM(CG)
+
+#include "AffineTransform.h"
+#include <ApplicationServices/ApplicationServices.h>
+#include "FloatRect.h"
+#include "IntRect.h"
+#include "PlatformString.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(CGPathCreateMutable())
+{
+}
+
+Path::~Path()
+{
+ CGPathRelease(m_path);
+}
+
+Path::Path(const Path& other)
+ : m_path(CGPathCreateMutableCopy(other.m_path))
+{
+}
+
+Path& Path::operator=(const Path& other)
+{
+ CGMutablePathRef path = CGPathCreateMutableCopy(other.m_path);
+ CGPathRelease(m_path);
+ m_path = path;
+ return *this;
+}
+
+
+static void copyClosingSubpathsApplierFunction(void* info, const CGPathElement* element)
+{
+ CGMutablePathRef path = static_cast<CGMutablePathRef>(info);
+ CGPoint* points = element->points;
+
+ switch (element->type) {
+ case kCGPathElementMoveToPoint:
+ if (!CGPathIsEmpty(path)) // to silence a warning when trying to close an empty path
+ CGPathCloseSubpath(path); // This is the only change from CGPathCreateMutableCopy
+ CGPathMoveToPoint(path, 0, points[0].x, points[0].y);
+ break;
+ case kCGPathElementAddLineToPoint:
+ CGPathAddLineToPoint(path, 0, points[0].x, points[0].y);
+ break;
+ case kCGPathElementAddQuadCurveToPoint:
+ CGPathAddQuadCurveToPoint(path, 0, points[0].x, points[0].y, points[1].x, points[1].y);
+ break;
+ case kCGPathElementAddCurveToPoint:
+ CGPathAddCurveToPoint(path, 0, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y);
+ break;
+ case kCGPathElementCloseSubpath:
+ CGPathCloseSubpath(path);
+ break;
+ }
+}
+
+static CGMutablePathRef copyCGPathClosingSubpaths(CGPathRef originalPath)
+{
+ CGMutablePathRef path = CGPathCreateMutable();
+ CGPathApply(originalPath, path, copyClosingSubpathsApplierFunction);
+ CGPathCloseSubpath(path);
+ return path;
+}
+
+bool Path::contains(const FloatPoint &point, WindRule rule) const
+{
+ if (!boundingRect().contains(point))
+ 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);
+ return ret;
+}
+
+void Path::translate(const FloatSize& size)
+{
+ CGAffineTransform translation = CGAffineTransformMake(1, 0, 0, 1, size.width(), size.height());
+ CGMutablePathRef newPath = CGPathCreateMutable();
+ CGPathAddPath(newPath, &translation, m_path);
+ CGPathRelease(m_path);
+ m_path = newPath;
+}
+
+FloatRect Path::boundingRect() const
+{
+ return CGPathGetBoundingBox(m_path);
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ CGPathMoveToPoint(m_path, 0, point.x(), point.y());
+}
+
+void Path::addLineTo(const FloatPoint& p)
+{
+ CGPathAddLineToPoint(m_path, 0, p.x(), p.y());
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ CGPathAddQuadCurveToPoint(m_path, 0, cp.x(), cp.y(), p.x(), p.y());
+}
+
+void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ CGPathAddCurveToPoint(m_path, 0, cp1.x(), cp1.y(), cp2.x(), cp2.y(), p.x(), p.y());
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ CGPathAddArcToPoint(m_path, 0, p1.x(), p1.y(), p2.x(), p2.y(), radius);
+}
+
+void Path::closeSubpath()
+{
+ if (!CGPathIsEmpty(m_path)) // to silence a warning when trying to close an empty path
+ CGPathCloseSubpath(m_path);
+}
+
+void Path::addArc(const FloatPoint& p, float r, float sa, float ea, bool clockwise)
+{
+ // Workaround for <rdar://problem/5189233> CGPathAddArc hangs or crashes when passed inf as start or end angle
+ if (isfinite(sa) && isfinite(ea))
+ CGPathAddArc(m_path, 0, p.x(), p.y(), r, sa, ea, clockwise);
+}
+
+void Path::addRect(const FloatRect& r)
+{
+ CGPathAddRect(m_path, 0, r);
+}
+
+void Path::addEllipse(const FloatRect& r)
+{
+ CGPathAddEllipseInRect(m_path, 0, r);
+}
+
+void Path::clear()
+{
+ CGPathRelease(m_path);
+ m_path = CGPathCreateMutable();
+}
+
+bool Path::isEmpty() const
+{
+ return CGPathIsEmpty(m_path);
+ }
+
+static void CGPathToCFStringApplierFunction(void* info, const CGPathElement *element)
+{
+ CFMutableStringRef string = (CFMutableStringRef)info;
+ CFStringRef typeString = CFSTR("");
+ CGPoint* points = element->points;
+ switch (element->type) {
+ case kCGPathElementMoveToPoint:
+ CFStringAppendFormat(string, 0, CFSTR("M%.2f,%.2f"), points[0].x, points[0].y);
+ break;
+ case kCGPathElementAddLineToPoint:
+ CFStringAppendFormat(string, 0, CFSTR("L%.2f,%.2f"), points[0].x, points[0].y);
+ break;
+ case kCGPathElementAddQuadCurveToPoint:
+ CFStringAppendFormat(string, 0, CFSTR("Q%.2f,%.2f,%.2f,%.2f"),
+ points[0].x, points[0].y, points[1].x, points[1].y);
+ break;
+ case kCGPathElementAddCurveToPoint:
+ CFStringAppendFormat(string, 0, CFSTR("C%.2f,%.2f,%.2f,%.2f,%.2f,%.2f"),
+ points[0].x, points[0].y, points[1].x, points[1].y,
+ points[2].x, points[2].y);
+ break;
+ case kCGPathElementCloseSubpath:
+ typeString = CFSTR("X"); break;
+ }
+}
+
+static CFStringRef CFStringFromCGPath(CGPathRef path)
+{
+ if (!path)
+ return 0;
+
+ CFMutableStringRef string = CFStringCreateMutable(NULL, 0);
+ CGPathApply(path, string, CGPathToCFStringApplierFunction);
+
+ return string;
+}
+
+
+#pragma mark -
+#pragma mark Path Management
+
+String Path::debugString() const
+{
+ String result;
+ if (!isEmpty()) {
+ CFStringRef pathString = CFStringFromCGPath(m_path);
+ result = String(pathString);
+ CFRelease(pathString);
+ }
+ return result;
+}
+
+struct PathApplierInfo {
+ void* info;
+ PathApplierFunction function;
+};
+
+void CGPathApplierToPathApplier(void *info, const CGPathElement *element)
+{
+ PathApplierInfo* pinfo = (PathApplierInfo*)info;
+ FloatPoint points[3];
+ PathElement pelement;
+ pelement.type = (PathElementType)element->type;
+ pelement.points = points;
+ CGPoint* cgPoints = element->points;
+ switch (element->type) {
+ case kCGPathElementMoveToPoint:
+ case kCGPathElementAddLineToPoint:
+ points[0] = cgPoints[0];
+ break;
+ case kCGPathElementAddQuadCurveToPoint:
+ points[0] = cgPoints[0];
+ points[1] = cgPoints[1];
+ break;
+ case kCGPathElementAddCurveToPoint:
+ points[0] = cgPoints[0];
+ points[1] = cgPoints[1];
+ points[2] = cgPoints[2];
+ break;
+ case kCGPathElementCloseSubpath:
+ break;
+ }
+ pinfo->function(pinfo->info, &pelement);
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ PathApplierInfo pinfo;
+ pinfo.info = info;
+ pinfo.function = function;
+ CGPathApply(m_path, &pinfo, CGPathApplierToPathApplier);
+}
+
+void Path::transform(const AffineTransform& transform)
+{
+ CGMutablePathRef path = CGPathCreateMutable();
+ CGAffineTransform transformCG = transform;
+ CGPathAddPath(path, &transformCG, m_path);
+ CGPathRelease(m_path);
+ m_path = path;
+}
+
+}
+
+#endif // PLATFORM(CG)
diff --git a/WebCore/platform/graphics/gtk/ColorGtk.cpp b/WebCore/platform/graphics/gtk/ColorGtk.cpp
new file mode 100644
index 0000000..27f1b14
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/ColorGtk.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2007 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 "Color.h"
+
+#include <gdk/gdk.h>
+
+namespace WebCore {
+
+Color::Color(const GdkColor& c)
+ : m_color(makeRGB(c.red >> 8, c.green >> 8, c.blue >> 8))
+ , m_valid(true)
+{
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp b/WebCore/platform/graphics/gtk/FontCacheGtk.cpp
new file mode 100644
index 0000000..aec5758
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/FontCacheGtk.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@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 "SimpleFontData.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+void FontCache::platformInit()
+{
+ if (!FontPlatformData::init())
+ ASSERT_NOT_REACHED();
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ return new SimpleFontData(FontPlatformData(font.fontDescription(), font.family().family()));
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ return new FontPlatformData(font.fontDescription(), font.family().family());
+}
+
+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 timesStr("Times New Roman");
+ return getCachedFontPlatformData(fontDescription, timesStr);
+}
+
+bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicString& family)
+{
+ FontPlatformData platformData(fontDescription, family);
+ return platformData.m_pattern != 0;
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ return new FontPlatformData(fontDescription, family);
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp b/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..3ff63c2
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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()
+{
+ cairo_font_face_destroy(m_fontFace);
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic)
+{
+ return FontPlatformData(m_fontFace, size, bold, italic);
+}
+
+static void releaseData(void* data)
+{
+ static_cast<SharedBuffer*>(data)->deref();
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ ASSERT_ARG(buffer, buffer);
+
+ int error;
+
+ static FT_Library library = 0;
+ if (!library) {
+ error = FT_Init_FreeType(&library);
+ if (error) {
+ library = 0;
+ return 0;
+ }
+ }
+
+ FT_Face face;
+ error = FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(buffer->data()), buffer->size(), 0, &face);
+ if (error)
+ return 0;
+
+ buffer->ref();
+ cairo_font_face_t* fontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
+
+ static cairo_user_data_key_t bufferKey;
+ cairo_font_face_set_user_data(fontFace, &bufferKey, buffer, releaseData);
+
+ return new FontCustomPlatformData(fontFace);
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformData.h b/WebCore/platform/graphics/gtk/FontCustomPlatformData.h
new file mode 100644
index 0000000..237904d
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/FontCustomPlatformData.h
@@ -0,0 +1,49 @@
+/*
+ * 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 <wtf/Noncopyable.h>
+
+typedef struct _cairo_font_face cairo_font_face_t;
+
+namespace WebCore {
+
+class FontPlatformData;
+class SharedBuffer;
+
+struct FontCustomPlatformData : Noncopyable {
+ FontCustomPlatformData(cairo_font_face_t* fontFace)
+ : m_fontFace(fontFace)
+ {}
+
+ ~FontCustomPlatformData();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic);
+
+ cairo_font_face_t* m_fontFace;
+};
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
new file mode 100644
index 0000000..387b61c
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (c) 2007 Hiroyuki Ikezoe
+ * Copyright (c) 2007 Kouhei Sutou
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Xan Lopez <xan@gnome.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+
+#include <cairo.h>
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+
+namespace WebCore {
+
+#define IS_HIGH_SURROGATE(u) ((UChar)(u) >= (UChar)0xd800 && (UChar)(u) <= (UChar)0xdbff)
+#define IS_LOW_SURROGATE(u) ((UChar)(u) >= (UChar)0xdc00 && (UChar)(u) <= (UChar)0xdfff)
+
+static void utf16_to_utf8(const UChar* aText, gint aLength, char* &text, gint &length)
+{
+ gboolean need_copy = FALSE;
+ int i;
+
+ for (i = 0; i < aLength; i++) {
+ if (!aText[i] || IS_LOW_SURROGATE(aText[i])) {
+ need_copy = TRUE;
+ break;
+ }
+ else if (IS_HIGH_SURROGATE(aText[i])) {
+ if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
+ i++;
+ else {
+ need_copy = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (need_copy) {
+
+ /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
+ /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
+
+ UChar* p = (UChar*)g_memdup(aText, aLength * sizeof(aText[0]));
+
+ /* don't need to reset i */
+ for (i = 0; i < aLength; i++) {
+ if (!p[i] || IS_LOW_SURROGATE(p[i]))
+ p[i] = 0xFFFD;
+ else if (IS_HIGH_SURROGATE(p[i])) {
+ if (i < aLength - 1 && IS_LOW_SURROGATE(aText[i+1]))
+ i++;
+ else
+ p[i] = 0xFFFD;
+ }
+ }
+
+ aText = p;
+ }
+
+ glong items_written;
+ text = g_utf16_to_utf8(aText, aLength, NULL, &items_written, NULL);
+ length = items_written;
+
+ if (need_copy)
+ g_free((gpointer)aText);
+
+}
+
+static gchar* convertUniCharToUTF8(const UChar* characters, gint length, int from, int to)
+{
+ gchar* utf8 = 0;
+ gint new_length = 0;
+ utf16_to_utf8(characters, length, utf8, new_length);
+ if (!utf8)
+ return NULL;
+
+ if (from > 0) {
+ // discard the first 'from' characters
+ // FIXME: we should do this before the conversion probably
+ gchar* str_left = g_utf8_offset_to_pointer(utf8, from);
+ gchar* tmp = g_strdup(str_left);
+ g_free(utf8);
+ utf8 = tmp;
+ }
+
+ gchar* pos = utf8;
+ gint len = strlen(pos);
+ GString* ret = g_string_new_len(NULL, len);
+
+ // replace line break by space
+ while (len > 0) {
+ gint index, start;
+ pango_find_paragraph_boundary(pos, len, &index, &start);
+ g_string_append_len(ret, pos, index);
+ if (index == start)
+ break;
+ g_string_append_c(ret, ' ');
+ pos += start;
+ len -= start;
+ }
+ return g_string_free(ret, FALSE);
+}
+
+static void setPangoAttributes(const Font* font, const TextRun& run, PangoLayout* layout)
+{
+ PangoAttrList* list = pango_attr_list_new();
+ PangoAttribute* attr;
+
+ attr = pango_attr_size_new_absolute((int)(font->size() * PANGO_SCALE));
+ attr->end_index = G_MAXUINT;
+ pango_attr_list_insert_before(list, attr);
+
+ if (!run.spacingDisabled()) {
+ attr = pango_attr_letter_spacing_new(font->letterSpacing() * PANGO_SCALE);
+ attr->end_index = G_MAXUINT;
+ pango_attr_list_insert_before(list, attr);
+ }
+
+ // Pango does not yet support synthesising small caps
+ // See http://bugs.webkit.org/show_bug.cgi?id=15610
+
+ pango_layout_set_attributes(layout, list);
+ pango_attr_list_unref(list);
+
+ pango_layout_set_auto_dir(layout, FALSE);
+
+ PangoContext* pangoContext = pango_layout_get_context(layout);
+ PangoDirection direction = run.rtl() ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ pango_context_set_base_dir(pangoContext, direction);
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ cairo_t* cr = context->platformContext();
+ cairo_save(cr);
+
+ PangoLayout* layout = pango_cairo_create_layout(cr);
+
+ gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, to);
+ pango_layout_set_text(layout, utf8, -1);
+ g_free(utf8);
+
+ setPangoAttributes(this, run, layout);
+
+ // Set the text color to use for drawing.
+ float red, green, blue, alpha;
+ Color penColor = context->fillColor();
+ penColor.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(cr, red, green, blue, alpha);
+
+ // Our layouts are single line
+ cairo_move_to(cr, point.x(), point.y());
+ PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
+ pango_cairo_show_layout_line(cr, layoutLine);
+
+ g_object_unref(layout);
+ cairo_restore(cr);
+}
+
+// FIXME: we should create the layout with our actual context, but it seems
+// we can't access it from here
+static PangoLayout* getDefaultPangoLayout(const TextRun& run)
+{
+ PangoFontMap* map = pango_cairo_font_map_get_default();
+ PangoContext* pangoContext = pango_cairo_font_map_create_context(PANGO_CAIRO_FONT_MAP(map));
+ PangoLayout* layout = pango_layout_new(pangoContext);
+ g_object_unref(pangoContext);
+
+ return layout;
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ if (run.length() == 0)
+ return 0.0f;
+
+ PangoLayout* layout = getDefaultPangoLayout(run);
+ setPangoAttributes(this, run, layout);
+
+ gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
+ pango_layout_set_text(layout, utf8, -1);
+ g_free(utf8);
+
+ int layoutWidth;
+ pango_layout_get_size(layout, &layoutWidth, 0);
+ float width = (float)layoutWidth / (double)PANGO_SCALE;
+ g_object_unref(layout);
+
+ return width;
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+ PangoLayout* layout = getDefaultPangoLayout(run);
+ setPangoAttributes(this, run, layout);
+
+ gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
+ pango_layout_set_text(layout, utf8, -1);
+
+ int index, trailing;
+ pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing);
+ glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index);
+ g_free(utf8);
+ g_object_unref(layout);
+
+ return offset;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/FontPlatformData.h b/WebCore/platform/graphics/gtk/FontPlatformData.h
new file mode 100644
index 0000000..778d525
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/FontPlatformData.h
@@ -0,0 +1,80 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * 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 FontPlatformData_h
+#define FontPlatformData_h
+
+#include "GlyphBuffer.h"
+#include "FontDescription.h"
+#include <cairo.h>
+#include <cairo-ft.h>
+#include <fontconfig/fcfreetype.h>
+
+namespace WebCore {
+
+class FontPlatformData {
+public:
+ class Deleted {};
+ FontPlatformData(Deleted)
+ : m_pattern(reinterpret_cast<FcPattern*>(-1))
+ , m_scaledFont(0)
+ { }
+
+ FontPlatformData()
+ : m_pattern(0)
+ , m_scaledFont(0)
+ { }
+
+ FontPlatformData(const FontDescription&, const AtomicString& family);
+
+ FontPlatformData(float size, bool bold, bool italic);
+ FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic);
+
+ ~FontPlatformData();
+
+ static bool init();
+
+ bool isFixedPitch();
+ float size() const { return m_fontDescription.specifiedSize(); }
+
+ void setFont(cairo_t*) const;
+
+ unsigned hash() const
+ {
+ uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) };
+ return StringImpl::computeHash( reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
+ }
+
+ bool operator==(const FontPlatformData&) const;
+
+ FcPattern* m_pattern;
+ FontDescription m_fontDescription;
+ cairo_scaled_font_t* m_scaledFont;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
new file mode 100644
index 0000000..b28146f
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * 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 "FontPlatformData.h"
+
+#include "CString.h"
+#include "PlatformString.h"
+#include "FontDescription.h"
+
+#include <cairo-ft.h>
+#include <cairo.h>
+#include <fontconfig/fcfreetype.h>
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
+ : m_pattern(0)
+ , m_fontDescription(fontDescription)
+ , m_scaledFont(0)
+{
+ FontPlatformData::init();
+
+ CString familyNameString = familyName.string().utf8();
+ const char* fcfamily = familyNameString.data();
+ int fcslant = FC_SLANT_ROMAN;
+ int fcweight = FC_WEIGHT_NORMAL;
+ float fcsize = fontDescription.computedSize();
+ if (fontDescription.italic())
+ fcslant = FC_SLANT_ITALIC;
+ if (fontDescription.bold())
+ fcweight = FC_WEIGHT_BOLD;
+
+ int type = fontDescription.genericFamily();
+
+ FcPattern* pattern = FcPatternCreate();
+ cairo_font_face_t* fontFace;
+ static const cairo_font_options_t* defaultOptions = cairo_font_options_create();
+ const cairo_font_options_t* options = NULL;
+ cairo_matrix_t fontMatrix;
+
+ if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
+ goto freePattern;
+
+ switch (type) {
+ case FontDescription::SerifFamily:
+ fcfamily = "serif";
+ break;
+ case FontDescription::SansSerifFamily:
+ fcfamily = "sans-serif";
+ break;
+ case FontDescription::MonospaceFamily:
+ fcfamily = "monospace";
+ break;
+ case FontDescription::NoFamily:
+ case FontDescription::StandardFamily:
+ default:
+ fcfamily = "sans-serif";
+ }
+
+ if (!FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
+ goto freePattern;
+ if (!FcPatternAddInteger(pattern, FC_SLANT, fcslant))
+ goto freePattern;
+ if (!FcPatternAddInteger(pattern, FC_WEIGHT, fcweight))
+ goto freePattern;
+ if (!FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fcsize))
+ goto freePattern;
+
+ FcConfigSubstitute(NULL, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult fcresult;
+ m_pattern = FcFontMatch(NULL, pattern, &fcresult);
+ // FIXME: should we set some default font?
+ if (!m_pattern)
+ goto freePattern;
+ fontFace = cairo_ft_font_face_create_for_pattern(m_pattern);
+ cairo_matrix_t ctm;
+ cairo_matrix_init_scale(&fontMatrix, m_fontDescription.computedSize(), m_fontDescription.computedSize());
+ cairo_matrix_init_identity(&ctm);
+
+#if GTK_CHECK_VERSION(2,10,0)
+ if (GdkScreen* screen = gdk_screen_get_default())
+ options = gdk_screen_get_font_options(screen);
+#endif
+ // gdk_screen_get_font_options() returns NULL if no default options are
+ // set, so we always have to check.
+ if (!options)
+ options = defaultOptions;
+
+ m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
+ cairo_font_face_destroy(fontFace);
+
+freePattern:
+ FcPatternDestroy(pattern);
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
+ : m_pattern(0)
+ , m_fontDescription()
+ , m_scaledFont(0)
+{
+ m_fontDescription.setSpecifiedSize(size);
+ m_fontDescription.setBold(bold);
+ m_fontDescription.setItalic(italic);
+}
+
+FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic)
+ : m_pattern(0)
+ , m_fontDescription()
+ , m_scaledFont(0)
+{
+ m_fontDescription.setSpecifiedSize(size);
+ m_fontDescription.setBold(bold);
+ m_fontDescription.setItalic(italic);
+
+ cairo_matrix_t fontMatrix;
+ cairo_matrix_init_scale(&fontMatrix, size, size);
+ cairo_matrix_t ctm;
+ cairo_matrix_init_identity(&ctm);
+ cairo_font_options_t* options = cairo_font_options_create();
+
+ // We force antialiasing and disable hinting to provide consistent
+ // typographic qualities for custom fonts on all platforms.
+ cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
+
+ m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
+ cairo_font_options_destroy(options);
+}
+
+bool FontPlatformData::init()
+{
+ static bool initialized = false;
+ if (initialized)
+ return true;
+ if (!FcInit()) {
+ fprintf(stderr, "Can't init font config library\n");
+ return false;
+ }
+ initialized = true;
+ return true;
+}
+
+FontPlatformData::~FontPlatformData()
+{
+}
+
+bool FontPlatformData::isFixedPitch()
+{
+ // TODO: Support isFixedPitch() for custom fonts.
+ if (!m_pattern)
+ return false;
+
+ int spacing;
+ if (FcPatternGetInteger(m_pattern, FC_SPACING, 0, &spacing) == FcResultMatch)
+ return spacing == FC_MONO;
+ 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)
+ return true;
+ if (m_pattern == 0 || m_pattern == reinterpret_cast<FcPattern*>(-1)
+ || other.m_pattern == 0 || other.m_pattern == reinterpret_cast<FcPattern*>(-1))
+ return false;
+ return FcPatternEqual(m_pattern, other.m_pattern);
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp b/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp
new file mode 100644
index 0000000..24ad864
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+ *
+ * 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 "GlyphPageTreeNode.h"
+
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ // The bufferLength will be greater than the glyph page size if the buffer has Unicode supplementary characters.
+ // We won't support this for now.
+ if (bufferLength > GlyphPage::size)
+ return false;
+
+ FT_Face face = cairo_ft_scaled_font_lock_face(fontData->m_font.m_scaledFont);
+ if (!face)
+ return false;
+
+ bool haveGlyphs = false;
+ for (unsigned i = 0; i < length; i++) {
+ Glyph glyph = FcFreeTypeCharIndex(face, buffer[i]);
+ if (!glyph)
+ setGlyphDataForIndex(offset + i, 0, 0);
+ else {
+ setGlyphDataForIndex(offset + i, glyph, fontData);
+ haveGlyphs = true;
+ }
+ }
+
+ cairo_ft_scaled_font_unlock_face(fontData->m_font.m_scaledFont);
+
+ return haveGlyphs;
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp
new file mode 100644
index 0000000..a8e6536
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/IconGtk.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ *
+ * 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 "Icon.h"
+
+#include "CString.h"
+#include "GraphicsContext.h"
+#include "MIMETypeRegistry.h"
+#include "NotImplemented.h"
+#include "PassRefPtr.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+Icon::Icon()
+ : RefCounted<Icon>(0)
+ , m_icon(0)
+{
+ notImplemented();
+}
+
+Icon::~Icon()
+{
+ if(m_icon)
+ g_object_unref(m_icon);
+}
+
+static String lookupIconName(String MIMEType)
+{
+ /*
+ Lookup an appropriate icon according to either the Icon Naming Spec
+ or conventional Gnome icon names respectively.
+
+ See http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
+
+ The icon theme is probed for the following names:
+ 1. media-subtype
+ 2. gnome-mime-media-subtype
+ 3. media-x-generic
+ 4. gnome-mime-media
+
+ In the worst case it falls back to the stock file icon.
+ */
+ int pos = MIMEType.find('/');
+ if(pos >= 0) {
+ String media = MIMEType.substring(0, pos);
+ String subtype = MIMEType.substring(pos + 1);
+ GtkIconTheme* iconTheme = gtk_icon_theme_get_default();
+ String iconName = media + "-" + subtype;
+ if(gtk_icon_theme_has_icon(iconTheme, iconName.utf8().data()))
+ return iconName;
+ iconName = "gnome-mime-" + media + "-" + subtype;
+ if(gtk_icon_theme_has_icon(iconTheme, iconName.utf8().data()))
+ return iconName;
+ iconName = media + "-x-generic";
+ if(gtk_icon_theme_has_icon(iconTheme, iconName.utf8().data()))
+ return iconName;
+ iconName = media + "gnome-mime-" + media;
+ if(gtk_icon_theme_has_icon(iconTheme, iconName.utf8().data()))
+ return iconName;
+ }
+ return GTK_STOCK_FILE;
+}
+
+PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+{
+ if (!g_path_skip_root(filename.utf8().data()))
+ return 0;
+
+ String MIMEType = MIMETypeRegistry::getMIMETypeForPath(filename);
+ String iconName = lookupIconName(MIMEType);
+
+ Icon* icon = new Icon;
+ icon->m_icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), iconName.utf8().data(), 16, GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+ return icon->m_icon ? icon : 0;
+}
+
+void Icon::paint(GraphicsContext* context, const IntRect& rect)
+{
+ // TODO: Scale/clip the image if necessary.
+ cairo_t* cr = context->platformContext();
+ cairo_save(cr);
+ gdk_cairo_set_source_pixbuf(cr, m_icon, rect.x(), rect.y());
+ cairo_paint(cr);
+ cairo_restore(cr);
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp
new file mode 100644
index 0000000..a74bc54
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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"
+
+#include "BitmapImage.h"
+#include "Image.h"
+#include "NotImplemented.h"
+
+// This function loads resources from WebKit
+Vector<char> loadResourceIntoArray(const char*);
+
+namespace WebCore {
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+Image* Image::loadPlatformResource(const char *name)
+{
+ Vector<char> arr = loadResourceIntoArray(name);
+ BitmapImage* img = new BitmapImage;
+ RefPtr<SharedBuffer> buffer = new SharedBuffer(arr.data(), arr.size());
+ img->setData(buffer, true);
+ return img;
+}
+}
diff --git a/WebCore/platform/graphics/gtk/IntPointGtk.cpp b/WebCore/platform/graphics/gtk/IntPointGtk.cpp
new file mode 100644
index 0000000..c402158
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/IntPointGtk.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 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 "IntPoint.h"
+
+#include <gdk/gdk.h>
+
+namespace WebCore {
+
+IntPoint::IntPoint(const GdkPoint& p)
+ : m_x(p.x)
+ , m_y(p.y)
+{
+}
+
+IntPoint::operator GdkPoint() const
+{
+ GdkPoint p = { x(), y() };
+ return p;
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/gtk/IntRectGtk.cpp b/WebCore/platform/graphics/gtk/IntRectGtk.cpp
new file mode 100644
index 0000000..aaa1944
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/IntRectGtk.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 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 "IntRect.h"
+
+#include <gdk/gdk.h>
+
+namespace WebCore {
+
+IntRect::IntRect(const GdkRectangle& r)
+ : m_location(IntPoint(r.x, r.y))
+ , m_size(r.width, r.height)
+{
+}
+
+IntRect::operator GdkRectangle() const
+{
+ GdkRectangle r = { x(), y(), width(), height() };
+ return r;
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
new file mode 100644
index 0000000..c60bc20
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2007 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
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayerPrivateGStreamer.h"
+#include "VideoSinkGStreamer.h"
+
+#include "CString.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "KURL.h"
+#include "MIMETypeRegistry.h"
+#include "MediaPlayer.h"
+#include "NotImplemented.h"
+#include "ScrollView.h"
+#include "Widget.h"
+
+#include <gdk/gdkx.h>
+#include <gst/base/gstbasesrc.h>
+#include <gst/gst.h>
+#include <gst/interfaces/mixer.h>
+#include <gst/interfaces/xoverlay.h>
+#include <gst/video/video.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <limits>
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpointer data)
+{
+ if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ERROR)
+ {
+ GError* err;
+ gchar* debug;
+
+ gst_message_parse_error(message, &err, &debug);
+ 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);
+ g_error_free(err);
+ g_free(debug);
+ }
+ }
+ return true;
+}
+
+gboolean mediaPlayerPrivateEOSCallback(GstBus* bus, GstMessage* message, gpointer data)
+{
+ if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_EOS)
+ {
+ LOG_VERBOSE(Media, "End of Stream");
+ MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ mp->didEnd();
+ }
+ return true;
+}
+
+gboolean mediaPlayerPrivateStateCallback(GstBus* bus, GstMessage* message, gpointer data)
+{
+ if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_STATE_CHANGED)
+ {
+ MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data);
+ mp->updateStates();
+ }
+ return true;
+}
+
+gboolean mediaPlayerPrivateBufferingCallback(GstBus* bus, GstMessage* message, gpointer data)
+{
+ if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_BUFFERING)
+ {
+ gint percent = 0;
+ gst_message_parse_buffering(message, &percent);
+ LOG_VERBOSE(Media, "Buffering %d", percent);
+ }
+ return true;
+}
+
+MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
+ : m_player(player)
+ , m_playBin(0)
+ , m_videoSink(0)
+ , 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::DataUnavailable)
+ , m_startedPlaying(false)
+ , m_isStreaming(false)
+ , m_rect(IntRect())
+ , m_visible(true)
+{
+
+ static bool gstInitialized = false;
+ // FIXME: We should pass the arguments from the command line
+ if (!gstInitialized) {
+ gst_init(0, NULL);
+ gstInitialized = true;
+ }
+
+ // 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);
+}
+
+MediaPlayerPrivate::~MediaPlayerPrivate()
+{
+ if (m_surface)
+ cairo_surface_destroy(m_surface);
+
+ if (m_playBin) {
+ gst_element_set_state(m_playBin, GST_STATE_NULL);
+ gst_object_unref(GST_OBJECT(m_playBin));
+ }
+}
+
+void MediaPlayerPrivate::load(String url)
+{
+ LOG_VERBOSE(Media, "Load %s", url.utf8().data());
+ if (m_networkState != MediaPlayer::Loading) {
+ m_networkState = MediaPlayer::Loading;
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != MediaPlayer::DataUnavailable) {
+ m_readyState = MediaPlayer::DataUnavailable;
+ m_player->readyStateChanged();
+ }
+
+ createGSTPlayBin(url);
+ pause();
+}
+
+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()
+{
+ if (!m_playBin)
+ return 0.0;
+
+ GstFormat fmt = GST_FORMAT_TIME;
+ gint64 len = 0;
+
+ if (gst_element_query_duration(m_playBin, &fmt, &len))
+ LOG_VERBOSE(Media, "Duration: %" GST_TIME_FORMAT, GST_TIME_ARGS(len));
+ else
+ LOG_VERBOSE(Media, "Duration query failed ");
+
+ if ((GstClockTime)len == GST_CLOCK_TIME_NONE) {
+ m_isStreaming = true;
+ return numeric_limits<float>::infinity();
+ }
+ return (float) (len / 1000000000.0);
+ // FIXME: handle 3.14.9.5 properly
+}
+
+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;
+
+ GstQuery* query = gst_query_new_position(GST_FORMAT_TIME);
+ if (gst_element_query(m_playBin, query)) {
+ gint64 position;
+ gst_query_parse_position(query, NULL, &position);
+ ret = (float) (position / 1000000000.0);
+ LOG_VERBOSE(Media, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS(position));
+ } else {
+ LOG_VERBOSE(Media, "Position query failed...");
+ ret = 0.0;
+ }
+ gst_query_unref(query);
+
+ return ret;
+}
+
+void MediaPlayerPrivate::seek(float time)
+{
+ GstClockTime sec = (GstClockTime)(time * GST_SECOND);
+
+ if (!m_playBin)
+ return;
+
+ if (m_isStreaming)
+ 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);
+}
+
+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);
+ }
+}
+
+void MediaPlayerPrivate::startEndPointTimerIfNeeded()
+{
+ notImplemented();
+}
+
+void MediaPlayerPrivate::cancelSeek()
+{
+ notImplemented();
+}
+
+void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*)
+{
+ notImplemented();
+}
+
+bool MediaPlayerPrivate::paused() const
+{
+ return !m_startedPlaying;
+}
+
+bool MediaPlayerPrivate::seeking() const
+{
+ return false;
+}
+
+// Returns the size of the video
+IntSize MediaPlayerPrivate::naturalSize()
+{
+ if (!hasVideo())
+ return IntSize();
+
+ int x = 0, y = 0;
+ if (GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink")) {
+ gst_video_get_size(GST_PAD(pad), &x, &y);
+ gst_object_unref(GST_OBJECT(pad));
+ }
+
+ return IntSize(x, y);
+}
+
+bool MediaPlayerPrivate::hasVideo()
+{
+ gint currentVideo = -1;
+ if (m_playBin)
+ g_object_get(G_OBJECT(m_playBin), "current-video", &currentVideo, NULL);
+ return currentVideo > -1;
+}
+
+void MediaPlayerPrivate::setVolume(float volume)
+{
+ m_volume = volume;
+ LOG_VERBOSE(Media, "Volume to %f", volume);
+ setMuted(false);
+}
+
+void MediaPlayerPrivate::setMuted(bool b)
+{
+ 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);
+ }
+}
+
+void MediaPlayerPrivate::setRate(float rate)
+{
+ if (rate == 0.0) {
+ 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);
+}
+
+int MediaPlayerPrivate::dataRate() const
+{
+ notImplemented();
+ return 1;
+}
+
+MediaPlayer::NetworkState MediaPlayerPrivate::networkState()
+{
+ return m_networkState;
+}
+
+MediaPlayer::ReadyState MediaPlayerPrivate::readyState()
+{
+ return m_readyState;
+}
+
+float MediaPlayerPrivate::maxTimeBuffered()
+{
+ notImplemented();
+ LOG_VERBOSE(Media, "maxTimeBuffered");
+ // rtsp streams are not buffered
+ return m_isStreaming ? 0 : maxTimeLoaded();
+}
+
+float MediaPlayerPrivate::maxTimeSeekable()
+{
+ // TODO
+ LOG_VERBOSE(Media, "maxTimeSeekable");
+ if (m_isStreaming)
+ return numeric_limits<float>::infinity();
+ // infinite duration means live stream
+ return maxTimeLoaded();
+}
+
+float MediaPlayerPrivate::maxTimeLoaded()
+{
+ // TODO
+ LOG_VERBOSE(Media, "maxTimeLoaded");
+ notImplemented();
+ return duration();
+}
+
+unsigned MediaPlayerPrivate::bytesLoaded()
+{
+ notImplemented();
+ LOG_VERBOSE(Media, "bytesLoaded");
+ /*if (!m_playBin)
+ return 0;
+ float dur = duration();
+ float maxTime = maxTimeLoaded();
+ if (!dur)
+ return 0;*/
+ return 1;//totalBytes() * maxTime / dur;
+}
+
+bool MediaPlayerPrivate::totalBytesKnown()
+{
+ notImplemented();
+ LOG_VERBOSE(Media, "totalBytesKnown");
+ return totalBytes() > 0;
+}
+
+unsigned MediaPlayerPrivate::totalBytes()
+{
+ notImplemented();
+ LOG_VERBOSE(Media, "totalBytes");
+ if (!m_playBin)
+ return 0;
+
+ if (!m_source)
+ return 0;
+
+ // Do something with m_source to get the total bytes of the media
+
+ return 100;
+}
+
+void MediaPlayerPrivate::cancelLoad()
+{
+ notImplemented();
+}
+
+void MediaPlayerPrivate::updateStates()
+{
+ // There is no (known) way to get such level of information about
+ // the state of GStreamer, therefore, when in PAUSED state,
+ // we are sure we can display the first frame and go to play
+
+ 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);
+
+ switch(ret) {
+ case GST_STATE_CHANGE_SUCCESS:
+ LOG_VERBOSE(Media, "State: %s, pending: %s",
+ gst_element_state_get_name(state),
+ gst_element_state_get_name(pending));
+
+ if (state == GST_STATE_READY) {
+ m_readyState = MediaPlayer::CanPlayThrough;
+ } else if (state == GST_STATE_PAUSED) {
+ m_readyState = MediaPlayer::CanPlayThrough;
+ }
+ if (m_networkState < MediaPlayer::Loaded)
+ m_networkState = MediaPlayer::Loaded;
+
+ g_object_get(m_playBin, "source", &m_source, NULL);
+ if (!m_source)
+ LOG_VERBOSE(Media, "m_source is NULL");
+ break;
+ case GST_STATE_CHANGE_ASYNC:
+ LOG_VERBOSE(Media, "Async: State: %s, pending: %s",
+ gst_element_state_get_name(state),
+ gst_element_state_get_name(pending));
+ // Change in progress
+ return;
+ break;
+ 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::CanPlay;
+ } else if (state == GST_STATE_PAUSED) {
+ m_readyState = MediaPlayer::CanPlay;
+ }
+ if (m_networkState < MediaPlayer::LoadedMetaData)
+ m_networkState = MediaPlayer::LoadedMetaData;
+ break;
+ default:
+ LOG_VERBOSE(Media, "Else : %d", ret);
+ break;
+ }
+
+ if (seeking())
+ m_readyState = MediaPlayer::DataUnavailable;
+
+ if (m_networkState != oldNetworkState) {
+ LOG_VERBOSE(Media, "Network State Changed from %u to %u",
+ oldNetworkState, m_networkState);
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != oldReadyState) {
+ LOG_VERBOSE(Media, "Ready State Changed from %u to %u",
+ oldReadyState, m_readyState);
+ m_player->readyStateChanged();
+ }
+}
+
+void MediaPlayerPrivate::loadStateChanged()
+{
+ updateStates();
+}
+
+void MediaPlayerPrivate::rateChanged()
+{
+ updateStates();
+}
+
+void MediaPlayerPrivate::sizeChanged()
+{
+ notImplemented();
+}
+
+void MediaPlayerPrivate::timeChanged()
+{
+ updateStates();
+ m_player->timeChanged();
+}
+
+void MediaPlayerPrivate::volumeChanged()
+{
+ m_player->volumeChanged();
+}
+
+void MediaPlayerPrivate::didEnd()
+{
+ m_isEndReached = true;
+ pause();
+ timeChanged();
+}
+
+void MediaPlayerPrivate::loadingFailed()
+{
+ if (m_networkState != MediaPlayer::LoadFailed) {
+ m_networkState = MediaPlayer::LoadFailed;
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != MediaPlayer::DataUnavailable) {
+ m_readyState = MediaPlayer::DataUnavailable;
+ m_player->readyStateChanged();
+ }
+}
+
+void MediaPlayerPrivate::setRect(const IntRect& rect)
+{
+ m_rect = rect;
+}
+
+void MediaPlayerPrivate::setVisible(bool visible)
+{
+ m_visible = visible;
+}
+
+void MediaPlayerPrivate::repaint()
+{
+ m_player->repaint();
+}
+
+void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (context->paintingDisabled())
+ return;
+
+ if (!m_visible)
+ return;
+
+ //TODO: m_rect vs rect?
+ cairo_t* cr = context->platformContext();
+
+ cairo_save(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ 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);
+ cairo_fill(cr);
+ cairo_restore(cr);
+}
+
+void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
+{
+ // FIXME: do the real thing
+ notImplemented();
+ types.add(String("video/x-theora+ogg"));
+}
+
+void MediaPlayerPrivate::createGSTPlayBin(String url)
+{
+ ASSERT(!m_playBin);
+ m_playBin = gst_element_factory_make("playbin", "play");
+
+ GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(m_playBin));
+ gst_bus_add_signal_watch(bus);
+ g_signal_connect(bus, "message::error", G_CALLBACK(mediaPlayerPrivateErrorCallback), this);
+ g_signal_connect(bus, "message::eos", G_CALLBACK(mediaPlayerPrivateEOSCallback), this);
+ g_signal_connect(bus, "message::state-changed", G_CALLBACK(mediaPlayerPrivateStateCallback), this);
+ g_signal_connect(bus, "message::buffering", G_CALLBACK(mediaPlayerPrivateBufferingCallback), this);
+ gst_object_unref(bus);
+
+ g_object_set(G_OBJECT(m_playBin), "uri", url.utf8().data(), NULL);
+
+ GstElement* audioSink = gst_element_factory_make("gconfaudiosink", NULL);
+ m_videoSink = webkit_video_sink_new(m_surface);
+
+ g_object_set(m_playBin, "audio-sink", audioSink, NULL);
+ g_object_set(m_playBin, "video-sink", m_videoSink, NULL);
+
+ setVolume(m_volume);
+}
+
+}
+
+#endif
+
diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
new file mode 100644
index 0000000..3f08bc0
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Collabora Ltd. All rights reserved.
+ * Copyright (C) 2007 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
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef MediaPlayerPrivateGStreamer_h
+#define MediaPlayerPrivateGStreamer_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayer.h"
+#include "Timer.h"
+
+#include <gtk/gtk.h>
+
+typedef struct _GstElement GstElement;
+typedef struct _GstMessage GstMessage;
+typedef struct _GstBus GstBus;
+
+namespace WebCore {
+
+ class GraphicsContext;
+ class IntSize;
+ class IntRect;
+ class String;
+
+ gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpointer data);
+ gboolean mediaPlayerPrivateEOSCallback(GstBus* bus, GstMessage* message, gpointer data);
+ gboolean mediaPlayerPrivateStateCallback(GstBus* bus, GstMessage* message, gpointer data);
+
+ class MediaPlayerPrivate : Noncopyable
+ {
+ friend gboolean mediaPlayerPrivateErrorCallback(GstBus* bus, GstMessage* message, gpointer data);
+ friend gboolean mediaPlayerPrivateEOSCallback(GstBus* bus, GstMessage* message, gpointer data);
+ friend gboolean mediaPlayerPrivateStateCallback(GstBus* bus, GstMessage* message, gpointer data);
+
+ public:
+ MediaPlayerPrivate(MediaPlayer*);
+ ~MediaPlayerPrivate();
+
+ IntSize naturalSize();
+ bool hasVideo();
+
+ void load(String url);
+ void cancelLoad();
+
+ void play();
+ void pause();
+
+ bool paused() const;
+ bool seeking() const;
+
+ float duration();
+ float currentTime() const;
+ void seek(float);
+ void setEndTime(float);
+
+ void setRate(float);
+ void setVolume(float);
+ void setMuted(bool);
+
+ int dataRate() const;
+
+ MediaPlayer::NetworkState networkState();
+ MediaPlayer::ReadyState readyState();
+
+ float maxTimeBuffered();
+ float maxTimeSeekable();
+ unsigned bytesLoaded();
+ bool totalBytesKnown();
+ unsigned totalBytes();
+
+ void setVisible(bool);
+ void setRect(const IntRect&);
+
+ void loadStateChanged();
+ void rateChanged();
+ void sizeChanged();
+ void timeChanged();
+ void volumeChanged();
+ void didEnd();
+ void loadingFailed();
+
+ void repaint();
+ void paint(GraphicsContext*, const IntRect&);
+ static void getSupportedTypes(HashSet<String>&);
+ static bool isAvailable() { return true; }
+
+ private:
+
+ void updateStates();
+ void cancelSeek();
+ void endPointTimerFired(Timer<MediaPlayerPrivate>*);
+ float maxTimeLoaded();
+ void startEndPointTimerIfNeeded();
+
+ void createGSTPlayBin(String url);
+
+ private:
+ MediaPlayer* m_player;
+ GstElement* m_playBin;
+ GstElement* m_videoSink;
+ GstElement* m_source;
+ float m_rate;
+ float m_endTime;
+ bool m_isEndReached;
+ double m_volume;
+ MediaPlayer::NetworkState m_networkState;
+ MediaPlayer::ReadyState m_readyState;
+ bool m_startedPlaying;
+ bool m_isStreaming;
+ IntRect m_rect;
+ bool m_visible;
+ cairo_surface_t* m_surface;
+ };
+}
+
+#endif
+#endif
diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
new file mode 100644
index 0000000..a754c45
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * 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 "Font.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "GlyphBuffer.h"
+#include <cairo.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+void SimpleFontData::platformInit()
+{
+ cairo_font_extents_t font_extents;
+ cairo_text_extents_t text_extents;
+ cairo_scaled_font_extents(m_font.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);
+ cairo_scaled_font_text_extents(m_font.m_scaledFont, "x", &text_extents);
+ m_xHeight = text_extents.height;
+ cairo_scaled_font_text_extents(m_font.m_scaledFont, " ", &text_extents);
+ m_spaceWidth = static_cast<int>(text_extents.x_advance);
+ m_lineGap = m_lineSpacing - m_ascent - m_descent;
+}
+
+void SimpleFontData::platformDestroy()
+{
+ if (!isCustomFont()) {
+ if (m_font.m_pattern && ((FcPattern*)-1 != m_font.m_pattern)) {
+ FcPatternDestroy(m_font.m_pattern);
+ m_font.m_pattern = 0;
+ }
+
+ if (m_font.m_scaledFont) {
+ cairo_scaled_font_destroy(m_font.m_scaledFont);
+ m_font.m_scaledFont = 0;
+ }
+ }
+
+ delete m_smallCapsFontData;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(0.70f*fontDescription.computedSize());
+ const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family());
+ m_smallCapsFontData = new SimpleFontData(*pdata);
+ }
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ FT_Face face = cairo_ft_scaled_font_lock_face(m_font.m_scaledFont);
+
+ if (!face)
+ return false;
+
+ for (unsigned i = 0; i < length; i++) {
+ if (FcFreeTypeCharIndex(face, characters[i]) == 0) {
+ cairo_ft_scaled_font_unlock_face(m_font.m_scaledFont);
+ return false;
+ }
+ }
+
+ cairo_ft_scaled_font_unlock_face(m_font.m_scaledFont);
+
+ return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+ m_treatAsFixedPitch = m_font.isFixedPitch();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ ASSERT(m_font.m_scaledFont);
+
+ cairo_glyph_t cglyph = { glyph, 0, 0 };
+ cairo_text_extents_t extents;
+ cairo_scaled_font_glyph_extents(m_font.m_scaledFont, &cglyph, 1, &extents);
+
+ float w = (float)m_spaceWidth;
+ if (cairo_scaled_font_status(m_font.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0)
+ w = (float)extents.x_advance;
+ return w;
+}
+
+void SimpleFontData::setFont(cairo_t* cr) const
+{
+ ASSERT(cr);
+ m_font.setFont(cr);
+}
+
+}
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
new file mode 100644
index 0000000..7e97688
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2007 OpenedHand
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * 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
+ */
+
+/**
+ * SECTION:webkit-video-sink
+ * @short_description: GStreamer video sink
+ *
+ * #WebKitVideoSink is a GStreamer sink element that sends
+ * data to a #cairo_surface_t.
+ */
+
+#include "config.h"
+#include "VideoSinkGStreamer.h"
+
+#include <glib.h>
+#include <gst/gst.h>
+#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_DEBUG_CATEGORY_STATIC(webkit_video_sink_debug);
+#define GST_CAT_DEFAULT webkit_video_sink_debug
+
+static GstElementDetails webkit_video_sink_details =
+ GST_ELEMENT_DETAILS("WebKit video sink",
+ "Sink/Video",
+ "Sends video data from a GStreamer pipeline to a Cairo surface",
+ "Alp Toker <alp@atoker.com>");
+
+enum {
+ PROP_0,
+ PROP_SURFACE
+};
+
+struct _WebKitVideoSinkPrivate {
+ cairo_surface_t* surface;
+ GAsyncQueue* async_queue;
+ gboolean rgb_ordering;
+ int width;
+ int height;
+ int fps_n;
+ int fps_d;
+ int par_n;
+ int par_d;
+};
+
+#define _do_init(bla) \
+ GST_DEBUG_CATEGORY_INIT (webkit_video_sink_debug, \
+ "webkitsink", \
+ 0, \
+ "webkit video sink")
+
+GST_BOILERPLATE_FULL(WebKitVideoSink,
+ webkit_video_sink,
+ GstBaseSink,
+ GST_TYPE_BASE_SINK,
+ _do_init);
+
+static void
+webkit_video_sink_base_init(gpointer g_class)
+{
+ GstElementClass* element_class = GST_ELEMENT_CLASS(g_class);
+
+ gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinktemplate));
+ gst_element_class_set_details(element_class, &webkit_video_sink_details);
+}
+
+static void
+webkit_video_sink_init(WebKitVideoSink* sink, WebKitVideoSinkClass* klass)
+{
+ WebKitVideoSinkPrivate* priv;
+
+ sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate);
+ priv->async_queue = g_async_queue_new();
+}
+
+static gboolean
+webkit_video_sink_idle_func(gpointer data)
+{
+ WebKitVideoSinkPrivate* priv;
+ GstBuffer* buffer;
+
+ priv = (WebKitVideoSinkPrivate*)data;
+
+ if (!priv->async_queue)
+ return FALSE;
+
+ buffer = (GstBuffer*)g_async_queue_try_pop(priv->async_queue);
+ if (buffer == NULL || G_UNLIKELY(!GST_IS_BUFFER(buffer)))
+ return FALSE;
+
+ // 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);
+
+ // TODO: We copy the data twice right now. This could be easily improved.
+ cairo_t* cr = cairo_create(priv->surface);
+ 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);
+
+ return FALSE;
+}
+
+static GstFlowReturn
+webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer)
+{
+ WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(bsink);
+ WebKitVideoSinkPrivate* priv = sink->priv;
+
+ g_async_queue_push(priv->async_queue, gst_buffer_ref(buffer));
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, webkit_video_sink_idle_func, priv, NULL);
+
+ return GST_FLOW_OK;
+}
+
+static gboolean
+webkit_video_sink_set_caps(GstBaseSink* bsink, GstCaps* caps)
+{
+ WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(bsink);
+ WebKitVideoSinkPrivate* priv = sink->priv;
+ GstStructure* structure;
+ gboolean ret;
+ const GValue* fps;
+ const GValue* par;
+ gint width, height;
+ int red_mask;
+
+ GstCaps* intersection = gst_caps_intersect(gst_static_pad_template_get_caps(&sinktemplate), caps);
+
+ if (gst_caps_is_empty(intersection))
+ return FALSE;
+
+ gst_caps_unref(intersection);
+
+ structure = gst_caps_get_structure(caps, 0);
+
+ 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 != NULL);
+
+ par = gst_structure_get_value(structure, "pixel-aspect-ratio");
+
+ if (!ret)
+ return FALSE;
+
+ priv->width = width;
+ priv->height = height;
+
+ /* 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
+ priv->par_n = priv->par_d = 1;
+
+ gst_structure_get_int(structure, "red_mask", &red_mask);
+ priv->rgb_ordering = (red_mask == 0xff000000);
+
+ return TRUE;
+}
+
+static void
+webkit_video_sink_dispose(GObject* object)
+{
+ WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
+ WebKitVideoSinkPrivate* priv = sink->priv;
+
+ if (priv->surface) {
+ cairo_surface_destroy(priv->surface);
+ priv->surface = NULL;
+ }
+
+ if (priv->async_queue) {
+ g_async_queue_unref(priv->async_queue);
+ priv->async_queue = NULL;
+ }
+
+ G_OBJECT_CLASS(parent_class)->dispose(object);
+}
+
+static void
+webkit_video_sink_finalize(GObject* object)
+{
+ WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
+
+ G_OBJECT_CLASS(parent_class)->finalize(object);
+}
+
+static void
+webkit_video_sink_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
+{
+ WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
+ WebKitVideoSinkPrivate* priv = sink->priv;
+
+ switch (prop_id) {
+ case PROP_SURFACE:
+ if (priv->surface)
+ cairo_surface_destroy(priv->surface);
+ priv->surface = cairo_surface_reference((cairo_surface_t*)g_value_get_pointer(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+webkit_video_sink_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
+{
+ WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(object);
+
+ switch (prop_id) {
+ case PROP_SURFACE:
+ g_value_set_pointer(value, sink->priv->surface);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+webkit_video_sink_stop(GstBaseSink* base_sink)
+{
+ WebKitVideoSinkPrivate* priv = WEBKIT_VIDEO_SINK(base_sink)->priv;
+
+ g_async_queue_lock(priv->async_queue);
+
+ /* Remove all remaining objects from the queue */
+ while(GstBuffer* buffer = (GstBuffer*)g_async_queue_try_pop_unlocked(priv->async_queue))
+ gst_buffer_unref(buffer);
+
+ g_async_queue_unlock(priv->async_queue);
+
+ return TRUE;
+}
+
+static void
+webkit_video_sink_class_init(WebKitVideoSinkClass* klass)
+{
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ GstBaseSinkClass* gstbase_sink_class = GST_BASE_SINK_CLASS(klass);
+
+ g_type_class_add_private(klass, sizeof(WebKitVideoSinkPrivate));
+
+ gobject_class->set_property = webkit_video_sink_set_property;
+ gobject_class->get_property = webkit_video_sink_get_property;
+
+ gobject_class->dispose = webkit_video_sink_dispose;
+ gobject_class->finalize = webkit_video_sink_finalize;
+
+ gstbase_sink_class->render = webkit_video_sink_render;
+ gstbase_sink_class->preroll = webkit_video_sink_render;
+ gstbase_sink_class->stop = webkit_video_sink_stop;
+ gstbase_sink_class->set_caps = webkit_video_sink_set_caps;
+
+ g_object_class_install_property(
+ gobject_class, PROP_SURFACE,
+ g_param_spec_pointer("surface", "surface", "Target cairo_surface_t*",
+ (GParamFlags)(G_PARAM_READWRITE)));
+}
+
+/**
+ * webkit_video_sink_new:
+ * @surface: a #cairo_surface_t
+ *
+ * Creates a new GStreamer video sink which uses @surface as the target
+ * for sinking a video stream from GStreamer.
+ *
+ * Return value: a #GstElement for the newly created video sink
+ */
+GstElement*
+webkit_video_sink_new(cairo_surface_t* surface)
+{
+ return (GstElement*)g_object_new(WEBKIT_TYPE_VIDEO_SINK, "surface", surface, NULL);
+}
+
+void
+webkit_video_sink_set_surface(WebKitVideoSink* sink, cairo_surface_t* surface)
+{
+ WebKitVideoSinkPrivate* priv;
+
+ sink->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE(sink, WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkPrivate);
+ if (priv->surface)
+ cairo_surface_destroy(priv->surface);
+ priv->surface = cairo_surface_reference(surface);
+}
diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h
new file mode 100644
index 0000000..2a706fb
--- /dev/null
+++ b/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2007 OpenedHand
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ *
+ * 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 _HAVE_WEBKIT_VIDEO_SINK_H
+#define _HAVE_WEBKIT_VIDEO_SINK_H
+
+#include <cairo.h>
+#include <glib-object.h>
+#include <gst/base/gstbasesink.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_VIDEO_SINK webkit_video_sink_get_type()
+
+#define WEBKIT_VIDEO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSink))
+
+#define WEBKIT_VIDEO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkClass))
+
+#define WEBKIT_IS_VIDEO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ WEBKIT_TYPE_VIDEO_SINK))
+
+#define WEBKIT_IS_VIDEO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ WEBKIT_TYPE_VIDEO_SINK))
+
+#define WEBKIT_VIDEO_SINK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ WEBKIT_TYPE_VIDEO_SINK, WebKitVideoSinkClass))
+
+typedef struct _WebKitVideoSink WebKitVideoSink;
+typedef struct _WebKitVideoSinkClass WebKitVideoSinkClass;
+typedef struct _WebKitVideoSinkPrivate WebKitVideoSinkPrivate;
+
+struct _WebKitVideoSink
+{
+ /*< private >*/
+ GstBaseSink parent;
+ WebKitVideoSinkPrivate *priv;
+};
+
+struct _WebKitVideoSinkClass
+{
+ /*< private >*/
+ GstBaseSinkClass parent_class;
+
+ /* Future padding */
+ void (* _webkit_reserved1) (void);
+ void (* _webkit_reserved2) (void);
+ void (* _webkit_reserved3) (void);
+ void (* _webkit_reserved4) (void);
+ void (* _webkit_reserved5) (void);
+ void (* _webkit_reserved6) (void);
+};
+
+GType webkit_video_sink_get_type (void) G_GNUC_CONST;
+GstElement *webkit_video_sink_new (cairo_surface_t *surface);
+
+void webkit_video_sink_set_surface (WebKitVideoSink *sink, cairo_surface_t *surface);
+
+G_END_DECLS
+
+#endif
diff --git a/WebCore/platform/graphics/mac/ColorMac.h b/WebCore/platform/graphics/mac/ColorMac.h
new file mode 100644
index 0000000..3be9094
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ColorMac.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 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.
+ * 3. Neither the name of Apple 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 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 ColorMac_h
+#define ColorMac_h
+
+#include "Color.h"
+
+#ifdef __OBJC__
+@class NSColor;
+#else
+class NSColor;
+#endif
+
+namespace WebCore {
+
+ Color colorFromNSColor(NSColor *);
+ NSColor* nsColor(const Color&);
+
+ bool usesTestModeFocusRingColor();
+ void setUsesTestModeFocusRingColor(bool);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/mac/ColorMac.mm b/WebCore/platform/graphics/mac/ColorMac.mm
new file mode 100644
index 0000000..5c89715
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ColorMac.mm
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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.
+ */
+
+#import "config.h"
+#import "Color.h"
+#import "ColorMac.h"
+
+#import <wtf/Assertions.h>
+#import <wtf/RetainPtr.h>
+
+@interface WebCoreControlTintObserver : NSObject
++ (void)controlTintDidChange;
+@end
+
+namespace WebCore {
+
+// NSColor calls don't throw, so no need to block Cocoa exceptions in this file
+
+static RGBA32 oldAquaFocusRingColor = 0xFF7DADD9;
+static bool tintIsKnown;
+static void (*tintChangeFunction)();
+static RGBA32 systemFocusRingColor;
+static bool useOldAquaFocusRingColor;
+
+
+static RGBA32 makeRGBAFromNSColor(NSColor *c)
+{
+ return makeRGBA((int)(255 * [c redComponent]), (int)(255 * [c greenComponent]), (int)(255 * [c blueComponent]), (int)(255 * [c alphaComponent]));
+}
+
+Color colorFromNSColor(NSColor *c)
+{
+ return Color(makeRGBAFromNSColor(c));
+}
+
+NSColor* nsColor(const Color& color)
+{
+ unsigned c = color.rgb();
+ switch (c) {
+ case 0: {
+ // Need this to avoid returning nil because cachedRGBAValues will default to 0.
+ static RetainPtr<NSColor> clearColor = [NSColor clearColor];
+ return clearColor.get();
+ }
+ case Color::black: {
+ static RetainPtr<NSColor> blackColor = [NSColor blackColor];
+ return blackColor.get();
+ }
+ case Color::white: {
+ static RetainPtr<NSColor> whiteColor = [NSColor whiteColor];
+ return whiteColor.get();
+ }
+ default: {
+ const int cacheSize = 32;
+ static unsigned cachedRGBAValues[cacheSize];
+ static RetainPtr<NSColor> cachedColors[cacheSize];
+
+ for (int i = 0; i != cacheSize; ++i)
+ if (cachedRGBAValues[i] == c)
+ return cachedColors[i].get();
+
+#ifdef COLORMATCH_EVERYTHING
+ NSColor* result = [NSColor colorWithCalibratedRed:color.red() / 255.0f
+ green:color.green() / 255.0f
+ blue:color.blue() / 255.0f
+ alpha:color.alpha() /255.0f];
+#else
+ NSColor* result = [NSColor colorWithDeviceRed:color.red() / 255.0f
+ green:color.green() / 255.0f
+ blue:color.blue() / 255.0f
+ alpha:color.alpha() /255.0f];
+#endif
+
+ static int cursor;
+ cachedRGBAValues[cursor] = c;
+ cachedColors[cursor] = result;
+ if (++cursor == cacheSize)
+ cursor = 0;
+ return result;
+ }
+ }
+}
+
+static CGColorRef CGColorFromNSColor(NSColor* color)
+{
+ // This needs to always use device colorspace so it can de-calibrate the color for
+ // CGColor to possibly recalibrate it.
+ NSColor* deviceColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ CGFloat red = [deviceColor redComponent];
+ CGFloat green = [deviceColor greenComponent];
+ CGFloat blue = [deviceColor blueComponent];
+ CGFloat alpha = [deviceColor alphaComponent];
+ const CGFloat components[4] = { red, green, blue, alpha };
+ static CGColorSpaceRef deviceRGBColorSpace = CGColorSpaceCreateDeviceRGB();
+ CGColorRef cgColor = CGColorCreate(deviceRGBColorSpace, components);
+ return cgColor;
+}
+
+CGColorRef cgColor(const Color& c)
+{
+ // We could directly create a CGColor here, but that would
+ // skip any RGB caching the nsColor method does. A direct
+ // creation could be investigated for a possible performance win.
+ return CGColorFromNSColor(nsColor(c));
+}
+
+static void observeTint()
+{
+ ASSERT(!tintIsKnown);
+ [[NSNotificationCenter defaultCenter] addObserver:[WebCoreControlTintObserver class]
+ selector:@selector(controlTintDidChange)
+ name:NSControlTintDidChangeNotification
+ object:NSApp];
+ [WebCoreControlTintObserver controlTintDidChange];
+ tintIsKnown = true;
+}
+
+void setFocusRingColorChangeFunction(void (*function)())
+{
+ ASSERT(!tintChangeFunction);
+ tintChangeFunction = function;
+ if (!tintIsKnown)
+ observeTint();
+}
+
+Color focusRingColor()
+{
+ if (!tintIsKnown)
+ observeTint();
+
+ if (usesTestModeFocusRingColor())
+ return oldAquaFocusRingColor;
+
+ return systemFocusRingColor;
+}
+
+bool usesTestModeFocusRingColor()
+{
+ return useOldAquaFocusRingColor;
+}
+
+void setUsesTestModeFocusRingColor(bool newValue)
+{
+ useOldAquaFocusRingColor = newValue;
+}
+
+}
+
+@implementation WebCoreControlTintObserver
+
++ (void)controlTintDidChange
+{
+#ifdef COLORMATCH_EVERYTHING
+#error Not yet implemented.
+#else
+ NSColor* color = [[NSColor keyboardFocusIndicatorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ WebCore::systemFocusRingColor = WebCore::makeRGBAFromNSColor(color);
+#endif
+}
+
+@end
diff --git a/WebCore/platform/graphics/mac/FloatPointMac.mm b/WebCore/platform/graphics/mac/FloatPointMac.mm
new file mode 100644
index 0000000..2f73314
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FloatPointMac.mm
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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"
+
+namespace WebCore {
+
+#ifndef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+
+FloatPoint::FloatPoint(const NSPoint& p) : m_x(p.x), m_y(p.y)
+{
+}
+
+FloatPoint::operator NSPoint() const
+{
+ return NSMakePoint(m_x, m_y);
+}
+
+#endif
+
+}
diff --git a/WebCore/platform/graphics/mac/FloatRectMac.mm b/WebCore/platform/graphics/mac/FloatRectMac.mm
new file mode 100644
index 0000000..1d6b045
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FloatRectMac.mm
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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"
+
+namespace WebCore {
+
+#ifndef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+
+FloatRect::FloatRect(const NSRect& r) : m_location(r.origin), m_size(r.size)
+{
+}
+
+FloatRect::operator NSRect() const
+{
+ return NSMakeRect(x(), y(), width(), height());
+}
+
+#endif
+
+}
diff --git a/WebCore/platform/graphics/mac/FloatSizeMac.mm b/WebCore/platform/graphics/mac/FloatSizeMac.mm
new file mode 100644
index 0000000..01efbe9
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FloatSizeMac.mm
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005 Nokia. 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 "FloatSize.h"
+
+namespace WebCore {
+
+#ifndef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+
+FloatSize::FloatSize(const NSSize& s) : m_width(s.width), m_height(s.height)
+{
+}
+
+FloatSize::operator NSSize() const
+{
+ return NSMakeSize(m_width, m_height);
+}
+
+#endif
+
+}
diff --git a/WebCore/platform/graphics/mac/FontCacheMac.mm b/WebCore/platform/graphics/mac/FontCacheMac.mm
new file mode 100644
index 0000000..ffb3068
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontCacheMac.mm
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+#import "config.h"
+#import "FontCache.h"
+
+#import "Font.h"
+#import "SimpleFontData.h"
+#import "FontPlatformData.h"
+#import "WebCoreSystemInterface.h"
+#import "WebFontCache.h"
+
+#ifdef BUILDING_ON_TIGER
+typedef int NSInteger;
+#endif
+
+namespace WebCore {
+
+static bool getAppDefaultValue(CFStringRef key, int *v)
+{
+ CFPropertyListRef value;
+
+ value = CFPreferencesCopyValue(key, kCFPreferencesCurrentApplication,
+ kCFPreferencesAnyUser,
+ kCFPreferencesAnyHost);
+ if (value == 0) {
+ value = CFPreferencesCopyValue(key, kCFPreferencesCurrentApplication,
+ kCFPreferencesCurrentUser,
+ kCFPreferencesAnyHost);
+ if (value == 0)
+ return false;
+ }
+
+ if (CFGetTypeID(value) == CFNumberGetTypeID()) {
+ if (v != 0)
+ CFNumberGetValue((const CFNumberRef)value, kCFNumberIntType, v);
+ } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
+ if (v != 0)
+ *v = CFStringGetIntValue((const CFStringRef)value);
+ } else {
+ CFRelease(value);
+ return false;
+ }
+
+ CFRelease(value);
+ return true;
+}
+
+static bool getUserDefaultValue(CFStringRef key, int *v)
+{
+ CFPropertyListRef value;
+
+ value = CFPreferencesCopyValue(key, kCFPreferencesAnyApplication,
+ kCFPreferencesCurrentUser,
+ kCFPreferencesCurrentHost);
+ if (value == 0)
+ return false;
+
+ if (CFGetTypeID(value) == CFNumberGetTypeID()) {
+ if (v != 0)
+ CFNumberGetValue((const CFNumberRef)value, kCFNumberIntType, v);
+ } else if (CFGetTypeID(value) == CFStringGetTypeID()) {
+ if (v != 0)
+ *v = CFStringGetIntValue((const CFStringRef)value);
+ } else {
+ CFRelease(value);
+ return false;
+ }
+
+ CFRelease(value);
+ return true;
+}
+
+static int getLCDScaleParameters(void)
+{
+ int mode;
+ CFStringRef key;
+
+ key = CFSTR("AppleFontSmoothing");
+ if (!getAppDefaultValue(key, &mode)) {
+ if (!getUserDefaultValue(key, &mode))
+ return 1;
+ }
+
+ if (wkFontSmoothingModeIsLCD(mode))
+ return 4;
+ return 1;
+}
+
+#define MINIMUM_GLYPH_CACHE_SIZE 1536 * 1024
+
+void FontCache::platformInit()
+{
+ size_t s = MINIMUM_GLYPH_CACHE_SIZE*getLCDScaleParameters();
+
+ wkSetUpFontCache(s);
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ const FontPlatformData& platformData = font.fontDataAt(0)->fontDataForCharacter(characters[0])->platformData();
+ NSFont *nsFont = platformData.font();
+
+ NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<UChar*>(characters)
+ length:length freeWhenDone:NO];
+ NSFont *substituteFont = wkGetFontInLanguageForRange(nsFont, string, NSMakeRange(0, length));
+ [string release];
+
+ if (!substituteFont && length == 1)
+ substituteFont = wkGetFontInLanguageForCharacter(nsFont, characters[0]);
+ if (!substituteFont)
+ return 0;
+
+ // Use the family name from the AppKit-supplied substitute font, requesting the
+ // traits, weight, and size we want. One way this does better than the original
+ // AppKit request is that it takes synthetic bold and oblique into account.
+ // But it does create the possibility that we could end up with a font that
+ // doesn't actually cover the characters we need.
+
+ NSFontManager *manager = [NSFontManager sharedFontManager];
+
+ NSFontTraitMask traits;
+ NSInteger weight;
+ CGFloat size;
+
+ if (nsFont) {
+ traits = [manager traitsOfFont:nsFont];
+ if (platformData.m_syntheticBold)
+ traits |= NSBoldFontMask;
+ if (platformData.m_syntheticOblique)
+ traits |= NSItalicFontMask;
+ weight = [manager weightOfFont:nsFont];
+ size = [nsFont pointSize];
+ } else {
+ // For custom fonts nsFont is nil.
+ traits = (font.bold() ? NSBoldFontMask : 0) | (font.italic() ? NSItalicFontMask : 0);
+ weight = 5;
+ size = font.pixelSize();
+ }
+
+ NSFont *bestVariation = [manager fontWithFamily:[substituteFont familyName]
+ traits:traits
+ weight:weight
+ size:size];
+ if (bestVariation)
+ substituteFont = bestVariation;
+
+ substituteFont = font.fontDescription().usePrinterFont()
+ ? [substituteFont printerFont] : [substituteFont screenFont];
+
+ NSFontTraitMask substituteFontTraits = [manager traitsOfFont:substituteFont];
+
+ FontPlatformData alternateFont(substituteFont,
+ !font.isPlatformFont() && (traits & NSBoldFontMask) && !(substituteFontTraits & NSBoldFontMask),
+ !font.isPlatformFont() && (traits & NSItalicFontMask) && !(substituteFontTraits & NSItalicFontMask));
+ return getCachedFontData(&alternateFont);
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ // Attempt to find an appropriate font using a match based on
+ // the presence of keywords in the the requested names. For example, we'll
+ // match any name that contains "Arabic" to Geeza Pro.
+ FontPlatformData* platformData = 0;
+ const FontFamily* currFamily = &font.fontDescription().family();
+ while (currFamily && !platformData) {
+ if (currFamily->family().length()) {
+ static String matchWords[3] = { String("Arabic"), String("Pashto"), String("Urdu") };
+ static AtomicString geezaStr("Geeza Pro");
+ for (int j = 0; j < 3 && !platformData; ++j)
+ if (currFamily->family().contains(matchWords[j], false))
+ platformData = getCachedFontPlatformData(font.fontDescription(), geezaStr);
+ }
+ currFamily = currFamily->next();
+ }
+
+ return platformData;
+}
+
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
+{
+ static AtomicString timesStr("Times");
+ static AtomicString lucidaGrandeStr("Lucida Grande");
+
+ // 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.
+ FontPlatformData* platformFont = getCachedFontPlatformData(fontDescription, timesStr);
+ if (!platformFont)
+ // The Times fallback will almost always work, but in the highly unusual case where
+ // the user doesn't have it, we fall back on Lucida Grande because that's
+ // guaranteed to be there, according to Nathan Taylor. This is good enough
+ // to avoid a crash at least.
+ platformFont = getCachedFontPlatformData(fontDescription, lucidaGrandeStr);
+
+ return platformFont;
+}
+
+bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicString& family)
+{
+ NSFontTraitMask traits = 0;
+ if (fontDescription.italic())
+ traits |= NSItalicFontMask;
+ if (fontDescription.bold())
+ traits |= NSBoldFontMask;
+ float size = fontDescription.computedPixelSize();
+
+ NSFont* nsFont = [WebFontCache fontWithFamily:family traits:traits size:size];
+ return nsFont != 0;
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ NSFontTraitMask traits = 0;
+ if (fontDescription.italic())
+ traits |= NSItalicFontMask;
+ if (fontDescription.bold())
+ traits |= NSBoldFontMask;
+ float size = fontDescription.computedPixelSize();
+
+ NSFont* nsFont = [WebFontCache fontWithFamily:family traits:traits size:size];
+ if (!nsFont)
+ return 0;
+
+ NSFontTraitMask actualTraits = 0;
+ if (fontDescription.bold() || fontDescription.italic())
+ actualTraits = [[NSFontManager sharedFontManager] traitsOfFont:nsFont];
+
+ FontPlatformData* result = new FontPlatformData;
+
+ // Use the correct font for print vs. screen.
+ result->setFont(fontDescription.usePrinterFont() ? [nsFont printerFont] : [nsFont screenFont]);
+ result->m_syntheticBold = (traits & NSBoldFontMask) && !(actualTraits & NSBoldFontMask);
+ result->m_syntheticOblique = (traits & NSItalicFontMask) && !(actualTraits & NSItalicFontMask);
+ return result;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..f143458
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FontCustomPlatformData.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+#include "SharedBuffer.h"
+#include "FontPlatformData.h"
+
+namespace WebCore {
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+ ATSFontDeactivate(m_atsContainer, NULL, kATSOptionFlagsDefault);
+ CGFontRelease(m_cgFont);
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic)
+{
+ return FontPlatformData(m_cgFont, (ATSUFontID)m_atsFont, size, bold, italic);
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ ASSERT_ARG(buffer, buffer);
+
+ // Use ATS to activate the font.
+ ATSFontContainerRef containerRef = 0;
+
+ // The value "3" means that the font is private and can't be seen by anyone else.
+ ATSFontActivateFromMemory((void*)buffer->data(), buffer->size(), 3, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &containerRef);
+ if (!containerRef)
+ return 0;
+ ItemCount fontCount;
+ ATSFontFindFromContainer(containerRef, kATSOptionFlagsDefault, 0, NULL, &fontCount);
+
+ // We just support the first font in the list.
+ if (fontCount == 0) {
+ ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
+ return 0;
+ }
+
+ ATSFontRef fontRef = 0;
+ ATSFontFindFromContainer(containerRef, kATSOptionFlagsDefault, 1, &fontRef, NULL);
+ if (!fontRef) {
+ ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
+ return 0;
+ }
+
+ CGFontRef cgFontRef = CGFontCreateWithPlatformFont(&fontRef);
+#ifndef BUILDING_ON_TIGER
+ // Workaround for <rdar://problem/5675504>.
+ if (!CGFontGetNumberOfGlyphs(cgFontRef)) {
+ CFRelease(cgFontRef);
+ cgFontRef = 0;
+ }
+#endif
+ if (!cgFontRef) {
+ ATSFontDeactivate(containerRef, NULL, kATSOptionFlagsDefault);
+ return 0;
+ }
+
+ return new FontCustomPlatformData(containerRef, fontRef, cgFontRef);
+}
+
+}
diff --git a/WebCore/platform/graphics/mac/FontCustomPlatformData.h b/WebCore/platform/graphics/mac/FontCustomPlatformData.h
new file mode 100644
index 0000000..d2e83ca
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontCustomPlatformData.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FontCustomPlatformData_h
+#define FontCustomPlatformData_h
+
+#include <wtf/Noncopyable.h>
+
+typedef struct CGFont* CGFontRef;
+typedef UInt32 ATSFontContainerRef;
+typedef UInt32 ATSFontRef;
+
+namespace WebCore {
+
+class FontPlatformData;
+class SharedBuffer;
+
+struct FontCustomPlatformData : Noncopyable {
+ FontCustomPlatformData(ATSFontContainerRef container, ATSFontRef atsFont, CGFontRef cgFont)
+ : m_atsContainer(container), m_atsFont(atsFont), m_cgFont(cgFont)
+ {}
+ ~FontCustomPlatformData();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic);
+
+ ATSFontContainerRef m_atsContainer;
+ ATSFontRef m_atsFont;
+ CGFontRef m_cgFont;
+};
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
new file mode 100644
index 0000000..06d8d9e
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -0,0 +1,659 @@
+/**
+ * This file is part of the html renderer for KDE.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#import "config.h"
+#import "Font.h"
+
+#import "BlockExceptions.h"
+#import "CharacterNames.h"
+#import "FontFallbackList.h"
+#import "GlyphBuffer.h"
+#import "GraphicsContext.h"
+#import "IntRect.h"
+#import "Logging.h"
+#import "ShapeArabic.h"
+#import "SimpleFontData.h"
+#import "WebCoreSystemInterface.h"
+#import "WebCoreTextRenderer.h"
+
+#define SYNTHETIC_OBLIQUE_ANGLE 14
+
+#ifdef __LP64__
+#define URefCon void*
+#else
+#define URefCon UInt32
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+// =================================================================
+// Font Class (Platform-Specific Portion)
+// =================================================================
+
+struct ATSULayoutParameters
+{
+ ATSULayoutParameters(const TextRun& run)
+ : m_run(run)
+ , m_font(0)
+ , m_fonts(0)
+ , m_charBuffer(0)
+ , m_hasSyntheticBold(false)
+ , m_syntheticBoldPass(false)
+ , m_padPerSpace(0)
+ {}
+
+ void initialize(const Font*, const GraphicsContext* = 0);
+
+ const TextRun& m_run;
+
+ const Font* m_font;
+
+ ATSUTextLayout m_layout;
+ const SimpleFontData **m_fonts;
+
+ UChar *m_charBuffer;
+ bool m_hasSyntheticBold;
+ bool m_syntheticBoldPass;
+ float m_padPerSpace;
+};
+
+// Be sure to free the array allocated by this function.
+static TextRun addDirectionalOverride(const TextRun& run, bool rtl)
+{
+ UChar* charactersWithOverride = new UChar[run.length() + 2];
+ charactersWithOverride[0] = rtl ? rightToLeftOverride : leftToRightOverride;
+ memcpy(&charactersWithOverride[1], run.data(0), sizeof(UChar) * run.length());
+ charactersWithOverride[run.length() + 1] = popDirectionalFormatting;
+
+ TextRun result = run;
+ result.setText(charactersWithOverride, run.length() + 2);
+ return result;
+}
+
+static void initializeATSUStyle(const SimpleFontData* fontData)
+{
+ // The two NSFont calls in this method (pointSize and _atsFontID) do not raise exceptions.
+
+ if (!fontData->m_ATSUStyleInitialized) {
+ OSStatus status;
+ ByteCount propTableSize;
+
+ status = ATSUCreateStyle(&fontData->m_ATSUStyle);
+ if (status != noErr)
+ LOG_ERROR("ATSUCreateStyle failed (%d)", status);
+
+ ATSUFontID fontID = fontData->platformData().m_atsuFontID;
+ if (fontID == 0) {
+ ATSUDisposeStyle(fontData->m_ATSUStyle);
+ LOG_ERROR("unable to get ATSUFontID for %@", fontData->m_font.font());
+ return;
+ }
+
+ CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
+ if (fontData->m_font.m_syntheticOblique)
+ transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
+ Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
+
+ // Turn off automatic kerning until it is supported in the CG code path (6136 in bugzilla)
+ Fract kerningInhibitFactor = FloatToFract(1.0);
+ ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
+ ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
+ 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);
+ status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
+ if (status == noErr) // naively assume that if a 'prop' table exists then it contains mirroring info
+ fontData->m_ATSUMirrors = true;
+ else if (status == kATSInvalidFontTableAccess)
+ fontData->m_ATSUMirrors = false;
+ else
+ LOG_ERROR("ATSFontGetTable failed (%d)", status);
+
+ // Turn off ligatures such as 'fi' to match the CG code path's behavior, until bugzilla 6135 is fixed.
+ // 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->m_font.font() coveredCharacterSet] characterIsMember:'a']) {
+ ATSUFontFeatureType featureTypes[] = { kLigaturesType };
+ ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
+ status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
+ }
+
+ fontData->m_ATSUStyleInitialized = true;
+ }
+}
+
+static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOperation, ATSULineRef iLineRef, URefCon iRefCon,
+ void *iOperationCallbackParameterPtr, ATSULayoutOperationCallbackStatus *oCallbackStatus)
+{
+ ATSULayoutParameters *params = (ATSULayoutParameters *)iRefCon;
+ OSStatus status;
+ ItemCount count;
+ ATSLayoutRecord *layoutRecords;
+
+ if (params->m_run.applyWordRounding()) {
+ status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, (void **)&layoutRecords, &count);
+ if (status != noErr) {
+ *oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
+ return status;
+ }
+
+ Fixed lastNativePos = 0;
+ float lastAdjustedPos = 0;
+ const UChar* characters = params->m_charBuffer ? params->m_charBuffer : params->m_run.characters();
+ const SimpleFontData **renderers = params->m_fonts;
+ const SimpleFontData *renderer;
+ const SimpleFontData *lastRenderer = 0;
+ UChar ch, nextCh;
+ ByteCount offset = layoutRecords[0].originalOffset;
+ nextCh = *(UChar *)(((char *)characters)+offset);
+ bool shouldRound = false;
+ bool syntheticBoldPass = params->m_syntheticBoldPass;
+ Fixed syntheticBoldOffset = 0;
+ ATSGlyphRef spaceGlyph = 0;
+ bool hasExtraSpacing = params->m_font->letterSpacing() || params->m_font->wordSpacing() | params->m_run.padding();
+ float padding = params->m_run.padding();
+ // In the CoreGraphics code path, the rounding hack is applied in logical order.
+ // Here it is applied in visual left-to-right order, which may be better.
+ ItemCount lastRoundingChar = 0;
+ ItemCount i;
+ for (i = 1; i < count; i++) {
+ bool isLastChar = i == count - 1;
+ renderer = renderers[offset / 2];
+ if (renderer != lastRenderer) {
+ lastRenderer = renderer;
+ spaceGlyph = renderer->m_spaceGlyph;
+ // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
+ // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
+ // does in any of its device-metrics modes.
+ shouldRound = [renderer->m_font.font() renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode;
+ if (syntheticBoldPass)
+ syntheticBoldOffset = FloatToFixed(renderer->m_syntheticBoldOffset);
+ }
+ float width;
+ if (nextCh == zeroWidthSpace || Font::treatAsZeroWidthSpace(nextCh) && !Font::treatAsSpace(nextCh)) {
+ width = 0;
+ layoutRecords[i-1].glyphID = spaceGlyph;
+ } else {
+ width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
+ if (shouldRound)
+ width = roundf(width);
+ width += renderer->m_syntheticBoldOffset;
+ if (renderer->m_treatAsFixedPitch ? width == renderer->m_spaceWidth : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
+ width = renderer->m_adjustedSpaceWidth;
+ }
+ lastNativePos = layoutRecords[i].realPos;
+
+ if (hasExtraSpacing) {
+ if (width && params->m_font->letterSpacing())
+ width +=params->m_font->letterSpacing();
+ if (Font::treatAsSpace(nextCh)) {
+ if (params->m_run.padding()) {
+ if (padding < params->m_padPerSpace) {
+ width += padding;
+ padding = 0;
+ } else {
+ width += params->m_padPerSpace;
+ padding -= params->m_padPerSpace;
+ }
+ }
+ if (offset != 0 && !Font::treatAsSpace(*((UChar *)(((char *)characters)+offset) - 1)) && params->m_font->wordSpacing())
+ width += params->m_font->wordSpacing();
+ }
+ }
+
+ ch = nextCh;
+ offset = layoutRecords[i].originalOffset;
+ // Use space for nextCh at the end of the loop so that we get inside the rounding hack code.
+ // We won't actually round unless the other conditions are satisfied.
+ nextCh = isLastChar ? ' ' : *(UChar *)(((char *)characters)+offset);
+
+ if (Font::isRoundingHackCharacter(ch))
+ width = ceilf(width);
+ lastAdjustedPos = lastAdjustedPos + width;
+ if (Font::isRoundingHackCharacter(nextCh) && (!isLastChar || params->m_run.applyRunRounding())){
+ if (params->m_run.ltr())
+ lastAdjustedPos = ceilf(lastAdjustedPos);
+ else {
+ float roundingWidth = ceilf(lastAdjustedPos) - lastAdjustedPos;
+ Fixed rw = FloatToFixed(roundingWidth);
+ ItemCount j;
+ for (j = lastRoundingChar; j < i; j++)
+ layoutRecords[j].realPos += rw;
+ lastRoundingChar = i;
+ lastAdjustedPos += roundingWidth;
+ }
+ }
+ if (syntheticBoldPass) {
+ if (syntheticBoldOffset)
+ layoutRecords[i-1].realPos += syntheticBoldOffset;
+ else
+ layoutRecords[i-1].glyphID = spaceGlyph;
+ }
+ layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
+ }
+
+ status = ATSUDirectReleaseLayoutDataArrayPtr(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords);
+ }
+ *oCallbackStatus = kATSULayoutOperationCallbackStatusHandled;
+ return noErr;
+}
+
+static inline bool isArabicLamWithAlefLigature(UChar c)
+{
+ return c >= 0xfef5 && c <= 0xfefc;
+}
+
+static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength, unsigned shapingStart)
+{
+ while (shapingStart < totalLength) {
+ unsigned shapingEnd;
+ // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
+ // since we want to be able to identify this sequence as the result of shaping a Lam
+ // followed by an Alef and padding with a space.
+ bool foundLigatureSpace = false;
+ for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
+ foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
+ shapingEnd++;
+
+ UErrorCode shapingError = U_ZERO_ERROR;
+ unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
+
+ if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
+ for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
+ if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
+ dest[++j] = zeroWidthSpace;
+ }
+ if (foundLigatureSpace) {
+ dest[shapingEnd] = ' ';
+ shapingEnd++;
+ } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
+ // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
+ // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
+ ASSERT(dest[shapingStart] == ' ');
+ dest[shapingStart] = zeroWidthSpace;
+ }
+ } else {
+ // Something went wrong. Abandon shaping and just copy the rest of the buffer.
+ LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
+ shapingEnd = totalLength;
+ memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
+ }
+ shapingStart = shapingEnd;
+ }
+}
+
+void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* graphicsContext)
+{
+ m_font = font;
+
+ const SimpleFontData* fontData = font->primaryFont();
+ m_fonts = new const SimpleFontData*[m_run.length()];
+ m_charBuffer = font->isSmallCaps() ? new UChar[m_run.length()] : 0;
+
+ ATSUTextLayout layout;
+ OSStatus status;
+ ATSULayoutOperationOverrideSpecifier overrideSpecifier;
+
+ initializeATSUStyle(fontData);
+
+ // FIXME: This is currently missing the following required features that the CoreGraphics code path has:
+ // - \n, \t, and nonbreaking space render as a space.
+
+ UniCharCount runLength = m_run.length();
+
+ if (m_charBuffer)
+ memcpy(m_charBuffer, m_run.characters(), runLength * sizeof(UChar));
+
+ status = ATSUCreateTextLayoutWithTextPtr(
+ (m_charBuffer ? m_charBuffer : m_run.characters()),
+ 0, // offset
+ runLength, // length
+ runLength, // total length
+ 1, // styleRunCount
+ &runLength, // length of style run
+ &fontData->m_ATSUStyle,
+ &layout);
+ if (status != noErr)
+ LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed(%d)", status);
+ m_layout = layout;
+ ATSUSetTextLayoutRefCon(m_layout, (URefCon)this);
+
+ // FIXME: There are certain times when this method is called, when we don't have access to a GraphicsContext
+ // measuring text runs with floatWidthForComplexText is one example.
+ // ATSUI requires that we pass a valid CGContextRef to it when specifying kATSUCGContextTag (crashes when passed 0)
+ // ATSUI disables sub-pixel rendering if kATSUCGContextTag is not specified! So we're in a bind.
+ // Sometimes [[NSGraphicsContext currentContext] graphicsPort] may return the wrong (or no!) context. Nothing we can do about it (yet).
+ CGContextRef cgContext = graphicsContext ? graphicsContext->platformContext() : (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+
+ ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
+ Boolean rtl = m_run.rtl();
+ overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
+ overrideSpecifier.overrideUPP = overrideLayoutOperation;
+ ATSUAttributeTag tags[] = { kATSUCGContextTag, kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
+ ByteCount sizes[] = { sizeof(CGContextRef), sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
+ ATSUAttributeValuePtr values[] = { &cgContext, &lineLayoutOptions, &rtl, &overrideSpecifier };
+
+ status = ATSUSetLayoutControls(layout, (m_run.applyWordRounding() ? 4 : 3), tags, sizes, values);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetLayoutControls failed(%d)", status);
+
+ status = ATSUSetTransientFontMatching(layout, YES);
+ if (status != noErr)
+ LOG_ERROR("ATSUSetTransientFontMatching failed(%d)", status);
+
+ m_hasSyntheticBold = false;
+ ATSUFontID ATSUSubstituteFont;
+ UniCharArrayOffset substituteOffset = 0;
+ UniCharCount substituteLength;
+ UniCharArrayOffset lastOffset;
+ const SimpleFontData* substituteFontData = 0;
+
+ while (substituteOffset < runLength) {
+ // FIXME: Using ATSUMatchFontsToText() here results in several problems: the CSS font family list is not necessarily followed for the 2nd
+ // and onwards unmatched characters; segmented fonts do not work correctly; behavior does not match the simple text and Uniscribe code
+ // paths. Change this function to use Font::glyphDataForCharacter() for each character instead.
+ lastOffset = substituteOffset;
+ status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);
+ if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {
+ const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);
+ substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;
+ if (substituteFontData) {
+ initializeATSUStyle(substituteFontData);
+ if (substituteFontData->m_ATSUStyle)
+ ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);
+ } else
+ substituteFontData = fontData;
+ } else {
+ substituteOffset = runLength;
+ substituteLength = 0;
+ }
+
+ bool shapedArabic = false;
+ bool isSmallCap = false;
+ UniCharArrayOffset firstSmallCap = 0;
+ const SimpleFontData *r = fontData;
+ UniCharArrayOffset i;
+ for (i = lastOffset; ; i++) {
+ if (i == substituteOffset || i == substituteOffset + substituteLength) {
+ if (isSmallCap) {
+ isSmallCap = false;
+ initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()));
+ ATSUSetRunStyle(layout, r->smallCapsFontData(m_font->fontDescription())->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
+ }
+ if (i == substituteOffset && substituteLength > 0)
+ r = substituteFontData;
+ else
+ break;
+ }
+ if (!shapedArabic && WTF::Unicode::isArabicChar(m_run[i]) && !r->shapesArabic()) {
+ shapedArabic = true;
+ if (!m_charBuffer) {
+ m_charBuffer = new UChar[runLength];
+ memcpy(m_charBuffer, m_run.characters(), i * sizeof(UChar));
+ ATSUTextMoved(layout, m_charBuffer);
+ }
+ shapeArabic(m_run.characters(), m_charBuffer, runLength, i);
+ }
+ if (m_run.rtl() && !r->m_ATSUMirrors) {
+ UChar mirroredChar = u_charMirror(m_run[i]);
+ if (mirroredChar != m_run[i]) {
+ if (!m_charBuffer) {
+ m_charBuffer = new UChar[runLength];
+ memcpy(m_charBuffer, m_run.characters(), runLength * sizeof(UChar));
+ ATSUTextMoved(layout, m_charBuffer);
+ }
+ m_charBuffer[i] = mirroredChar;
+ }
+ }
+ if (m_font->isSmallCaps()) {
+ const SimpleFontData* smallCapsData = r->smallCapsFontData(m_font->fontDescription());
+ UChar c = m_charBuffer[i];
+ UChar newC;
+ if (U_GET_GC_MASK(c) & U_GC_M_MASK)
+ m_fonts[i] = isSmallCap ? smallCapsData : r;
+ else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
+ m_charBuffer[i] = newC;
+ if (!isSmallCap) {
+ isSmallCap = true;
+ firstSmallCap = i;
+ }
+ m_fonts[i] = smallCapsData;
+ } else {
+ if (isSmallCap) {
+ isSmallCap = false;
+ initializeATSUStyle(smallCapsData);
+ ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
+ }
+ m_fonts[i] = r;
+ }
+ } else
+ m_fonts[i] = r;
+ if (m_fonts[i]->m_syntheticBoldOffset)
+ m_hasSyntheticBold = true;
+ }
+ substituteOffset += substituteLength;
+ }
+ if (m_run.padding()) {
+ float numSpaces = 0;
+ unsigned k;
+ for (k = 0; k < runLength; k++)
+ if (Font::treatAsSpace(m_run[k]))
+ numSpaces++;
+
+ if (numSpaces == 0)
+ m_padPerSpace = 0;
+ else
+ m_padPerSpace = ceilf(m_run.padding() / numSpaces);
+ } else
+ m_padPerSpace = 0;
+}
+
+static void disposeATSULayoutParameters(ATSULayoutParameters *params)
+{
+ ATSUDisposeTextLayout(params->m_layout);
+ delete []params->m_charBuffer;
+ delete []params->m_fonts;
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
+{
+ TextRun adjustedRun = run.directionalOverride() ? addDirectionalOverride(run, run.rtl()) : run;
+ if (run.directionalOverride()) {
+ from++;
+ to++;
+ }
+
+ ATSULayoutParameters params(adjustedRun);
+ params.initialize(this);
+
+ ATSTrapezoid firstGlyphBounds;
+ ItemCount actualNumBounds;
+
+ OSStatus status = ATSUGetGlyphBounds(params.m_layout, 0, 0, from, to - from, kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
+ if (status != noErr || actualNumBounds != 1) {
+ static ATSTrapezoid zeroTrapezoid = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+ firstGlyphBounds = zeroTrapezoid;
+ }
+ disposeATSULayoutParameters(&params);
+
+ 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);
+
+ if (run.directionalOverride())
+ delete []adjustedRun.characters();
+
+ return rect;
+}
+
+void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ OSStatus status;
+
+ int drawPortionLength = to - from;
+ TextRun adjustedRun = run.directionalOverride() ? addDirectionalOverride(run, run.rtl()) : run;
+ if (run.directionalOverride())
+ from++;
+
+ ATSULayoutParameters params(adjustedRun);
+ params.initialize(this, graphicsContext);
+
+ // ATSUI can't draw beyond -32768 to +32767 so we translate the CTM and tell ATSUI to draw at (0, 0).
+ CGContextRef context = graphicsContext->platformContext();
+
+ CGContextTranslateCTM(context, point.x(), point.y());
+ status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
+ if (status == noErr && params.m_hasSyntheticBold) {
+ // Force relayout for the bold pass
+ ATSUClearLayoutCache(params.m_layout, 0);
+ params.m_syntheticBoldPass = true;
+ status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
+ }
+ CGContextTranslateCTM(context, -point.x(), -point.y());
+
+ if (status != noErr)
+ // Nothing to do but report the error (dev build only).
+ LOG_ERROR("ATSUDrawText() failed(%d)", status);
+
+ disposeATSULayoutParameters(&params);
+
+ if (run.directionalOverride())
+ delete []adjustedRun.characters();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ if (run.length() == 0)
+ return 0;
+
+ ATSULayoutParameters params(run);
+ params.initialize(this);
+
+ OSStatus status;
+
+ ATSTrapezoid firstGlyphBounds;
+ ItemCount actualNumBounds;
+ status = ATSUGetGlyphBounds(params.m_layout, 0, 0, 0, run.length(), kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
+ if (status != noErr)
+ LOG_ERROR("ATSUGetGlyphBounds() failed(%d)", status);
+ if (actualNumBounds != 1)
+ LOG_ERROR("unexpected result from ATSUGetGlyphBounds(): actualNumBounds(%d) != 1", actualNumBounds);
+
+ disposeATSULayoutParameters(&params);
+
+ 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
+{
+ TextRun adjustedRun = run.directionalOverride() ? addDirectionalOverride(run, run.rtl()) : run;
+
+ ATSULayoutParameters params(adjustedRun);
+ params.initialize(this);
+
+ UniCharArrayOffset primaryOffset = 0;
+
+ // FIXME: No idea how to avoid including partial glyphs.
+ // Not even sure if that's the behavior this yields now.
+ Boolean isLeading;
+ UniCharArrayOffset secondaryOffset = 0;
+ OSStatus status = ATSUPositionToOffset(params.m_layout, FloatToFixed(x), FloatToFixed(-1), &primaryOffset, &isLeading, &secondaryOffset);
+ unsigned offset;
+ if (status == noErr) {
+ offset = (unsigned)primaryOffset;
+ if (run.directionalOverride() && offset > 0)
+ offset--;
+ } else
+ // Failed to find offset! Return 0 offset.
+ offset = 0;
+
+ disposeATSULayoutParameters(&params);
+
+ if (run.directionalOverride())
+ delete []adjustedRun.characters();
+
+ return offset;
+}
+
+void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
+{
+ CGContextRef cgContext = context->platformContext();
+
+ bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
+ bool newShouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
+
+ if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
+ CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
+
+ const FontPlatformData& platformData = font->platformData();
+ NSFont* drawFont;
+ if (!isPrinterFont()) {
+ drawFont = [platformData.font() screenFont];
+ if (drawFont != platformData.font())
+ // We are getting this in too many places (3406411); use ERROR so it only prints on debug versions for now. (We should debug this also, eventually).
+ LOG_ERROR("Attempting to set non-screen font (%@) when drawing to screen. Using screen font anyway, may result in incorrect metrics.",
+ [[[platformData.font() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
+ } else {
+ drawFont = [platformData.font() printerFont];
+ if (drawFont != platformData.font())
+ NSLog(@"Attempting to set non-printer font (%@) when printing. Using printer font anyway, may result in incorrect metrics.",
+ [[[platformData.font() fontDescriptor] fontAttributes] objectForKey:NSFontNameAttribute]);
+ }
+
+ CGContextSetFont(cgContext, platformData.m_cgFont);
+
+ CGAffineTransform matrix = CGAffineTransformIdentity;
+ if (drawFont)
+ memcpy(&matrix, [drawFont matrix], sizeof(matrix));
+ matrix.b = -matrix.b;
+ matrix.d = -matrix.d;
+ if (platformData.m_syntheticOblique)
+ matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
+ CGContextSetTextMatrix(cgContext, matrix);
+
+ if (drawFont) {
+ wkSetCGFontRenderingMode(cgContext, drawFont);
+ CGContextSetFontSize(cgContext, 1.0f);
+ } else
+ CGContextSetFontSize(cgContext, platformData.m_size);
+
+ CGContextSetTextPosition(cgContext, point.x(), point.y());
+ CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ if (font->m_syntheticBoldOffset) {
+ CGContextSetTextPosition(cgContext, point.x() + font->m_syntheticBoldOffset, point.y());
+ CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ }
+
+ if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
+ CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
+}
+
+}
diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h
new file mode 100644
index 0000000..8f118e0
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontPlatformData.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FontPlatformData_h
+#define FontPlatformData_h
+
+#include "StringImpl.h"
+
+#ifdef __OBJC__
+@class NSFont;
+#else
+class NSFont;
+#endif
+
+typedef struct CGFont* CGFontRef;
+typedef UInt32 ATSUFontID;
+
+#include <CoreFoundation/CFBase.h>
+#include <objc/objc-auto.h>
+
+namespace WebCore {
+
+struct FontPlatformData {
+ class Deleted {};
+
+ FontPlatformData(Deleted)
+ : m_syntheticBold(false), m_syntheticOblique(false), m_cgFont(0), m_atsuFontID(0), m_size(0), m_font((NSFont*)-1)
+ {}
+
+ FontPlatformData(float s, bool b, bool o)
+ : m_syntheticBold(b)
+ , m_syntheticOblique(o)
+ , m_cgFont(0)
+ , m_atsuFontID(0)
+ , m_size(s)
+ , m_font(0)
+ {
+ }
+
+ FontPlatformData(NSFont* f = 0, bool b = false, bool o = false);
+
+ FontPlatformData(CGFontRef f, ATSUFontID fontID, float s, bool b , bool o)
+ : m_syntheticBold(b), m_syntheticOblique(o), m_cgFont(f), m_atsuFontID(fontID), m_size(s), m_font(0)
+ {
+ }
+
+ FontPlatformData(const FontPlatformData& f);
+
+ ~FontPlatformData();
+
+ float size() const { return m_size; }
+
+ bool m_syntheticBold;
+ bool m_syntheticOblique;
+
+ CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced.
+ ATSUFontID m_atsuFontID;
+ float m_size;
+
+ unsigned hash() const
+ {
+ ASSERT(m_font != 0 || m_cgFont == 0);
+ uintptr_t hashCodes[2] = { (uintptr_t)m_font, m_syntheticBold << 1 | m_syntheticOblique };
+ return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
+ }
+
+ bool operator==(const FontPlatformData& other) const
+ {
+ return m_font == other.m_font && m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique &&
+ m_cgFont == other.m_cgFont && m_size == other.m_size && m_atsuFontID == other.m_atsuFontID;
+ }
+
+ NSFont *font() const { return m_font; }
+ void setFont(NSFont* font);
+
+private:
+ NSFont *m_font;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
new file mode 100644
index 0000000..d1e00d1
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the internal font implementation.
+ *
+ * Copyright (C) 2006-7 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#import "config.h"
+#import "FontPlatformData.h"
+
+#import "WebCoreSystemInterface.h"
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(NSFont* f, bool b , bool o)
+: m_syntheticBold(b), m_syntheticOblique(o), m_font(f)
+{
+ if (f)
+ CFRetain(f);
+ m_size = f ? [f pointSize] : 0.0f;
+ m_cgFont = wkGetCGFontFromNSFont(f);
+ m_atsuFontID = wkGetNSFontATSUFontId(f);
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData& f)
+{
+ m_font = (f.m_font && f.m_font != (NSFont*)-1) ? (NSFont*)CFRetain(f.m_font) : f.m_font;
+ m_syntheticBold = f.m_syntheticBold;
+ m_syntheticOblique = f.m_syntheticOblique;
+ m_size = f.m_size;
+ m_cgFont = f.m_cgFont;
+ m_atsuFontID = f.m_atsuFontID;
+}
+
+FontPlatformData:: ~FontPlatformData()
+{
+ if (m_font && m_font != (NSFont*)-1)
+ CFRelease(m_font);
+}
+
+void FontPlatformData::setFont(NSFont* font) {
+ if (m_font == font)
+ return;
+ if (font)
+ CFRetain(font);
+ if (m_font && m_font != (NSFont*)-1)
+ CFRelease(m_font);
+ m_font = font;
+ m_size = font ? [font pointSize] : 0.0f;
+ m_cgFont = wkGetCGFontFromNSFont(font);
+ m_atsuFontID = wkGetNSFontATSUFontId(font);
+}
+
+}
+
diff --git a/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
new file mode 100644
index 0000000..b9f2da3
--- /dev/null
+++ b/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2006, 2007 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.
+ * 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 "GlyphPageTreeNode.h"
+
+#include "SimpleFontData.h"
+#include "WebCoreSystemInterface.h"
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ // Use an array of long so we get good enough alignment.
+ long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)];
+
+ OSStatus status = wkInitializeGlyphVector(GlyphPage::size, &glyphVector);
+ if (status != noErr)
+ // This should never happen, perhaps indicates a bad font! If it does the
+ // font substitution code will find an alternate font.
+ return false;
+
+ wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector);
+
+ unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
+ if (numGlyphs != length) {
+ // This should never happen, perhaps indicates a bad font?
+ // If it does happen, the font substitution code will find an alternate font.
+ wkClearGlyphVector(&glyphVector);
+ return false;
+ }
+
+ bool haveGlyphs = false;
+ ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
+ for (unsigned i = 0; i < length; i++) {
+ Glyph glyph = glyphRecord->glyphID;
+ if (!glyph)
+ setGlyphDataForIndex(offset + i, 0, 0);
+ else {
+ setGlyphDataForIndex(offset + i, glyph, fontData);
+ haveGlyphs = true;
+ }
+ glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
+ }
+ wkClearGlyphVector(&glyphVector);
+
+ return haveGlyphs;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
new file mode 100644
index 0000000..3f9176c
--- /dev/null
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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.
+ */
+
+#import "config.h"
+#import "GraphicsContext.h"
+
+#import "../cg/GraphicsContextPlatformPrivateCG.h"
+
+#import "WebCoreSystemInterface.h"
+
+// FIXME: More of this should use CoreGraphics instead of AppKit.
+// FIXME: More of this should move into GraphicsContextCG.cpp.
+
+namespace WebCore {
+
+// NSColor, NSBezierPath, and NSGraphicsContext
+// calls in this file are all exception-safe, so we don't block
+// exceptions for those.
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ int radius = (focusRingWidth() - 1) / 2;
+ int offset = radius + focusRingOffset();
+ CGColorRef colorRef = color.isValid() ? cgColor(color) : 0;
+
+ CGMutablePathRef focusRingPath = 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));
+
+ CGContextRef context = platformContext();
+#ifdef BUILDING_ON_TIGER
+ CGContextBeginTransparencyLayer(context, NULL);
+#endif
+ CGContextBeginPath(context);
+ CGContextAddPath(context, focusRingPath);
+ wkDrawFocusRing(context, colorRef, 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.
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [[NSGraphicsContext graphicsContextWithGraphicsPort:platformContext() flipped:YES]
+ setCompositingOperation:(NSCompositingOperation)op];
+ [pool drain];
+}
+#endif
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
+{
+ if (paintingDisabled())
+ return;
+
+ // Constants for spelling pattern color
+ static RetainPtr<NSColor> spellingPatternColor = nil;
+ static bool usingDotForSpelling = false;
+
+ // Constants for grammar pattern color
+ static RetainPtr<NSColor> grammarPatternColor = nil;
+ static bool usingDotForGrammar = false;
+
+ // These are the same for misspelling or bad grammar
+ int patternHeight = cMisspellingLineThickness;
+ int patternWidth = cMisspellingLinePatternWidth;
+
+ // Initialize pattern color if needed
+ if (!grammar && !spellingPatternColor) {
+ NSImage *image = [NSImage imageNamed:@"SpellingDot"];
+ ASSERT(image); // if image is not available, we want to know
+ NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
+ if (color)
+ usingDotForSpelling = true;
+ else
+ color = [NSColor redColor];
+ spellingPatternColor = color;
+ }
+
+ if (grammar && !grammarPatternColor) {
+ NSImage *image = [NSImage imageNamed:@"GrammarDot"];
+ ASSERT(image); // if image is not available, we want to know
+ NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
+ if (color)
+ usingDotForGrammar = true;
+ else
+ color = [NSColor greenColor];
+ grammarPatternColor = color;
+ }
+
+ bool usingDot;
+ NSColor *patternColor;
+ if (grammar) {
+ usingDot = usingDotForGrammar;
+ patternColor = grammarPatternColor.get();
+ } else {
+ usingDot = usingDotForSpelling;
+ patternColor = spellingPatternColor.get();
+ }
+
+ // Make sure to draw only complete dots.
+ // NOTE: Code here used to shift the underline to the left and increase the width
+ // to make sure everything gets underlined, but that results in drawing out of
+ // bounds (e.g. when at the edge of a view) and could make it appear that the
+ // space between adjacent misspelled words was underlined.
+ if (usingDot) {
+ // allow slightly more considering that the pattern ends with a transparent pixel
+ int widthMod = width % patternWidth;
+ if (patternWidth - widthMod > cMisspellingLinePatternGapWidth)
+ width -= widthMod;
+ }
+
+ // FIXME: This code should not use NSGraphicsContext currentContext
+ // In order to remove this requirement we will need to use CGPattern instead of NSColor
+ // FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
+ // for transforms.
+
+ // Draw underline
+ NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+ CGContextRef context = (CGContextRef)[currentContext graphicsPort];
+ CGContextSaveGState(context);
+
+ [patternColor set];
+
+ wkSetPatternPhaseInUserSpace(context, point);
+
+ NSRectFillUsingOperation(NSMakeRect(point.x(), point.y(), width, patternHeight), NSCompositeSourceOver);
+
+ CGContextRestoreGState(context);
+}
+
+}
diff --git a/WebCore/platform/graphics/mac/IconMac.mm b/WebCore/platform/graphics/mac/IconMac.mm
new file mode 100644
index 0000000..b630ba6
--- /dev/null
+++ b/WebCore/platform/graphics/mac/IconMac.mm
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2006, 2007 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.
+ *
+ */
+
+#import "config.h"
+#import "Icon.h"
+
+#import "GraphicsContext.h"
+#import "LocalCurrentGraphicsContext.h"
+#import "PlatformString.h"
+#import <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+Icon::Icon()
+ : RefCounted<Icon>(0)
+{
+}
+
+Icon::Icon(NSImage *image)
+ : RefCounted<Icon>(0)
+ , m_nsImage(image)
+{
+ // Need this because WebCore uses AppKit's flipped coordinate system exclusively.
+ [image setFlipped:YES];
+}
+
+Icon::~Icon()
+{
+}
+
+PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+{
+ // Don't pass relative filenames -- we don't want a result that depends on the current directory.
+ // Need 0U here to disambiguate String::operator[] from operator(NSString*, int)[]
+ if (filename.isEmpty() || filename[0U] != '/')
+ return 0;
+
+ NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile:filename];
+ if (!image)
+ return 0;
+
+ return new Icon(image);
+}
+
+void Icon::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (context->paintingDisabled())
+ return;
+
+ LocalCurrentGraphicsContext localCurrentGC(context);
+
+ [m_nsImage.get() drawInRect:rect
+ fromRect:NSMakeRect(0, 0, [m_nsImage.get() size].width, [m_nsImage.get() size].height)
+ operation:NSCompositeSourceOver fraction:1.0f];
+}
+
+}
diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm
new file mode 100644
index 0000000..121eb78
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ImageMac.mm
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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.
+ */
+
+#import "config.h"
+#import "BitmapImage.h"
+
+#import "FloatRect.h"
+#import "FoundationExtras.h"
+#import "GraphicsContext.h"
+#import "PlatformString.h"
+#import "WebCoreFrameBridge.h"
+
+namespace WebCore {
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+ if (m_frames.size() != 1)
+ return;
+
+ m_nsImage = 0;
+ m_tiffRep = 0;
+}
+
+Image* Image::loadPlatformResource(const char *name)
+{
+ static BitmapImage nullImage;
+
+ NSBundle *bundle = [NSBundle bundleForClass:[WebCoreFrameBridge class]];
+ NSString *imagePath = [bundle pathForResource:[NSString stringWithUTF8String:name] ofType:@"tiff"];
+ NSData *namedImageData = [NSData dataWithContentsOfFile:imagePath];
+ if (namedImageData) {
+ Image* image = new BitmapImage;
+ image->setData(SharedBuffer::wrapNSData(namedImageData), true);
+ return image;
+ }
+
+ // We have reports indicating resource loads are failing, but we don't yet know the root cause(s).
+ // Two theories are bad installs (image files are missing), and too-many-open-files.
+ // See rdar://5607381
+ ASSERT_NOT_REACHED();
+ return &nullImage;
+}
+
+CFDataRef BitmapImage::getTIFFRepresentation()
+{
+ if (m_tiffRep)
+ return m_tiffRep.get();
+
+ unsigned numFrames = frameCount();
+
+ // If numFrames is zero, we know for certain this image doesn't have valid data
+ // Even though the call to CGImageDestinationCreateWithData will fail and we'll handle it gracefully,
+ // in certain circumstances that call will spam the console with an error message
+ if (!numFrames)
+ return 0;
+
+ Vector<CGImageRef> images;
+ for (unsigned i = 0; i < numFrames; ++i ) {
+ CGImageRef cgImage = frameAtIndex(i);
+ if (cgImage)
+ images.append(cgImage);
+ }
+
+ unsigned numValidFrames = images.size();
+
+ 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);
+
+ if (!destination)
+ return 0;
+
+ for (unsigned i = 0; i < numValidFrames; ++i)
+ CGImageDestinationAddImage(destination, images[i], 0);
+
+ CGImageDestinationFinalize(destination);
+ CFRelease(destination);
+
+ m_tiffRep = data;
+ return m_tiffRep.get();
+}
+
+NSImage* BitmapImage::getNSImage()
+{
+ if (m_nsImage)
+ return m_nsImage.get();
+
+ CFDataRef data = getTIFFRepresentation();
+ if (!data)
+ return 0;
+
+ m_nsImage.adoptNS([[NSImage alloc] initWithData:(NSData*)data]);
+ return m_nsImage.get();
+}
+
+}
diff --git a/WebCore/platform/graphics/mac/IntPointMac.mm b/WebCore/platform/graphics/mac/IntPointMac.mm
new file mode 100644
index 0000000..7a2e730
--- /dev/null
+++ b/WebCore/platform/graphics/mac/IntPointMac.mm
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, 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"
+#include "IntPoint.h"
+
+namespace WebCore {
+
+#ifndef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+
+IntPoint::IntPoint(const NSPoint& p) : m_x(static_cast<int>(p.x)), m_y(static_cast<int>(p.y))
+{
+}
+
+IntPoint::operator NSPoint() const
+{
+ return NSMakePoint(m_x, m_y);
+}
+
+#endif
+
+}
diff --git a/WebCore/platform/graphics/mac/IntRectMac.mm b/WebCore/platform/graphics/mac/IntRectMac.mm
new file mode 100644
index 0000000..738618a
--- /dev/null
+++ b/WebCore/platform/graphics/mac/IntRectMac.mm
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2003, 2006 Apple Computer, 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"
+#include "IntRect.h"
+
+namespace WebCore {
+
+#ifndef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+
+IntRect::operator NSRect() const
+{
+ return NSMakeRect(x(), y(), width(), height());
+}
+
+IntRect enclosingIntRect(const NSRect& rect)
+{
+ int l = static_cast<int>(floorf(rect.origin.x));
+ int t = static_cast<int>(floorf(rect.origin.y));
+ int r = static_cast<int>(ceilf(NSMaxX(rect)));
+ int b = static_cast<int>(ceilf(NSMaxY(rect)));
+ return IntRect(l, t, r - l, b - t);
+}
+
+#endif
+
+}
diff --git a/WebCore/platform/graphics/mac/IntSizeMac.mm b/WebCore/platform/graphics/mac/IntSizeMac.mm
new file mode 100644
index 0000000..c7dcd88
--- /dev/null
+++ b/WebCore/platform/graphics/mac/IntSizeMac.mm
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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"
+#include "IntSize.h"
+
+namespace WebCore {
+
+#ifndef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
+
+IntSize::IntSize(const NSSize& s) : m_width(static_cast<int>(s.width)), m_height(static_cast<int>(s.height))
+{
+}
+
+IntSize::operator NSSize() const
+{
+ return NSMakeSize(m_width, m_height);
+}
+
+#endif
+
+}
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
new file mode 100644
index 0000000..8975d9b
--- /dev/null
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2007 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 MediaPlayerPrivateQTKit_h
+#define MediaPlayerPrivateQTKit_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayer.h"
+#include "Timer.h"
+#include <wtf/RetainPtr.h>
+
+#ifdef __OBJC__
+#import <QTKit/QTTime.h>
+@class QTMovie;
+@class QTMovieView;
+@class WebCoreMovieObserver;
+#else
+class QTMovie;
+class QTMovieView;
+class QTTime;
+class WebCoreMovieObserver;
+#endif
+
+namespace WebCore {
+
+class MediaPlayerPrivate : Noncopyable {
+public:
+ MediaPlayerPrivate(MediaPlayer*);
+ ~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 time);
+
+ void setRate(float);
+ void setVolume(float);
+
+ int dataRate() const;
+
+ MediaPlayer::NetworkState networkState() const { return m_networkState; }
+ MediaPlayer::ReadyState readyState() const { return m_readyState; }
+
+ float maxTimeBuffered() const;
+ float maxTimeSeekable() const;
+ unsigned bytesLoaded() const;
+ bool totalBytesKnown() const;
+ unsigned totalBytes() const;
+
+ void setVisible(bool);
+ void setRect(const IntRect& r);
+
+ void loadStateChanged();
+ void rateChanged();
+ void sizeChanged();
+ void timeChanged();
+ void didEnd();
+
+ void repaint();
+ void paint(GraphicsContext*, const IntRect&);
+
+ static void getSupportedTypes(HashSet<String>& types);
+ static bool isAvailable();
+
+private:
+ void createQTMovie(const String& url);
+ void createQTMovieView();
+ void detachQTMovieView();
+ QTTime createQTTime(float time) const;
+
+ void updateStates();
+ void doSeek();
+ void cancelSeek();
+ void seekTimerFired(Timer<MediaPlayerPrivate>*);
+ void endPointTimerFired(Timer<MediaPlayerPrivate>*);
+ float maxTimeLoaded() const;
+ void startEndPointTimerIfNeeded();
+ void disableUnsupportedTracks(unsigned& enabledTrackCount);
+
+ MediaPlayer* m_player;
+ RetainPtr<QTMovie> m_qtMovie;
+ RetainPtr<QTMovieView> m_qtMovieView;
+ RetainPtr<WebCoreMovieObserver> m_objcObserver;
+ float m_seekTo;
+ float m_endTime;
+ Timer<MediaPlayerPrivate> m_seekTimer;
+ Timer<MediaPlayerPrivate> m_endPointTimer;
+ MediaPlayer::NetworkState m_networkState;
+ MediaPlayer::ReadyState m_readyState;
+ bool m_startedPlaying;
+ bool m_isStreaming;
+};
+
+}
+
+#endif
+#endif
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
new file mode 100644
index 0000000..541d5f6
--- /dev/null
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -0,0 +1,843 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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.
+ */
+
+#import "config.h"
+
+#if ENABLE(VIDEO)
+
+#import "MediaPlayerPrivateQTKit.h"
+
+#import "BlockExceptions.h"
+#import "GraphicsContext.h"
+#import "KURL.h"
+#import "ScrollView.h"
+#import "SoftLinking.h"
+#import "WebCoreSystemInterface.h"
+#import <QTKit/QTKit.h>
+#import <objc/objc-runtime.h>
+
+#ifdef BUILDING_ON_TIGER
+static IMP method_setImplementation(Method m, IMP imp)
+{
+ IMP result = m->method_imp;
+ m->method_imp = imp;
+ return result;
+}
+#endif
+
+SOFT_LINK_FRAMEWORK(QTKit)
+
+SOFT_LINK(QTKit, QTMakeTime, QTTime, (long long timeValue, long timeScale), (timeValue, timeScale))
+
+SOFT_LINK_CLASS(QTKit, QTMovie)
+SOFT_LINK_CLASS(QTKit, QTMovieView)
+
+SOFT_LINK_POINTER(QTKit, QTMediaTypeAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMediaTypeBase, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMediaTypeSound, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieNaturalSizeAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMoviePreventExternalURLLinksAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieRateDidChangeNotification, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieSizeDidChangeNotification, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieTimeDidChangeNotification, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieTimeScaleAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieURLAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieVolumeDidChangeNotification, NSString *)
+SOFT_LINK_POINTER(QTKit, QTSecurityPolicyNoCrossSiteAttribute, NSString *)
+
+#define QTMovie getQTMovieClass()
+#define QTMovieView getQTMovieViewClass()
+
+#define QTMediaTypeAttribute getQTMediaTypeAttribute()
+#define QTMediaTypeBase getQTMediaTypeBase()
+#define QTMediaTypeSound getQTMediaTypeSound()
+#define QTMediaTypeText getQTMediaTypeText()
+#define QTMediaTypeVideo getQTMediaTypeVideo()
+#define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute()
+#define QTMovieDidEndNotification getQTMovieDidEndNotification()
+#define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute()
+#define QTMovieIsActiveAttribute getQTMovieIsActiveAttribute()
+#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
+#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
+#define QTMovieNaturalSizeAttribute getQTMovieNaturalSizeAttribute()
+#define QTMoviePreventExternalURLLinksAttribute getQTMoviePreventExternalURLLinksAttribute()
+#define QTMovieRateDidChangeNotification getQTMovieRateDidChangeNotification()
+#define QTMovieSizeDidChangeNotification getQTMovieSizeDidChangeNotification()
+#define QTMovieTimeDidChangeNotification getQTMovieTimeDidChangeNotification()
+#define QTMovieTimeScaleAttribute getQTMovieTimeScaleAttribute()
+#define QTMovieURLAttribute getQTMovieURLAttribute()
+#define QTMovieVolumeDidChangeNotification getQTMovieVolumeDidChangeNotification()
+#define QTSecurityPolicyNoCrossSiteAttribute getQTSecurityPolicyNoCrossSiteAttribute()
+
+// Older versions of the QTKit header don't have these constants.
+#if !defined QTKIT_VERSION_MAX_ALLOWED || QTKIT_VERSION_MAX_ALLOWED <= QTKIT_VERSION_7_0
+enum {
+ QTMovieLoadStateError = -1L,
+ QTMovieLoadStateLoaded = 2000L,
+ QTMovieLoadStatePlayable = 10000L,
+ QTMovieLoadStatePlaythroughOK = 20000L,
+ QTMovieLoadStateComplete = 100000L
+};
+#endif
+
+using namespace WebCore;
+using namespace std;
+
+@interface WebCoreMovieObserver : NSObject
+{
+ MediaPlayerPrivate* m_callback;
+ BOOL m_delayCallbacks;
+}
+-(id)initWithCallback:(MediaPlayerPrivate*)callback;
+-(void)disconnect;
+-(void)repaint;
+-(void)setDelayCallbacks:(BOOL)shouldDelay;
+-(void)loadStateChanged:(NSNotification *)notification;
+-(void)rateChanged:(NSNotification *)notification;
+-(void)sizeChanged:(NSNotification *)notification;
+-(void)timeChanged:(NSNotification *)notification;
+-(void)didEnd:(NSNotification *)notification;
+@end
+
+namespace WebCore {
+
+static const float endPointTimerInterval = 0.020f;
+static const long minimumQuickTimeVersion = 0x07300000; // 7.3
+
+MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
+ : m_player(player)
+ , m_objcObserver(AdoptNS, [[WebCoreMovieObserver alloc] initWithCallback:this])
+ , m_seekTo(-1)
+ , m_endTime(numeric_limits<float>::infinity())
+ , m_seekTimer(this, &MediaPlayerPrivate::seekTimerFired)
+ , m_endPointTimer(this, &MediaPlayerPrivate::endPointTimerFired)
+ , m_networkState(MediaPlayer::Empty)
+ , m_readyState(MediaPlayer::DataUnavailable)
+ , m_startedPlaying(false)
+ , m_isStreaming(false)
+{
+}
+
+MediaPlayerPrivate::~MediaPlayerPrivate()
+{
+ detachQTMovieView();
+
+ [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
+ [m_objcObserver.get() disconnect];
+}
+
+void MediaPlayerPrivate::createQTMovie(const String& url)
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
+
+ m_qtMovie = 0;
+
+ // Disable streaming support for now, <rdar://problem/5693967>
+ if (protocolIs(url, "rtsp"))
+ return;
+
+ NSURL *cocoaURL = KURL(url);
+ NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
+ cocoaURL, QTMovieURLAttribute,
+ [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute,
+ [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute,
+ nil];
+
+ NSError* error = nil;
+ m_qtMovie.adoptNS([[QTMovie alloc] initWithAttributes:movieAttributes error:&error]);
+
+ // FIXME: Find a proper way to detect streaming content.
+ m_isStreaming = protocolIs(url, "rtsp");
+
+ if (!m_qtMovie)
+ return;
+
+ [m_qtMovie.get() setVolume:m_player->volume()];
+
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(loadStateChanged:)
+ name:QTMovieLoadStateDidChangeNotification
+ object:m_qtMovie.get()];
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(rateChanged:)
+ name:QTMovieRateDidChangeNotification
+ object:m_qtMovie.get()];
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(sizeChanged:)
+ name:QTMovieSizeDidChangeNotification
+ object:m_qtMovie.get()];
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(timeChanged:)
+ name:QTMovieTimeDidChangeNotification
+ object:m_qtMovie.get()];
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(didEnd:)
+ name:QTMovieDidEndNotification
+ object:m_qtMovie.get()];
+}
+
+static void mainThreadSetNeedsDisplay(id self, SEL _cmd)
+{
+ id movieView = [self superview];
+ ASSERT(!movieView || [movieView isKindOfClass:[QTMovieView class]]);
+ if (!movieView || ![movieView isKindOfClass:[QTMovieView class]])
+ return;
+
+ WebCoreMovieObserver* delegate = [movieView delegate];
+ ASSERT(!delegate || [delegate isKindOfClass:[WebCoreMovieObserver class]]);
+ if (!delegate || ![delegate isKindOfClass:[WebCoreMovieObserver class]])
+ return;
+
+ [delegate repaint];
+}
+
+void MediaPlayerPrivate::createQTMovieView()
+{
+ detachQTMovieView();
+
+ if (!m_player->m_parentWidget || !m_qtMovie)
+ return;
+
+ static bool addedCustomMethods = false;
+ if (!addedCustomMethods) {
+ Class QTMovieContentViewClass = NSClassFromString(@"QTMovieContentView");
+ ASSERT(QTMovieContentViewClass);
+
+ Method mainThreadSetNeedsDisplayMethod = class_getInstanceMethod(QTMovieContentViewClass, @selector(_mainThreadSetNeedsDisplay));
+ ASSERT(mainThreadSetNeedsDisplayMethod);
+
+ method_setImplementation(mainThreadSetNeedsDisplayMethod, reinterpret_cast<IMP>(mainThreadSetNeedsDisplay));
+ addedCustomMethods = true;
+ }
+
+ m_qtMovieView.adoptNS([[QTMovieView alloc] init]);
+ setRect(m_player->rect());
+ NSView* parentView = static_cast<ScrollView*>(m_player->m_parentWidget)->getDocumentView();
+ [parentView addSubview:m_qtMovieView.get()];
+#ifdef BUILDING_ON_TIGER
+ // setDelegate: isn't a public call in Tiger, so use performSelector to keep the compiler happy
+ [m_qtMovieView.get() performSelector:@selector(setDelegate:) withObject:m_objcObserver.get()];
+#else
+ [m_qtMovieView.get() setDelegate:m_objcObserver.get()];
+#endif
+ [m_qtMovieView.get() setMovie:m_qtMovie.get()];
+ [m_qtMovieView.get() setControllerVisible:NO];
+ [m_qtMovieView.get() setPreservesAspectRatio:NO];
+ // the area not covered by video should be transparent
+ [m_qtMovieView.get() setFillColor:[NSColor clearColor]];
+ wkQTMovieViewSetDrawSynchronously(m_qtMovieView.get(), YES);
+}
+
+void MediaPlayerPrivate::detachQTMovieView()
+{
+ if (m_qtMovieView) {
+#ifdef BUILDING_ON_TIGER
+ // setDelegate: isn't a public call in Tiger, so use performSelector to keep the compiler happy
+ [m_qtMovieView.get() performSelector:@selector(setDelegate:) withObject:nil];
+#else
+ [m_qtMovieView.get() setDelegate:nil];
+#endif
+ [m_qtMovieView.get() removeFromSuperview];
+ m_qtMovieView = nil;
+ }
+}
+
+QTTime MediaPlayerPrivate::createQTTime(float time) const
+{
+ if (!m_qtMovie)
+ return QTMakeTime(0, 600);
+ long timeScale = [[m_qtMovie.get() attributeForKey:QTMovieTimeScaleAttribute] longValue];
+ return QTMakeTime(time * timeScale, timeScale);
+}
+
+void MediaPlayerPrivate::load(const String& url)
+{
+ if (m_networkState != MediaPlayer::Loading) {
+ m_networkState = MediaPlayer::Loading;
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != MediaPlayer::DataUnavailable) {
+ m_readyState = MediaPlayer::DataUnavailable;
+ m_player->readyStateChanged();
+ }
+ cancelSeek();
+ m_endPointTimer.stop();
+
+ [m_objcObserver.get() setDelayCallbacks:YES];
+
+ createQTMovie(url);
+ if (m_player->visible())
+ createQTMovieView();
+
+ [m_objcObserver.get() loadStateChanged:nil];
+ [m_objcObserver.get() setDelayCallbacks:NO];
+}
+
+void MediaPlayerPrivate::play()
+{
+ if (!m_qtMovie)
+ return;
+ m_startedPlaying = true;
+ [m_objcObserver.get() setDelayCallbacks:YES];
+ [m_qtMovie.get() setRate:m_player->rate()];
+ [m_objcObserver.get() setDelayCallbacks:NO];
+ startEndPointTimerIfNeeded();
+}
+
+void MediaPlayerPrivate::pause()
+{
+ if (!m_qtMovie)
+ return;
+ m_startedPlaying = false;
+ [m_objcObserver.get() setDelayCallbacks:YES];
+ [m_qtMovie.get() stop];
+ [m_objcObserver.get() setDelayCallbacks:NO];
+ m_endPointTimer.stop();
+}
+
+float MediaPlayerPrivate::duration() const
+{
+ if (!m_qtMovie)
+ return 0;
+ QTTime time = [m_qtMovie.get() duration];
+ if (time.flags == kQTTimeIsIndefinite)
+ return numeric_limits<float>::infinity();
+ return static_cast<float>(time.timeValue) / time.timeScale;
+}
+
+float MediaPlayerPrivate::currentTime() const
+{
+ if (!m_qtMovie)
+ return 0;
+ QTTime time = [m_qtMovie.get() currentTime];
+ return min(static_cast<float>(time.timeValue) / time.timeScale, m_endTime);
+}
+
+void MediaPlayerPrivate::seek(float time)
+{
+ cancelSeek();
+
+ if (!m_qtMovie)
+ return;
+
+ if (time > duration())
+ time = duration();
+
+ m_seekTo = time;
+ if (maxTimeLoaded() >= m_seekTo)
+ doSeek();
+ else
+ m_seekTimer.start(0, 0.5f);
+}
+
+void MediaPlayerPrivate::doSeek()
+{
+ QTTime qttime = createQTTime(m_seekTo);
+ // setCurrentTime generates several event callbacks, update afterwards
+ [m_objcObserver.get() setDelayCallbacks:YES];
+ float oldRate = [m_qtMovie.get() rate];
+ [m_qtMovie.get() setRate:0];
+ [m_qtMovie.get() setCurrentTime:qttime];
+ float timeAfterSeek = currentTime();
+ // restore playback only if not at end, othewise QTMovie will loop
+ if (timeAfterSeek < duration() && timeAfterSeek < m_endTime)
+ [m_qtMovie.get() setRate:oldRate];
+ cancelSeek();
+ [m_objcObserver.get() setDelayCallbacks:NO];
+}
+
+void MediaPlayerPrivate::cancelSeek()
+{
+ m_seekTo = -1;
+ m_seekTimer.stop();
+}
+
+void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*)
+{
+ if (!m_qtMovie || !seeking() || currentTime() == m_seekTo) {
+ cancelSeek();
+ updateStates();
+ m_player->timeChanged();
+ return;
+ }
+
+ if (maxTimeLoaded() >= m_seekTo)
+ doSeek();
+ else {
+ MediaPlayer::NetworkState state = networkState();
+ if (state == MediaPlayer::Empty || state == MediaPlayer::Loaded) {
+ cancelSeek();
+ updateStates();
+ m_player->timeChanged();
+ }
+ }
+}
+
+void MediaPlayerPrivate::setEndTime(float time)
+{
+ m_endTime = time;
+ startEndPointTimerIfNeeded();
+}
+
+void MediaPlayerPrivate::startEndPointTimerIfNeeded()
+{
+ if (m_endTime < duration() && m_startedPlaying && !m_endPointTimer.isActive())
+ m_endPointTimer.startRepeating(endPointTimerInterval);
+}
+
+void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*)
+{
+ float time = currentTime();
+
+ // just do end for now
+ if (time >= m_endTime) {
+ pause();
+ didEnd();
+ }
+}
+
+bool MediaPlayerPrivate::paused() const
+{
+ if (!m_qtMovie)
+ return true;
+ return [m_qtMovie.get() rate] == 0;
+}
+
+bool MediaPlayerPrivate::seeking() const
+{
+ if (!m_qtMovie)
+ return false;
+ return m_seekTo >= 0;
+}
+
+IntSize MediaPlayerPrivate::naturalSize() const
+{
+ if (!m_qtMovie)
+ return IntSize();
+ return IntSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]);
+}
+
+bool MediaPlayerPrivate::hasVideo() const
+{
+ if (!m_qtMovie)
+ return false;
+ return [[m_qtMovie.get() attributeForKey:QTMovieHasVideoAttribute] boolValue];
+}
+
+void MediaPlayerPrivate::setVolume(float volume)
+{
+ if (!m_qtMovie)
+ return;
+ [m_qtMovie.get() setVolume:volume];
+}
+
+void MediaPlayerPrivate::setRate(float rate)
+{
+ if (!m_qtMovie)
+ return;
+ if (!paused())
+ [m_qtMovie.get() setRate:rate];
+}
+
+int MediaPlayerPrivate::dataRate() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return wkQTMovieDataRate(m_qtMovie.get());
+}
+
+
+float MediaPlayerPrivate::maxTimeBuffered() const
+{
+ // rtsp streams are not buffered
+ return m_isStreaming ? 0 : maxTimeLoaded();
+}
+
+float MediaPlayerPrivate::maxTimeSeekable() const
+{
+ // infinite duration means live stream
+ return isinf(duration()) ? 0 : maxTimeLoaded();
+}
+
+float MediaPlayerPrivate::maxTimeLoaded() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return wkQTMovieMaxTimeLoaded(m_qtMovie.get());
+}
+
+unsigned MediaPlayerPrivate::bytesLoaded() const
+{
+ float dur = duration();
+ if (!dur)
+ return 0;
+ return totalBytes() * maxTimeLoaded() / dur;
+}
+
+bool MediaPlayerPrivate::totalBytesKnown() const
+{
+ return totalBytes() > 0;
+}
+
+unsigned MediaPlayerPrivate::totalBytes() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return [[m_qtMovie.get() attributeForKey:QTMovieDataSizeAttribute] intValue];
+}
+
+void MediaPlayerPrivate::cancelLoad()
+{
+ // FIXME: Is there a better way to check for this?
+ if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
+ return;
+
+ detachQTMovieView();
+ m_qtMovie = nil;
+
+ updateStates();
+}
+
+void MediaPlayerPrivate::updateStates()
+{
+ MediaPlayer::NetworkState oldNetworkState = m_networkState;
+ MediaPlayer::ReadyState oldReadyState = m_readyState;
+
+ long loadState = m_qtMovie ? [[m_qtMovie.get() attributeForKey:QTMovieLoadStateAttribute] longValue] : static_cast<long>(QTMovieLoadStateError);
+
+ if (loadState >= QTMovieLoadStateLoaded && m_networkState < MediaPlayer::LoadedMetaData) {
+ unsigned enabledTrackCount;
+ disableUnsupportedTracks(enabledTrackCount);
+ // FIXME: We should differentiate between load errors and decode errors <rdar://problem/5605692>
+ if (!enabledTrackCount)
+ loadState = QTMovieLoadStateError;
+ }
+
+ // "Loaded" is reserved for fully buffered movies, never the case when streaming
+ if (loadState >= QTMovieLoadStateComplete && !m_isStreaming) {
+ if (m_networkState < MediaPlayer::Loaded)
+ m_networkState = MediaPlayer::Loaded;
+ m_readyState = MediaPlayer::CanPlayThrough;
+ } else if (loadState >= QTMovieLoadStatePlaythroughOK) {
+ if (m_networkState < MediaPlayer::LoadedFirstFrame && !seeking())
+ m_networkState = MediaPlayer::LoadedFirstFrame;
+ m_readyState = MediaPlayer::CanPlayThrough;
+ } else if (loadState >= QTMovieLoadStatePlayable) {
+ if (m_networkState < MediaPlayer::LoadedFirstFrame && !seeking())
+ m_networkState = MediaPlayer::LoadedFirstFrame;
+ // FIXME: This might not work correctly in streaming case, <rdar://problem/5693967>
+ m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::CanPlay : MediaPlayer::DataUnavailable;
+ } else if (loadState >= QTMovieLoadStateLoaded) {
+ if (m_networkState < MediaPlayer::LoadedMetaData)
+ m_networkState = MediaPlayer::LoadedMetaData;
+ m_readyState = MediaPlayer::DataUnavailable;
+ } else if (loadState > QTMovieLoadStateError) {
+ if (m_networkState < MediaPlayer::Loading)
+ m_networkState = MediaPlayer::Loading;
+ m_readyState = MediaPlayer::DataUnavailable;
+ } else {
+ m_networkState = MediaPlayer::LoadFailed;
+ m_readyState = MediaPlayer::DataUnavailable;
+ }
+
+ if (seeking())
+ m_readyState = MediaPlayer::DataUnavailable;
+
+ if (m_networkState != oldNetworkState)
+ m_player->networkStateChanged();
+ if (m_readyState != oldReadyState)
+ m_player->readyStateChanged();
+}
+
+void MediaPlayerPrivate::loadStateChanged()
+{
+ updateStates();
+}
+
+void MediaPlayerPrivate::rateChanged()
+{
+ updateStates();
+}
+
+void MediaPlayerPrivate::sizeChanged()
+{
+}
+
+void MediaPlayerPrivate::timeChanged()
+{
+ updateStates();
+ m_player->timeChanged();
+}
+
+void MediaPlayerPrivate::didEnd()
+{
+ m_endPointTimer.stop();
+ m_startedPlaying = false;
+ updateStates();
+ m_player->timeChanged();
+}
+
+void MediaPlayerPrivate::setRect(const IntRect& r)
+{
+ if (!m_qtMovieView)
+ return;
+ // We don't really need the QTMovieView in any specific location so let's just get it out of the way
+ // where it won't intercept events or try to bring up the context menu.
+ IntRect farAwayButCorrectSize(r);
+ farAwayButCorrectSize.move(-1000000, -1000000);
+ [m_qtMovieView.get() setFrame:farAwayButCorrectSize];
+}
+
+void MediaPlayerPrivate::setVisible(bool b)
+{
+ if (b)
+ createQTMovieView();
+ else
+ detachQTMovieView();
+}
+
+void MediaPlayerPrivate::repaint()
+{
+ m_player->repaint();
+}
+
+void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
+{
+ if (context->paintingDisabled())
+ return;
+ NSView *view = m_qtMovieView.get();
+ if (view == nil)
+ return;
+ [m_objcObserver.get() setDelayCallbacks:YES];
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ context->save();
+ context->translate(r.x(), r.y() + r.height());
+ context->scale(FloatSize(1.0f, -1.0f));
+ IntRect paintRect(IntPoint(0, 0), IntSize(r.width(), r.height()));
+ NSGraphicsContext* newContext = [NSGraphicsContext graphicsContextWithGraphicsPort:context->platformContext() flipped:NO];
+ [view displayRectIgnoringOpacity:paintRect inContext:newContext];
+ context->restore();
+ END_BLOCK_OBJC_EXCEPTIONS;
+ [m_objcObserver.get() setDelayCallbacks:NO];
+}
+
+void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
+{
+ NSArray* fileTypes = [QTMovie movieFileTypes:QTIncludeCommonTypes];
+ int count = [fileTypes count];
+ for (int n = 0; n < count; n++) {
+ CFStringRef ext = reinterpret_cast<CFStringRef>([fileTypes objectAtIndex:n]);
+ RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
+ if (!uti)
+ continue;
+ RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
+ if (!mime)
+ continue;
+ types.add(mime.get());
+ }
+}
+
+bool MediaPlayerPrivate::isAvailable()
+{
+ SInt32 version;
+ OSErr result;
+ // This Carbon API is available in 64 bit too
+ result = Gestalt(gestaltQuickTime, &version);
+ if (result != noErr) {
+ LOG_ERROR("No QuickTime available. Disabling <video> and <audio> support.");
+ return false;
+ }
+ if (version < minimumQuickTimeVersion) {
+ LOG_ERROR("QuickTime version %x detected, at least %x required. Disabling <video> and <audio> support.", version, minimumQuickTimeVersion);
+ return false;
+ }
+ return true;
+}
+
+void MediaPlayerPrivate::disableUnsupportedTracks(unsigned& enabledTrackCount)
+{
+ if (!m_qtMovie) {
+ enabledTrackCount = 0;
+ return;
+ }
+
+ static HashSet<String>* allowedTrackTypes = 0;
+ if (!allowedTrackTypes) {
+ allowedTrackTypes = new HashSet<String>;
+ allowedTrackTypes->add(QTMediaTypeVideo);
+ allowedTrackTypes->add(QTMediaTypeSound);
+ allowedTrackTypes->add(QTMediaTypeText);
+ allowedTrackTypes->add(QTMediaTypeBase);
+ allowedTrackTypes->add("clcp");
+ allowedTrackTypes->add("sbtl");
+ }
+
+ NSArray *tracks = [m_qtMovie.get() tracks];
+
+ unsigned trackCount = [tracks count];
+ enabledTrackCount = trackCount;
+ for (unsigned trackIndex = 0; trackIndex < trackCount; trackIndex++) {
+ // Grab the track at the current index. If there isn't one there, then
+ // we can move onto the next one.
+ QTTrack *track = [tracks objectAtIndex:trackIndex];
+ if (!track)
+ continue;
+
+ // Check to see if the track is disabled already, we should move along.
+ // We don't need to re-disable it.
+ if (![track isEnabled])
+ continue;
+
+ // Grab the track's media. We're going to check to see if we need to
+ // disable the tracks. They could be unsupported.
+ QTMedia *trackMedia = [track media];
+ if (!trackMedia)
+ continue;
+
+ // Grab the media type for this track.
+ NSString *mediaType = [trackMedia attributeForKey:QTMediaTypeAttribute];
+ if (!mediaType)
+ continue;
+
+ // Test whether the media type is in our white list.
+ if (!allowedTrackTypes->contains(mediaType)) {
+ // If this track type is not allowed, then we need to disable it.
+ [track setEnabled:NO];
+ --enabledTrackCount;
+ }
+
+ // Disable chapter tracks. These are most likely to lead to trouble, as
+ // they will be composited under the video tracks, forcing QT to do extra
+ // work.
+ QTTrack *chapterTrack = [track performSelector:@selector(chapterlist)];
+ if (!chapterTrack)
+ continue;
+
+ // Try to grab the media for the track.
+ QTMedia *chapterMedia = [chapterTrack media];
+ if (!chapterMedia)
+ continue;
+
+ // Grab the media type for this track.
+ id chapterMediaType = [chapterMedia attributeForKey:QTMediaTypeAttribute];
+ if (!chapterMediaType)
+ continue;
+
+ // Check to see if the track is a video track. We don't care about
+ // other non-video tracks.
+ if (![chapterMediaType isEqual:QTMediaTypeVideo])
+ continue;
+
+ // Check to see if the track is already disabled. If it is, we
+ // should move along.
+ if (![chapterTrack isEnabled])
+ continue;
+
+ // Disable the evil, evil track.
+ [chapterTrack setEnabled:NO];
+ --enabledTrackCount;
+ }
+}
+
+}
+
+@implementation WebCoreMovieObserver
+
+- (id)initWithCallback:(MediaPlayerPrivate *)callback
+{
+ m_callback = callback;
+ return [super init];
+}
+
+- (void)disconnect
+{
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
+ m_callback = 0;
+}
+
+-(void)repaint
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0.];
+ else if (m_callback)
+ m_callback->repaint();
+}
+
+- (void)loadStateChanged:(NSNotification *)notification
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0];
+ else
+ m_callback->loadStateChanged();
+}
+
+- (void)rateChanged:(NSNotification *)notification
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0];
+ else
+ m_callback->rateChanged();
+}
+
+- (void)sizeChanged:(NSNotification *)notification
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0];
+ else
+ m_callback->sizeChanged();
+}
+
+- (void)timeChanged:(NSNotification *)notification
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0];
+ else
+ m_callback->timeChanged();
+}
+
+- (void)didEnd:(NSNotification *)notification
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0];
+ else
+ m_callback->didEnd();
+}
+
+- (void)setDelayCallbacks:(BOOL)shouldDelay
+{
+ m_delayCallbacks = shouldDelay;
+}
+
+@end
+
+#endif
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
new file mode 100644
index 0000000..5d90514
--- /dev/null
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov
+ *
+ * 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.
+ */
+
+#import "config.h"
+#import "SimpleFontData.h"
+
+#import "BlockExceptions.h"
+#import "Color.h"
+#import "FloatRect.h"
+#import "Font.h"
+#import "FontCache.h"
+#import "FontDescription.h"
+#import "SharedBuffer.h"
+#import "WebCoreSystemInterface.h"
+#import <ApplicationServices/ApplicationServices.h>
+#import <float.h>
+#import <unicode/uchar.h>
+#import <wtf/Assertions.h>
+#import <wtf/RetainPtr.h>
+
+@interface NSFont (WebAppKitSecretAPI)
+- (BOOL)_isFakeFixedPitch;
+@end
+
+namespace WebCore {
+
+const float smallCapsFontSizeMultiplier = 0.7f;
+const float contextDPI = 72.0f;
+static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (contextDPI / (contextDPI * unitsPerEm)); }
+
+bool initFontData(SimpleFontData* fontData)
+{
+ if (!fontData->m_font.m_cgFont)
+ return false;
+
+ ATSUStyle fontStyle;
+ if (ATSUCreateStyle(&fontStyle) != noErr)
+ return false;
+
+ ATSUFontID fontId = fontData->m_font.m_atsuFontID;
+ if (!fontId) {
+ ATSUDisposeStyle(fontStyle);
+ return false;
+ }
+
+ ATSUAttributeTag tag = kATSUFontTag;
+ ByteCount size = sizeof(ATSUFontID);
+ ATSUFontID *valueArray[1] = {&fontId};
+ OSStatus status = ATSUSetAttributes(fontStyle, 1, &tag, &size, (void* const*)valueArray);
+ if (status != noErr) {
+ ATSUDisposeStyle(fontStyle);
+ return false;
+ }
+
+ if (wkGetATSStyleGroup(fontStyle, &fontData->m_styleGroup) != noErr) {
+ ATSUDisposeStyle(fontStyle);
+ return false;
+ }
+
+ ATSUDisposeStyle(fontStyle);
+
+ return true;
+}
+
+static NSString *webFallbackFontFamily(void)
+{
+ static RetainPtr<NSString> webFallbackFontFamily = nil;
+ if (!webFallbackFontFamily)
+ webFallbackFontFamily = [[NSFont systemFontOfSize:16.0f] familyName];
+ return webFallbackFontFamily.get();
+}
+
+#if !ERROR_DISABLED
+#ifdef __LP64__
+static NSString* pathFromFont(NSFont*)
+{
+ // FMGetATSFontRefFromFont is not available in 64-bit. As pathFromFont is only used for debugging
+ // purposes, returning nil is acceptable.
+ return nil;
+}
+#else
+static NSString* pathFromFont(NSFont *font)
+{
+ ATSFontRef atsFont = FMGetATSFontRefFromFont(wkGetNSFontATSUFontId(font));
+ FSRef fileRef;
+
+#ifndef BUILDING_ON_TIGER
+ OSStatus status = ATSFontGetFileReference(atsFont, &fileRef);
+ if (status != noErr)
+ return nil;
+#else
+ FSSpec oFile;
+ OSStatus status = ATSFontGetFileSpecification(atsFont, &oFile);
+ if (status != noErr)
+ return nil;
+
+ status = FSpMakeFSRef(&oFile, &fileRef);
+ if (status != noErr)
+ return nil;
+#endif
+
+ UInt8 filePathBuffer[PATH_MAX];
+ status = FSRefMakePath(&fileRef, filePathBuffer, PATH_MAX);
+ if (status == noErr)
+ return [NSString stringWithUTF8String:(const char*)filePathBuffer];
+
+ return nil;
+}
+#endif // __LP64__
+#endif // !ERROR_DISABLED
+
+void SimpleFontData::platformInit()
+{
+ m_styleGroup = 0;
+ m_ATSUStyleInitialized = false;
+ m_ATSUMirrors = false;
+ m_checkedShapesArabic = false;
+ m_shapesArabic = false;
+
+ m_syntheticBoldOffset = m_font.m_syntheticBold ? 1.0f : 0.f;
+
+ bool failedSetup = false;
+ if (!initFontData(this)) {
+ // Ack! Something very bad happened, like a corrupt font.
+ // Try looking for an alternate 'base' font for this renderer.
+
+ // Special case hack to use "Times New Roman" in place of "Times".
+ // "Times RO" is a common font whose family name is "Times".
+ // It overrides the normal "Times" family font.
+ // It also appears to have a corrupt regular variant.
+ NSString *fallbackFontFamily;
+ if ([[m_font.font() familyName] isEqual:@"Times"])
+ fallbackFontFamily = @"Times New Roman";
+ else
+ fallbackFontFamily = webFallbackFontFamily();
+
+ // Try setting up the alternate font.
+ // This is a last ditch effort to use a substitute font when something has gone wrong.
+#if !ERROR_DISABLED
+ RetainPtr<NSFont> initialFont = m_font.font();
+#endif
+ m_font.setFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toFamily:fallbackFontFamily]);
+#if !ERROR_DISABLED
+ NSString *filePath = pathFromFont(initialFont.get());
+ if (!filePath)
+ filePath = @"not known";
+#endif
+ if (!initFontData(this)) {
+ if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
+ // OK, couldn't setup Times New Roman as an alternate to Times, fallback
+ // on the system font. If this fails we have no alternative left.
+ m_font.setFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toFamily:webFallbackFontFamily()]);
+ if (!initFontData(this)) {
+ // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
+ LOG_ERROR("unable to initialize with font %@ at %@", initialFont.get(), filePath);
+ failedSetup = true;
+ }
+ } else {
+ // We tried the requested font and the system font. No joy. We have to give up.
+ LOG_ERROR("unable to initialize with font %@ at %@", initialFont.get(), filePath);
+ failedSetup = true;
+ }
+ }
+
+ // Report the problem.
+ LOG_ERROR("Corrupt font detected, using %@ in place of %@ located at \"%@\".",
+ [m_font.font() familyName], [initialFont.get() familyName], filePath);
+ }
+
+ // If all else fails, try to set up using the system font.
+ // This is probably because Times and Times New Roman are both unavailable.
+ if (failedSetup) {
+ m_font.setFont([NSFont systemFontOfSize:[m_font.font() pointSize]]);
+ LOG_ERROR("failed to set up font, using system font %s", m_font.font());
+ initFontData(this);
+ }
+
+ int iAscent;
+ int iDescent;
+ int iLineGap;
+#ifdef BUILDING_ON_TIGER
+ wkGetFontMetrics(m_font.m_cgFont, &iAscent, &iDescent, &iLineGap, &m_unitsPerEm);
+#else
+ iAscent = CGFontGetAscent(m_font.m_cgFont);
+ iDescent = CGFontGetDescent(m_font.m_cgFont);
+ iLineGap = CGFontGetLeading(m_font.m_cgFont);
+ m_unitsPerEm = CGFontGetUnitsPerEm(m_font.m_cgFont);
+#endif
+
+ float pointSize = m_font.m_size;
+ float fAscent = scaleEmToUnits(iAscent, m_unitsPerEm) * pointSize;
+ float fDescent = -scaleEmToUnits(iDescent, m_unitsPerEm) * pointSize;
+ float fLineGap = scaleEmToUnits(iLineGap, m_unitsPerEm) * pointSize;
+
+ // We need to adjust Times, Helvetica, and Courier to closely match the
+ // vertical metrics of their Microsoft counterparts that are the de facto
+ // web standard. The AppKit adjustment of 20% is too big and is
+ // incorrectly added to line spacing, so we use a 15% adjustment instead
+ // and add it to the ascent.
+ NSString *familyName = [m_font.font() familyName];
+ if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
+ fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
+
+ m_ascent = lroundf(fAscent);
+ m_descent = lroundf(fDescent);
+ m_lineGap = lroundf(fLineGap);
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ // Hack Hiragino line metrics to allow room for marked text underlines.
+ // <rdar://problem/5386183>
+ if (m_descent < 3 && m_lineGap >= 3 && [familyName hasPrefix:@"Hiragino"]) {
+ m_lineGap -= 3 - m_descent;
+ m_descent = 3;
+ }
+
+ // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font.
+ // Unfortunately, NSFont will round this for us so we don't quite get the right value.
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
+ if (xGlyph) {
+ NSRect xBox = [m_font.font() boundingRectForGlyph:xGlyph];
+ // Use the maximum of either width or height because "x" is nearly square
+ // 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));
+ } else
+ m_xHeight = [m_font.font() xHeight];
+}
+
+void SimpleFontData::platformDestroy()
+{
+ if (m_styleGroup)
+ wkReleaseStyleGroup(m_styleGroup);
+
+ if (m_ATSUStyleInitialized)
+ ATSUDisposeStyle(m_ATSUStyle);
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ if (isCustomFont()) {
+ FontPlatformData smallCapsFontData(m_font);
+ smallCapsFontData.m_size = smallCapsFontData.m_size * smallCapsFontSizeMultiplier;
+ m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
+ } else {
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ float size = [m_font.font() pointSize] * smallCapsFontSizeMultiplier;
+ FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toSize:size]);
+
+ // AppKit resets the type information (screen/printer) when you convert a font to a different size.
+ // We have to fix up the font that we're handed back.
+ smallCapsFont.setFont(fontDescription.usePrinterFont() ? [smallCapsFont.font() printerFont] : [smallCapsFont.font() screenFont]);
+
+ if (smallCapsFont.font()) {
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_font.font()];
+
+ if (m_font.m_syntheticBold)
+ fontTraits |= NSBoldFontMask;
+ if (m_font.m_syntheticOblique)
+ fontTraits |= NSItalicFontMask;
+
+ NSFontTraitMask smallCapsFontTraits = [fontManager traitsOfFont:smallCapsFont.font()];
+ smallCapsFont.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(smallCapsFontTraits & NSBoldFontMask);
+ smallCapsFont.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(smallCapsFontTraits & NSItalicFontMask);
+
+ m_smallCapsFontData = FontCache::getCachedFontData(&smallCapsFont);
+ }
+ END_BLOCK_OBJC_EXCEPTIONS;
+ }
+ }
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ NSString *string = [[NSString alloc] initWithCharactersNoCopy:(UniChar*)characters length:length freeWhenDone:NO];
+ NSCharacterSet *set = [[m_font.font() coveredCharacterSet] invertedSet];
+ bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
+ [string release];
+ return result;
+}
+
+void SimpleFontData::determinePitch()
+{
+ NSFont* f = m_font.font();
+ // Special case Osaka-Mono.
+ // According to <rdar://problem/3999467>, we should treat Osaka-Mono as fixed pitch.
+ // Note that the AppKit does not report Osaka-Mono as fixed pitch.
+
+ // Special case MS-PGothic.
+ // According to <rdar://problem/4032938>, we should not treat MS-PGothic as fixed pitch.
+ // Note that AppKit does report MS-PGothic as fixed pitch.
+
+ // Special case MonotypeCorsiva
+ // According to <rdar://problem/5454704>, we should not treat MonotypeCorsiva as fixed pitch.
+ // Note that AppKit does report MonotypeCorsiva as fixed pitch.
+
+ NSString *name = [f fontName];
+ m_treatAsFixedPitch = ([f isFixedPitch] || [f _isFakeFixedPitch] ||
+ [name caseInsensitiveCompare:@"Osaka-Mono"] == NSOrderedSame) &&
+ [name caseInsensitiveCompare:@"MS-PGothic"] != NSOrderedSame &&
+ [name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame;
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ NSFont* font = m_font.font();
+ float pointSize = m_font.m_size;
+ CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
+ CGSize advance;
+ if (!wkGetGlyphTransformedAdvances(m_font.m_cgFont, font, &m, &glyph, &advance)) {
+ LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize);
+ advance.width = 0;
+ }
+ return advance.width + m_syntheticBoldOffset;
+}
+
+void SimpleFontData::checkShapesArabic() const
+{
+ ASSERT(!m_checkedShapesArabic);
+
+ m_checkedShapesArabic = true;
+
+ ATSUFontID fontID = m_font.m_atsuFontID;
+ if (!fontID) {
+ LOG_ERROR("unable to get ATSUFontID for %@", m_font.font());
+ return;
+ }
+
+ // This function is called only on fonts that contain Arabic glyphs. Our
+ // heuristic is that if such a font has a glyph metamorphosis table, then
+ // it includes shaping information for Arabic.
+ FourCharCode tables[] = { 'morx', 'mort' };
+ for (unsigned i = 0; i < sizeof(tables) / sizeof(tables[0]); ++i) {
+ ByteCount tableSize;
+ OSStatus status = ATSFontGetTable(fontID, tables[i], 0, 0, 0, &tableSize);
+ if (status == noErr) {
+ m_shapesArabic = true;
+ return;
+ }
+
+ if (status != kATSInvalidFontTableAccess)
+ LOG_ERROR("ATSFontGetTable failed (%d)", status);
+ }
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/AffineTransformQt.cpp b/WebCore/platform/graphics/qt/AffineTransformQt.cpp
new file mode 100644
index 0000000..8bd5c87
--- /dev/null
+++ b/WebCore/platform/graphics/qt/AffineTransformQt.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * 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 "AffineTransform.h"
+
+#include "IntRect.h"
+#include "FloatRect.h"
+
+namespace WebCore {
+
+AffineTransform::AffineTransform()
+ : m_transform()
+{
+}
+
+AffineTransform::AffineTransform(double a, double b, double c, double d, double tx, double ty)
+ : m_transform(a, b, c, d, tx, ty)
+{
+}
+
+AffineTransform::AffineTransform(const QMatrix& matrix)
+ : m_transform(matrix)
+{
+}
+
+void AffineTransform::setMatrix(double a, double b, double c, double d, double tx, double ty)
+{
+ m_transform.setMatrix(a, b, c, d, tx, ty);
+}
+
+void AffineTransform::map(double x, double y, double* x2, double* y2) const
+{
+ qreal tx2, ty2;
+ m_transform.map(qreal(x), qreal(y), &tx2, &ty2);
+ *x2 = tx2;
+ *y2 = ty2;
+}
+
+IntRect AffineTransform::mapRect(const IntRect& rect) const
+{
+ return m_transform.mapRect(rect);
+}
+
+FloatRect AffineTransform::mapRect(const FloatRect& rect) const
+{
+ return m_transform.mapRect(rect);
+}
+
+bool AffineTransform::isIdentity() const
+{
+ return m_transform.isIdentity();
+}
+
+double AffineTransform::a() const
+{
+ return m_transform.m11();
+}
+
+void AffineTransform::setA(double a)
+{
+ m_transform.setMatrix(a, b(), c(), d(), e(), f());
+}
+
+double AffineTransform::b() const
+{
+ return m_transform.m12();
+}
+
+void AffineTransform::setB(double b)
+{
+ m_transform.setMatrix(a(), b, c(), d(), e(), f());
+}
+
+double AffineTransform::c() const
+{
+ return m_transform.m21();
+}
+
+void AffineTransform::setC(double c)
+{
+ m_transform.setMatrix(a(), b(), c, d(), e(), f());
+}
+
+double AffineTransform::d() const
+{
+ return m_transform.m22();
+}
+
+void AffineTransform::setD(double d)
+{
+ m_transform.setMatrix(a(), b(), c(), d, e(), f());
+}
+
+double AffineTransform::e() const
+{
+ return m_transform.dx();
+}
+
+void AffineTransform::setE(double e)
+{
+ m_transform.setMatrix(a(), b(), c(), d(), e, f());
+}
+
+double AffineTransform::f() const
+{
+ return m_transform.dy();
+}
+
+void AffineTransform::setF(double f)
+{
+ m_transform.setMatrix(a(), b(), c(), d(), e(), f);
+}
+
+void AffineTransform::reset()
+{
+ m_transform.reset();
+}
+
+AffineTransform& AffineTransform::scale(double sx, double sy)
+{
+ m_transform.scale(sx, sy);
+ return *this;
+}
+
+AffineTransform& AffineTransform::rotate(double d)
+{
+ m_transform.rotate(d);
+ return *this;
+}
+
+AffineTransform& AffineTransform::translate(double tx, double ty)
+{
+ m_transform.translate(tx, ty);
+ return *this;
+}
+
+AffineTransform& AffineTransform::shear(double sx, double sy)
+{
+ m_transform.shear(sx, sy);
+ return *this;
+}
+
+double AffineTransform::det() const
+{
+ return m_transform.det();
+}
+
+AffineTransform AffineTransform::inverse() const
+{
+ if(!isInvertible())
+ return AffineTransform();
+
+ return m_transform.inverted();
+}
+
+AffineTransform::operator QMatrix() const
+{
+ return m_transform;
+}
+
+bool AffineTransform::operator==(const AffineTransform& other) const
+{
+ return m_transform == other.m_transform;
+}
+
+AffineTransform& AffineTransform::operator*=(const AffineTransform& other)
+{
+ m_transform *= other.m_transform;
+ return *this;
+}
+
+AffineTransform AffineTransform::operator*(const AffineTransform& other)
+{
+ return m_transform * other.m_transform;
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ColorQt.cpp b/WebCore/platform/graphics/qt/ColorQt.cpp
new file mode 100644
index 0000000..5d16740
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ColorQt.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 <QColor>
+
+namespace WebCore {
+
+Color::Color(const QColor& c)
+ : m_color(makeRGBA(c.red(), c.green(), c.blue(), c.alpha()))
+{
+ m_valid = c.isValid();
+}
+
+Color::operator QColor() const
+{
+ return QColor(red(), green(), blue(), alpha());
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/FloatPointQt.cpp b/WebCore/platform/graphics/qt/FloatPointQt.cpp
new file mode 100644
index 0000000..82093d8
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FloatPointQt.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 <QPointF>
+
+namespace WebCore {
+
+FloatPoint::FloatPoint(const QPointF& p)
+ : m_x(p.x())
+ , m_y(p.y())
+{
+}
+
+FloatPoint::operator QPointF() const
+{
+ return QPointF(m_x, m_y);
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/FloatRectQt.cpp b/WebCore/platform/graphics/qt/FloatRectQt.cpp
new file mode 100644
index 0000000..1c918e3
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FloatRectQt.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 <QRectF>
+
+namespace WebCore {
+
+FloatRect::FloatRect(const QRectF& r)
+ : m_location(r.topLeft())
+ , m_size(r.width()
+ , r.height())
+{
+}
+
+FloatRect::operator QRectF() const
+{
+ return QRectF(x(), y(), width(), height());
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
new file mode 100644
index 0000000..8fb3fba
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#include "config.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "Font.h"
+
+namespace WebCore {
+
+bool FontCache::fontExists(const FontDescription &desc, const AtomicString& family)
+{
+ // try to construct a QFont inside WebCore::Font to see if we know about this font
+ FontDescription fnt(desc);
+ FontFamily fam;
+ fam.setFamily(family);
+ fnt.setFamily(fam);
+ return Font(fnt, /*letterSpacing*/0, /*wordSpacing*/0).font().exactMatch();
+}
+
+FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName)
+{
+ return 0;
+}
+
+SimpleFontData* FontCache::getCachedFontData(const FontPlatformData*)
+{
+ return 0;
+}
+
+FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription&)
+{
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..67193d4
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp
@@ -0,0 +1,56 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#include "config.h"
+#include "FontCustomPlatformData.h"
+
+#include "FontPlatformData.h"
+#include "SharedBuffer.h"
+#include <QFontDatabase>
+
+namespace WebCore {
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+ QFontDatabase::removeApplicationFont(handle);
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic)
+{
+ FontPlatformData result;
+ result.handle = handle;
+ return result;
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ ASSERT_ARG(buffer, buffer);
+
+ int id = QFontDatabase::addApplicationFontFromData(QByteArray(buffer->data(), buffer->size()));
+ if (id == -1)
+ return 0;
+ FontCustomPlatformData *data = new FontCustomPlatformData;
+ data->handle = id;
+ return data;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/WebCore/platform/graphics/qt/FontCustomPlatformData.h
new file mode 100644
index 0000000..b7a2b15
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#ifndef FontCustomPlatformData_h_
+#define FontCustomPlatformData_h_
+
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+class FontPlatformData;
+
+struct FontCustomPlatformData : Noncopyable {
+ ~FontCustomPlatformData();
+
+ int handle; // for use with QFontDatabase::addApplicationFont/removeApplicationFont
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic);
+};
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer);
+
+} // namespace WebCore
+
+#endif // FontCustomPlatformData_h_
diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h
new file mode 100644
index 0000000..7daf6ed
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#ifndef FontPlatformData_h
+#define FontPlatformData_h
+
+namespace WebCore {
+
+class FontPlatformData
+{
+public:
+ // this is only used for custom loaded fonts and represents the id handle passed to
+ // QFontDatabase::addApplicationFont/removeApplicationFont
+ int handle;
+};
+
+} // namespace WebCore
+
+#endif // FontPlatformData_h
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
new file mode 100644
index 0000000..29b63bf
--- /dev/null
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -0,0 +1,651 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#include "config.h"
+#include "Font.h"
+#include "FontDescription.h"
+#include "FontSelector.h"
+
+#include "GraphicsContext.h"
+#include <QTextLayout>
+#include <QPainter>
+#include <QFontMetrics>
+#include <QFontInfo>
+#include <qalgorithms.h>
+#include <qdebug.h>
+
+#include <limits.h>
+namespace WebCore {
+
+#if QT_VERSION >= 0x040400
+
+Font::Font()
+ : m_letterSpacing(0)
+ , m_wordSpacing(0)
+ , m_font()
+ , m_scFont()
+{
+ QFontMetrics metrics(m_font);
+ m_spaceWidth = metrics.width(QLatin1Char(' '));
+}
+
+Font::Font(const FontDescription& description, short letterSpacing, short wordSpacing)
+ : m_fontDescription(description)
+ , m_letterSpacing(letterSpacing)
+ , m_wordSpacing(wordSpacing)
+{
+ const FontFamily* family = &description.family();
+ QString familyName;
+ while (family) {
+ familyName += family->family();
+ family = family->next();
+ if (family)
+ familyName += QLatin1Char(',');
+ }
+
+ m_font.setFamily(familyName);
+ m_font.setPixelSize(qRound(description.computedSize()));
+ m_font.setItalic(description.italic());
+ if (description.bold()) {
+ // Qt's Bold is 75, Webkit is 63.
+ m_font.setWeight(QFont::Bold);
+ } else {
+ m_font.setWeight(description.weight());
+ }
+ bool smallCaps = description.smallCaps();
+ m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
+
+ QFontMetrics metrics = QFontMetrics(m_font);
+ m_spaceWidth = metrics.width(QLatin1Char(' '));
+
+ if (wordSpacing)
+ m_font.setWordSpacing(wordSpacing);
+ if (letterSpacing)
+ m_font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
+}
+
+void Font::setWordSpacing(short s)
+{
+ m_font.setWordSpacing(s);
+ m_wordSpacing = s;
+}
+void Font::setLetterSpacing(short s)
+{
+ m_font.setLetterSpacing(QFont::AbsoluteSpacing, s);
+ m_letterSpacing = s;
+}
+
+
+static QString qstring(const TextRun& run)
+{
+ QString string((QChar *)run.characters(), run.length());
+ QChar *uc = string.data();
+ for (int i = 0; i < string.length(); ++i) {
+ if (Font::treatAsSpace(uc[i].unicode()))
+ uc[i] = 0x20;
+ else if (Font::treatAsZeroWidthSpace(uc[i].unicode()))
+ uc[i] = 0x200c;
+ }
+ return string;
+}
+
+
+static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
+{
+ int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
+ if (style.padding())
+ flags |= Qt::TextJustificationForced;
+ layout->setFlags(flags);
+ layout->beginLayout();
+ QTextLine line = layout->createLine();
+ line.setLineWidth(INT_MAX/256);
+ if (style.padding())
+ line.setLineWidth(line.naturalTextWidth() + style.padding());
+ layout->endLayout();
+ return line;
+}
+
+void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ if (to < 0)
+ to = run.length();
+ QPainter *p = ctx->platformContext();
+ Color color = ctx->fillColor();
+ p->setPen(QColor(color));
+
+ QString string = qstring(run);
+
+ if (from > 0 || to < run.length()) {
+ QTextLayout layout(string, m_font);
+ QTextLine line = setupLayout(&layout, run);
+ float x1 = line.cursorToX(from);
+ float x2 = line.cursorToX(to);
+ if (x2 < x1)
+ qSwap(x1, x2);
+
+ QFontMetrics fm(m_font);
+ int ascent = fm.ascent();
+ QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
+
+ p->save();
+ p->setClipRect(clip.toRect());
+ QPointF pt(point.x(), point.y() - ascent);
+ line.draw(p, pt);
+ p->restore();
+ return;
+ }
+
+ p->setFont(m_font);
+
+ QPointF pt(point.x(), point.y());
+ int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
+ p->drawText(pt, string, flags, run.padding());
+}
+
+int Font::width(const TextRun& run) const
+{
+ if (!run.length())
+ return 0;
+ QString string = qstring(run);
+ int w = QFontMetrics(m_font).width(string);
+ // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
+ if (treatAsSpace(run[0]))
+ w -= m_wordSpacing;
+
+ return w + run.padding();
+}
+
+float Font::floatWidth(const TextRun& run) const
+{
+ return width(run);
+}
+
+int Font::offsetForPosition(const TextRun& run, int position, bool /*includePartialGlyphs*/) const
+{
+ QString string = qstring(run);
+ QTextLayout layout(string, m_font);
+ QTextLine line = setupLayout(&layout, run);
+ return line.xToCursor(position);
+}
+
+FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const
+{
+ QString string = qstring(run);
+ QTextLayout layout(string, m_font);
+ QTextLine line = setupLayout(&layout, run);
+
+ float x1 = line.cursorToX(from);
+ float x2 = line.cursorToX(to);
+ if (x2 < x1)
+ qSwap(x1, x2);
+
+ return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
+}
+
+#else
+
+
+struct TextRunComponent {
+ TextRunComponent() : font(0) {}
+ TextRunComponent(const UChar *start, int length, bool rtl, const QFont *font, int offset, bool sc = false);
+ TextRunComponent(int spaces, bool rtl, const QFont *font, int offset);
+
+ inline bool isSpace() const { return spaces != 0; }
+
+ QString string;
+ const QFont *font;
+ int width;
+ int offset;
+ int spaces;
+};
+
+TextRunComponent::TextRunComponent(const UChar *start, int length, bool rtl, const QFont *f, int o, bool sc)
+ : string(reinterpret_cast<const QChar*>(start), length)
+ , font(f)
+ , offset(o)
+ , spaces(0)
+{
+ if (sc)
+ string = string.toUpper();
+ string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
+ width = QFontMetrics(*font).width(string);
+}
+
+TextRunComponent::TextRunComponent(int s, bool rtl, const QFont *f, int o)
+ : string(s, QLatin1Char(' '))
+ , font(f)
+ , offset(o)
+ , spaces(s)
+{
+ string.prepend(rtl ? QChar(0x202e) : QChar(0x202d));
+ width = spaces * QFontMetrics(*font).width(QLatin1Char(' '));
+}
+
+
+Font::Font()
+ : m_letterSpacing(0)
+ , m_wordSpacing(0)
+ , m_font()
+ , m_scFont()
+{
+ QFontMetrics metrics(m_font);
+ m_spaceWidth = metrics.width(QLatin1Char(' '));
+ qreal pointsize = m_font.pointSizeF();
+ if (pointsize > 0)
+ m_scFont.setPointSizeF(pointsize*0.7);
+ else
+ m_scFont.setPixelSize(qRound(m_font.pixelSize()*.7));
+}
+
+Font::Font(const FontDescription& description, short letterSpacing, short wordSpacing)
+ : m_fontDescription(description)
+ , m_letterSpacing(letterSpacing)
+ , m_wordSpacing(wordSpacing)
+{
+ const FontFamily* family = &description.family();
+ QString familyName;
+ while (family) {
+ familyName += family->family();
+ family = family->next();
+ if (family)
+ familyName += QLatin1Char(',');
+ }
+
+ m_font.setFamily(familyName);
+ m_font.setPixelSize(qRound(description.computedSize()));
+ m_font.setItalic(description.italic());
+ if (description.bold()) {
+ // Qt's Bold is 75, Webkit is 63.
+ m_font.setWeight(QFont::Bold);
+ } else {
+ m_font.setWeight(description.weight());
+ }
+ QFontMetrics metrics = QFontMetrics(m_font);
+ m_spaceWidth = metrics.width(QLatin1Char(' '));
+ m_scFont = m_font;
+ m_scFont.setPixelSize(qRound(description.computedSize()*.7));
+}
+
+void Font::setWordSpacing(short s)
+{
+ m_wordSpacing = s;
+}
+void Font::setLetterSpacing(short s)
+{
+ m_letterSpacing = s;
+}
+
+static int generateComponents(Vector<TextRunComponent, 1024>* components, const Font &font, const TextRun &run)
+{
+// qDebug() << "generateComponents" << QString((const QChar *)run.characters(), run.length());
+ int letterSpacing = font.letterSpacing();
+ int wordSpacing = font.wordSpacing();
+ bool smallCaps = font.fontDescription().smallCaps();
+ int padding = run.padding();
+ int numSpaces = 0;
+ if (padding) {
+ for (int i = 0; i < run.length(); i++)
+ if (Font::treatAsSpace(run[i]))
+ ++numSpaces;
+ }
+
+ int offset = 0;
+ const QFont *f = &font.font();
+ if (letterSpacing || smallCaps) {
+ // need to draw every letter on it's own
+ int start = 0;
+ if (Font::treatAsSpace(run[0])) {
+ int add = 0;
+ if (numSpaces) {
+ add = padding/numSpaces;
+ padding -= add;
+ --numSpaces;
+ }
+ components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
+ offset += add + letterSpacing + components->last().width;
+ start = 1;
+// qDebug() << "space at 0" << offset;
+ } else if (smallCaps) {
+ f = (QChar::category(run[0]) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
+ }
+ for (int i = 1; i < run.length(); ++i) {
+ uint ch = run[i];
+ if (QChar(ch).isHighSurrogate() && QChar(run[i-1]).isLowSurrogate())
+ ch = QChar::surrogateToUcs4(ch, run[i-1]);
+ if (QChar(ch).isLowSurrogate() || QChar::category(ch) == QChar::Mark_NonSpacing)
+ continue;
+ if (Font::treatAsSpace(run[i])) {
+ int add = 0;
+// qDebug() << " treatAsSpace:" << i << start;
+ if (i - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, i - start,
+ run.rtl(),
+ f, offset, f == &font.scFont()));
+ offset += components->last().width + letterSpacing;
+// qDebug() << " appending(1) " << components->last().string << components->last().width;
+ }
+ if (numSpaces) {
+ add = padding/numSpaces;
+ padding -= add;
+ --numSpaces;
+ }
+ components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
+ offset += wordSpacing + add + components->last().width + letterSpacing;
+ start = i + 1;
+ continue;
+ } else if (!letterSpacing) {
+// qDebug() << i << char(run[i]) << (QChar::category(ch) == QChar::Letter_Lowercase) <<
+// QFontInfo(*f).pointSizeF();
+ if (QChar::category(ch) == QChar::Letter_Lowercase) {
+ if (f == &font.scFont())
+ continue;
+ } else {
+ if (f == &font.font())
+ continue;
+ }
+ }
+ if (i - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, i - start,
+ run.rtl(),
+ f, offset, f == &font.scFont()));
+ offset += components->last().width + letterSpacing;
+// qDebug() << " appending(2) " << components->last().string << components->last().width;
+ }
+ if (smallCaps)
+ f = (QChar::category(ch) == QChar::Letter_Lowercase ? &font.scFont() : &font.font());
+ start = i;
+ }
+ if (run.length() - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, run.length() - start,
+ run.rtl(),
+ f, offset, f == &font.scFont()));
+ offset += components->last().width;
+// qDebug() << " appending(3) " << components->last().string << components->last().width;
+ }
+ offset += letterSpacing;
+ } else {
+ int start = 0;
+ for (int i = 0; i < run.length(); ++i) {
+ if (Font::treatAsSpace(run[i])) {
+ if (i - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, i - start,
+ run.rtl(),
+ f, offset));
+ offset += components->last().width;
+ }
+ int add = 0;
+ if (numSpaces) {
+ add = padding/numSpaces;
+ padding -= add;
+ --numSpaces;
+ }
+ components->append(TextRunComponent(1, run.rtl(), &font.font(), offset));
+ offset += add + components->last().width;
+ if (i)
+ offset += wordSpacing;
+ start = i + 1;
+ }
+ }
+ if (run.length() - start > 0) {
+ components->append(TextRunComponent(run.characters() + start, run.length() - start,
+ run.rtl(),
+ f, offset));
+ offset += components->last().width;
+ }
+ }
+ return offset;
+}
+
+void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ if (to < 0)
+ to = run.length();
+ QPainter *p = ctx->platformContext();
+ Color color = ctx->fillColor();
+ p->setPen(QColor(color));
+
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ if (from > 0 || to < run.length()) {
+ FloatRect clip = selectionRectForText(run,
+ IntPoint(qRound(point.x()), qRound(point.y())),
+ QFontMetrics(m_font).height(), from, to);
+ QRectF rect(clip.x(), clip.y() - ascent(), clip.width(), clip.height());
+ p->save();
+ p->setClipRect(rect.toRect());
+ }
+
+ if (run.rtl()) {
+ for (int i = 0; i < components.size(); ++i) {
+ if (!components.at(i).isSpace()) {
+ p->setFont(*components.at(i).font);
+ QPointF pt(point.x() + w - components.at(i).offset - components.at(i).width, point.y());
+ p->drawText(pt, components.at(i).string);
+ }
+ }
+ } else {
+ for (int i = 0; i < components.size(); ++i) {
+ if (!components.at(i).isSpace()) {
+ p->setFont(*components.at(i).font);
+ QPointF pt(point.x() + components.at(i).offset, point.y());
+ p->drawText(pt, components.at(i).string);
+ }
+ }
+ }
+ if (from > 0 || to < run.length())
+ p->restore();
+}
+
+int Font::width(const TextRun& run) const
+{
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+// qDebug() << " width=" << w;
+ return w;
+}
+
+float Font::floatWidth(const TextRun& run) const
+{
+ return width(run);
+}
+
+int Font::offsetForPosition(const TextRun& run, int position, bool includePartialGlyphs) const
+{
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ int offset = 0;
+ if (run.rtl()) {
+ for (int i = 0; i < components.size(); ++i) {
+ int xe = w - components.at(i).offset;
+ int xs = xe - components.at(i).width;
+ if (position >= xs) {
+ QTextLayout layout(components.at(i).string, *components.at(i).font);
+ layout.beginLayout();
+ QTextLine l = layout.createLine();
+ if (!l.isValid())
+ return offset;
+
+ l.setLineWidth(INT_MAX/256);
+ layout.endLayout();
+
+ if (position - xs >= l.width())
+ return offset;
+ int cursor = l.xToCursor(position - xs);
+ if (cursor > 1)
+ --cursor;
+ return offset + cursor;
+ } else {
+ offset += components.at(i).string.length() - 1;
+ }
+ }
+ } else {
+ for (int i = 0; i < components.size(); ++i) {
+ int xs = components.at(i).offset;
+ int xe = xs + components.at(i).width;
+ if (position <= xe) {
+ QTextLayout layout(components.at(i).string, *components.at(i).font);
+ layout.beginLayout();
+ QTextLine l = layout.createLine();
+ if (!l.isValid())
+ return offset;
+
+ l.setLineWidth(INT_MAX/256);
+ layout.endLayout();
+
+ if (position - xs >= l.width())
+ return offset + components.at(i).string.length() - 1;
+ int cursor = l.xToCursor(position - xs);
+ if (cursor > 1)
+ --cursor;
+ return offset + cursor;
+ } else {
+ offset += components.at(i).string.length() - 1;
+ }
+ }
+ }
+ return run.length();
+}
+
+static float cursorToX(const Vector<TextRunComponent, 1024>& components, int width, bool rtl, int cursor)
+{
+ int start = 0;
+ for (int i = 0; i < components.size(); ++i) {
+ if (start + components.at(i).string.length() - 1 < cursor) {
+ start += components.at(i).string.length() - 1;
+ continue;
+ }
+ int xs = components.at(i).offset;
+ if (rtl)
+ xs = width - xs - components.at(i).width;
+ QTextLayout layout(components.at(i).string, *components.at(i).font);
+ layout.beginLayout();
+ QTextLine l = layout.createLine();
+ if (!l.isValid())
+ return 0;
+
+ l.setLineWidth(INT_MAX/256);
+ layout.endLayout();
+
+ return xs + l.cursorToX(cursor - start + 1);
+ }
+ return width;
+}
+
+FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt,
+ int h, int from, int to) const
+{
+ Vector<TextRunComponent, 1024> components;
+ int w = generateComponents(&components, *this, run);
+
+ if (from == 0 && to == run.length())
+ return FloatRect(pt.x(), pt.y(), w, h);
+
+ float x1 = cursorToX(components, w, run.rtl(), from);
+ float x2 = cursorToX(components, w, run.rtl(), to);
+ if (x2 < x1)
+ qSwap(x1, x2);
+
+ return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
+}
+#endif
+
+
+Font::~Font()
+{
+}
+
+Font::Font(const Font& other)
+ : m_fontDescription(other.m_fontDescription)
+ , m_letterSpacing(other.m_letterSpacing)
+ , m_wordSpacing(other.m_wordSpacing)
+ , m_font(other.m_font)
+ , m_scFont(other.m_scFont)
+ , m_spaceWidth(other.m_spaceWidth)
+{
+}
+
+Font& Font::operator=(const Font& other)
+{
+ m_fontDescription = other.m_fontDescription;
+ m_letterSpacing = other.m_letterSpacing;
+ m_wordSpacing = other.m_wordSpacing;
+ m_font = other.m_font;
+ m_scFont = other.m_scFont;
+ m_spaceWidth = other.m_spaceWidth;
+ return *this;
+}
+
+bool Font::operator==(const Font& other) const
+{
+ return m_fontDescription == other.m_fontDescription
+ && m_letterSpacing == other.m_letterSpacing
+ && m_wordSpacing == other.m_wordSpacing
+ && m_font == other.m_font
+ && m_scFont == other.m_scFont
+ && m_spaceWidth == other.m_spaceWidth;
+}
+
+void Font::update(PassRefPtr<FontSelector>) const
+{
+ // don't think we need this
+}
+
+
+bool Font::isFixedPitch() const
+{
+ return QFontInfo(m_font).fixedPitch();
+}
+
+// Metrics that we query the FontFallbackList for.
+int Font::ascent() const
+{
+ return QFontMetrics(m_font).ascent();
+}
+
+int Font::descent() const
+{
+ return QFontMetrics(m_font).descent();
+}
+
+int Font::lineSpacing() const
+{
+ return QFontMetrics(m_font).lineSpacing();
+}
+
+float Font::xHeight() const
+{
+ return QFontMetrics(m_font).xHeight();
+}
+
+unsigned Font::unitsPerEm() const
+{
+ return 1; // FIXME!
+}
+
+int Font::spaceWidth() const
+{
+ return m_spaceWidth;
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp b/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp
new file mode 100644
index 0000000..220807e
--- /dev/null
+++ b/WebCore/platform/graphics/qt/GlyphPageTreeNodeQt.cpp
@@ -0,0 +1,31 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#include "config.h"
+#include "GlyphPageTreeNode.h"
+
+namespace WebCore {
+
+void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData)
+{
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
new file mode 100644
index 0000000..ec35d96
--- /dev/null
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -0,0 +1,943 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org>
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "AffineTransform.h"
+#include "Path.h"
+#include "Color.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "Font.h"
+#include "Pen.h"
+#include "NotImplemented.h"
+
+#include <QStack>
+#include <QPainter>
+#include <QPolygonF>
+#include <QPainterPath>
+#include <QPaintDevice>
+#include <QPixmap>
+#include <QDebug>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+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:
+ return QPainter::CompositionMode_SourceOver;
+ case CompositeHighlight:
+ return QPainter::CompositionMode_SourceOver;
+ case CompositePlusLighter:
+ return QPainter::CompositionMode_SourceOver;
+ }
+
+ return QPainter::CompositionMode_SourceOver;
+}
+
+static inline Qt::PenCapStyle toQtLineCap(LineCap lc)
+{
+ switch (lc) {
+ case ButtCap:
+ return Qt::FlatCap;
+ case RoundCap:
+ return Qt::RoundCap;
+ case SquareCap:
+ return Qt::SquareCap;
+ }
+
+ return Qt::FlatCap;
+}
+
+static inline Qt::PenJoinStyle toQtLineJoin(LineJoin lj)
+{
+ switch (lj) {
+ case MiterJoin:
+ return Qt::SvgMiterJoin;
+ case RoundJoin:
+ return Qt::RoundJoin;
+ case BevelJoin:
+ return Qt::BevelJoin;
+ }
+
+ return Qt::MiterJoin;
+}
+
+static Qt::PenStyle toQPenStyle(StrokeStyle style)
+{
+ switch (style) {
+ case NoStroke:
+ return Qt::NoPen;
+ break;
+ case SolidStroke:
+ return Qt::SolidLine;
+ break;
+ case DottedStroke:
+ return Qt::DotLine;
+ break;
+ case DashedStroke:
+ return Qt::DashLine;
+ break;
+ }
+ qWarning("couldn't recognize the pen style");
+ return Qt::NoPen;
+}
+
+struct TransparencyLayer
+{
+ TransparencyLayer(const QPainter* p, const QRect &rect)
+ : pixmap(rect.width(), rect.height())
+ {
+ offset = rect.topLeft();
+ pixmap.fill(Qt::transparent);
+ painter.begin(&pixmap);
+ painter.translate(-offset);
+ painter.setPen(p->pen());
+ painter.setBrush(p->brush());
+ painter.setTransform(p->transform(), true);
+ painter.setOpacity(p->opacity());
+ painter.setFont(p->font());
+ painter.setCompositionMode(p->compositionMode());
+ painter.setClipPath(p->clipPath());
+ }
+
+ TransparencyLayer()
+ {
+ }
+
+ QPixmap pixmap;
+ QPoint offset;
+ QPainter painter;
+ qreal opacity;
+private:
+ TransparencyLayer(const TransparencyLayer &) {}
+ TransparencyLayer & operator=(const TransparencyLayer &) { return *this; }
+};
+
+struct TextShadow
+{
+ TextShadow()
+ : x(0)
+ , y(0)
+ , blur(0)
+ {
+ }
+
+ bool isNull() { return !x && !y && !blur; }
+
+ int x;
+ int y;
+ int blur;
+
+ Color color;
+};
+
+class GraphicsContextPlatformPrivate
+{
+public:
+ GraphicsContextPlatformPrivate(QPainter* painter);
+ ~GraphicsContextPlatformPrivate();
+
+ inline QPainter* p()
+ {
+ if (layers.isEmpty()) {
+ if (redirect)
+ return redirect;
+
+ return painter;
+ } else
+ return &layers.top()->painter;
+ }
+
+ QPaintDevice* device;
+
+ QStack<TransparencyLayer *> layers;
+ QPainter* redirect;
+
+ TextShadow shadow;
+
+ // Only used by SVG for now.
+ QPainterPath currentPath;
+
+private:
+ QPainter* painter;
+};
+
+
+GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p)
+{
+ painter = p;
+ device = painter ? painter->device() : 0;
+ redirect = 0;
+
+ // FIXME: Maybe only enable in SVG mode?
+ if (painter)
+ painter->setRenderHint(QPainter::Antialiasing);
+}
+
+GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
+{
+}
+
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate(context))
+{
+ setPaintingDisabled(!context);
+ if (context) {
+ // Make sure the context starts in sync with our state.
+ setPlatformFillColor(fillColor());
+ setPlatformStrokeColor(strokeColor());
+ }
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ while(!m_data->layers.isEmpty())
+ endTransparencyLayer();
+
+ destroyGraphicsContextPrivate(m_common);
+ delete m_data;
+}
+
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+ return m_data->p();
+}
+
+AffineTransform GraphicsContext::getCTM() const
+{
+ return platformContext()->combinedMatrix();
+}
+
+void GraphicsContext::savePlatformState()
+{
+ m_data->p()->save();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ m_data->p()->restore();
+}
+
+/* FIXME: DISABLED WHILE MERGING BACK FROM UNITY
+void GraphicsContext::drawTextShadow(const TextRun& run, const IntPoint& point, const FontStyle& style)
+{
+ if (paintingDisabled())
+ return;
+
+ if (m_data->shadow.isNull())
+ return;
+
+ TextShadow* shadow = &m_data->shadow;
+
+ if (shadow->blur <= 0) {
+ Pen p = pen();
+ setPen(shadow->color);
+ font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y));
+ setPen(p);
+ } else {
+ const int thickness = shadow->blur;
+ // FIXME: OPTIMIZE: limit the area to only the actually painted area + 2*thickness
+ const int w = m_data->p()->device()->width();
+ const int h = m_data->p()->device()->height();
+ const QRgb color = qRgb(255, 255, 255);
+ const QRgb bgColor = qRgb(0, 0, 0);
+ QImage image(QSize(w, h), QImage::Format_ARGB32);
+ image.fill(bgColor);
+ QPainter p;
+
+ Pen curPen = pen();
+ p.begin(&image);
+ setPen(color);
+ m_data->redirect = &p;
+ font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y));
+ m_data->redirect = 0;
+ p.end();
+ setPen(curPen);
+
+ int md = thickness * thickness; // max-dist^2
+
+ // blur map/precalculated shadow-decay
+ float* bmap = (float*) alloca(sizeof(float) * (md + 1));
+ for (int n = 0; n <= md; n++) {
+ float f;
+ f = n / (float) (md + 1);
+ f = 1.0 - f * f;
+ bmap[n] = f;
+ }
+
+ float factor = 0.0; // maximal potential opacity-sum
+ for (int n = -thickness; n <= thickness; n++) {
+ for (int m = -thickness; m <= thickness; m++) {
+ int d = n * n + m * m;
+ if (d <= md)
+ factor += bmap[d];
+ }
+ }
+
+ // alpha map
+ float* amap = (float*) alloca(sizeof(float) * (h * w));
+ memset(amap, 0, h * w * (sizeof(float)));
+
+ for (int j = thickness; j<h-thickness; j++) {
+ for (int i = thickness; i<w-thickness; i++) {
+ QRgb col = image.pixel(i,j);
+ if (col == bgColor)
+ continue;
+
+ float g = qAlpha(col);
+ g = g / 255;
+
+ for (int n = -thickness; n <= thickness; n++) {
+ for (int m = -thickness; m <= thickness; m++) {
+ int d = n * n + m * m;
+ if (d > md)
+ continue;
+
+ float f = bmap[d];
+ amap[(i + m) + (j + n) * w] += (g * f);
+ }
+ }
+ }
+ }
+
+ QImage res(QSize(w,h),QImage::Format_ARGB32);
+ int r = shadow->color.red();
+ int g = shadow->color.green();
+ int b = shadow->color.blue();
+ int a1 = shadow->color.alpha();
+
+ // arbitratry factor adjustment to make shadows more solid.
+ factor = 1.333 / factor;
+
+ for (int j = 0; j < h; j++) {
+ for (int i = 0; i < w; i++) {
+ int a = (int) (amap[i + j * w] * factor * a1);
+ if (a > 255)
+ a = 255;
+
+ res.setPixel(i,j, qRgba(r, g, b, a));
+ }
+ }
+
+ m_data->p()->drawImage(0, 0, res, 0, 0, -1, -1, Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::PreferDither);
+ }
+}
+*/
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->drawRect(rect);
+}
+
+// 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)
+{
+ if (paintingDisabled())
+ return;
+
+ FloatPoint p1 = point1;
+ FloatPoint p2 = point2;
+
+ adjustLineToPixelBoundaries(p1, p2, strokeThickness(), strokeStyle());
+ m_data->p()->drawLine(p1, p2);
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->drawEllipse(rect);
+}
+
+void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
+{
+ if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())
+ return;
+
+ m_data->p()->drawArc(rect, startAngle * 16, angleSpan * 16);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ if (npoints <= 1)
+ return;
+
+ QPolygonF polygon(npoints);
+
+ for (size_t i = 0; i < npoints; i++)
+ polygon[i] = points[i];
+
+ QPainter *p = m_data->p();
+ p->save();
+ p->setRenderHint(QPainter::Antialiasing, shouldAntialias);
+ p->drawConvexPolygon(polygon);
+ p->restore();
+}
+
+void GraphicsContext::fillRect(const IntRect& rect, const Color& c)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->fillRect(rect, QColor(c));
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->fillRect(rect, QColor(c));
+}
+
+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;
+
+ Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight);
+ m_data->p()->fillPath(*path.platformPath(), QColor(color));
+}
+
+void GraphicsContext::beginPath()
+{
+ m_data->currentPath = QPainterPath();
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ m_data->currentPath = *(path.platformPath());
+}
+
+void GraphicsContext::setFillRule(WindRule rule)
+{
+ m_data->currentPath.setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
+}
+
+PlatformPath* GraphicsContext::currentPath()
+{
+ return &m_data->currentPath;
+}
+
+void GraphicsContext::clip(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ if (p->clipRegion().isEmpty())
+ p->setClipRect(rect);
+ else p->setClipRect(rect, Qt::IntersectClip);
+}
+
+/**
+ * Focus ring handling is not handled here. Qt style in
+ * RenderTheme handles drawing focus on widgets which
+ * need it.
+ */
+void setFocusRingColorChangeFunction(void (*)()) { }
+Color focusRingColor() { return Color(0, 0, 0); }
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ const Vector<IntRect>& rects = focusRingRects();
+ unsigned rectCount = rects.size();
+
+ if (rects.size() == 0)
+ return;
+
+ QPainter *p = m_data->p();
+
+ const QPen oldPen = p->pen();
+ const QBrush oldBrush = p->brush();
+
+ QPen nPen = p->pen();
+ nPen.setColor(color);
+ p->setBrush(Qt::NoBrush);
+ nPen.setStyle(Qt::DotLine);
+ p->setPen(nPen);
+#if 0
+ // FIXME How do we do a bounding outline with Qt?
+ QPainterPath path;
+ for (int i = 0; i < rectCount; ++i)
+ path.addRect(QRectF(rects[i]));
+ QPainterPathStroker stroker;
+ QPainterPath newPath = stroker.createStroke(path);
+ p->strokePath(newPath, nPen);
+#else
+ for (int i = 0; i < rectCount; ++i)
+ p->drawRect(QRectF(rects[i]));
+#endif
+ p->setPen(oldPen);
+ p->setBrush(oldBrush);
+}
+
+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& frect)
+{
+ QRectF rect(frect);
+ rect = m_data->p()->deviceMatrix().mapRect(rect);
+
+ QRect result = rect.toRect(); //round it
+ return FloatRect(QRectF(result));
+}
+
+void GraphicsContext::setShadow(const IntSize& pos, int blur, const Color &color)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->shadow.x = pos.width();
+ m_data->shadow.y = pos.height();
+ m_data->shadow.blur = blur;
+ m_data->shadow.color = color;
+}
+
+void GraphicsContext::clearShadow()
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->shadow = TextShadow();
+}
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+ if (paintingDisabled())
+ return;
+
+ int x, y, w, h;
+ x = y = 0;
+ w = m_data->device->width();
+ h = m_data->device->height();
+
+ QPainter *p = m_data->p();
+ QRectF clip = p->clipPath().boundingRect();
+ bool ok;
+ QTransform transform = p->transform().inverted(&ok);
+ if (ok) {
+ QRectF deviceClip = transform.mapRect(clip);
+ x = int(qBound(qreal(0), deviceClip.x(), (qreal)w));
+ y = int(qBound(qreal(0), deviceClip.y(), (qreal)h));
+ w = int(qBound(qreal(0), deviceClip.width(), (qreal)w) + 2);
+ h = int(qBound(qreal(0), deviceClip.height(), (qreal)h) + 2);
+ }
+ TransparencyLayer * layer = new TransparencyLayer(m_data->p(), QRect(x, y, w, h));
+
+ layer->opacity = opacity;
+ m_data->layers.push(layer);
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+ if (paintingDisabled())
+ return;
+
+ TransparencyLayer *layer = m_data->layers.pop();
+ layer->painter.end();
+
+ QPainter *p = m_data->p();
+ p->save();
+ p->resetTransform();
+ p->setOpacity(layer->opacity);
+ p->drawPixmap(layer->offset, layer->pixmap);
+ p->restore();
+
+ delete layer;
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPainter::CompositionMode currentCompositionMode = p->compositionMode();
+ p->setCompositionMode(QPainter::CompositionMode_Source);
+ p->eraseRect(rect);
+ p->setCompositionMode(currentCompositionMode);
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect, float width)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPainterPath path;
+ path.addRect(rect);
+ QPen nPen = p->pen();
+ nPen.setWidthF(width);
+ p->strokePath(path, nPen);
+}
+
+void GraphicsContext::setLineCap(LineCap lc)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPen nPen = p->pen();
+ nPen.setCapStyle(toQtLineCap(lc));
+ p->setPen(nPen);
+}
+
+void GraphicsContext::setLineJoin(LineJoin lj)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPen nPen = p->pen();
+ nPen.setJoinStyle(toQtLineJoin(lj));
+ p->setPen(nPen);
+}
+
+void GraphicsContext::setMiterLimit(float limit)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPen nPen = p->pen();
+ nPen.setMiterLimit(limit);
+ p->setPen(nPen);
+}
+
+void GraphicsContext::setAlpha(float opacity)
+{
+ if (paintingDisabled())
+ return;
+ QPainter *p = m_data->p();
+ p->setOpacity(opacity);
+}
+
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->setCompositionMode(toQtCompositionMode(op));
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->setClipPath(*path.platformPath(), Qt::IntersectClip);
+}
+
+void GraphicsContext::clipOut(const Path& path)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QRectF clipBounds = p->clipPath().boundingRect();
+ QPainterPath clippedOut = *path.platformPath();
+ QPainterPath newClip;
+ newClip.setFillRule(Qt::OddEvenFill);
+ newClip.addRect(clipBounds);
+ newClip.addPath(clippedOut);
+
+ p->setClipPath(newClip, Qt::IntersectClip);
+}
+
+void GraphicsContext::translate(float x, float y)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->translate(x, y);
+}
+
+IntPoint GraphicsContext::origin()
+{
+ if (paintingDisabled())
+ return IntPoint();
+ const QTransform &transform = m_data->p()->transform();
+ return IntPoint(qRound(transform.dx()), qRound(transform.dy()));
+}
+
+void GraphicsContext::rotate(float radians)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->rotate(radians);
+}
+
+void GraphicsContext::scale(const FloatSize& s)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->scale(s.width(), s.height());
+}
+
+void GraphicsContext::clipOut(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QRectF clipBounds = p->clipPath().boundingRect();
+ QPainterPath newClip;
+ newClip.setFillRule(Qt::OddEvenFill);
+ newClip.addRect(clipBounds);
+ newClip.addRect(QRect(rect));
+
+ p->setClipPath(newClip, Qt::IntersectClip);
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QRectF clipBounds = p->clipPath().boundingRect();
+ QPainterPath newClip;
+ newClip.setFillRule(Qt::OddEvenFill);
+ newClip.addRect(clipBounds);
+ newClip.addEllipse(QRect(rect));
+
+ p->setClipPath(newClip, Qt::IntersectClip);
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
+ int thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ clip(rect);
+ QPainterPath path;
+
+ // Add outer ellipse
+ path.addEllipse(QRectF(rect.x(), rect.y(), rect.width(), rect.height()));
+
+ // Add inner ellipse.
+ path.addEllipse(QRectF(rect.x() + thickness, rect.y() + thickness,
+ rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
+
+ path.setFillRule(Qt::OddEvenFill);
+ m_data->p()->setClipPath(path, Qt::IntersectClip);
+}
+
+void GraphicsContext::concatCTM(const AffineTransform& transform)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->p()->setMatrix(transform, true);
+}
+
+void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformFont(const Font& aFont)
+{
+ if (paintingDisabled())
+ return;
+ m_data->p()->setFont(aFont.font());
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ QPainter *p = m_data->p();
+ QPen newPen(p->pen());
+ newPen.setColor(color);
+ p->setPen(newPen);
+}
+
+void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
+{
+ if (paintingDisabled())
+ return;
+ QPainter *p = m_data->p();
+ QPen newPen(p->pen());
+ newPen.setStyle(toQPenStyle(strokeStyle));
+ p->setPen(newPen);
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
+{
+ if (paintingDisabled())
+ return;
+ QPainter *p = m_data->p();
+ QPen newPen(p->pen());
+ newPen.setWidthF(thickness);
+ p->setPen(newPen);
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+ m_data->p()->setBrush(QBrush(color));
+}
+
+void GraphicsContext::setUseAntialiasing(bool enable)
+{
+ if (paintingDisabled())
+ return;
+ m_data->p()->setRenderHint(QPainter::Antialiasing, enable);
+}
+
+void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
+{
+ if (paintingDisabled())
+ return;
+ QPixmap pixmap = *buffer->pixmap();
+ if (pixmap.isNull())
+ return;
+ QPainter* painter = platformContext();
+ QPen currentPen = painter->pen();
+ qreal currentOpacity = painter->opacity();
+ QBrush currentBrush = painter->brush();
+ QBrush currentBackground = painter->background();
+ if (painter->isActive())
+ painter->end();
+ static_cast<QPainter*>(painter)->drawPixmap(r, pixmap);
+ painter->begin(&pixmap);
+ painter->setPen(currentPen);
+ painter->setBrush(currentBrush);
+ painter->setOpacity(currentOpacity);
+ painter->setBackground(currentBackground);
+}
+
+void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& dstRect)
+{
+ QPainter* painter = static_cast<QPainter*>(platformContext());
+ QPixmap px = *buffer->pixmap();
+ if (px.isNull())
+ return;
+ painter->drawPixmap(dstRect, px, srcRect);
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/IconQt.cpp b/WebCore/platform/graphics/qt/IconQt.cpp
new file mode 100644
index 0000000..c9c900b
--- /dev/null
+++ b/WebCore/platform/graphics/qt/IconQt.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * 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"
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qrect.h>
+#include <qglobal.h>
+
+namespace WebCore {
+
+Icon::Icon()
+ : RefCounted<Icon>(0)
+{
+}
+
+Icon::~Icon()
+{
+}
+
+PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+{
+ Icon *i = new Icon;
+ i->m_icon = QIcon(filename);
+ return PassRefPtr<Icon>(i);
+}
+
+void Icon::paint(GraphicsContext* ctx, const IntRect& rect)
+{
+ QPixmap px = m_icon.pixmap(rect.size());
+ QPainter *p = static_cast<QPainter*>(ctx->platformContext());
+ if (p && !px.isNull()) {
+ p->drawPixmap(rect.x(), rect.y(), px);
+ }
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
new file mode 100644
index 0000000..449677e
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * 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"
+
+#include <QPainter>
+#include <QPixmap>
+
+namespace WebCore {
+
+std::auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool grayScale)
+{
+ QPixmap px(size);
+ return std::auto_ptr<ImageBuffer>(new ImageBuffer(px));
+}
+
+ImageBuffer::ImageBuffer(const QPixmap& px)
+ : m_pixmap(px),
+ m_painter(0)
+{
+ m_painter = new QPainter(&m_pixmap);
+ m_context.set(new GraphicsContext(m_painter));
+}
+
+ImageBuffer::~ImageBuffer()
+{
+ delete m_painter;
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ if (!m_painter->isActive())
+ m_painter->begin(&m_pixmap);
+
+ return m_context.get();
+}
+
+QPixmap* ImageBuffer::pixmap() const
+{
+ if (!m_painter)
+ return &m_pixmap;
+ if (m_painter->isActive())
+ m_painter->end();
+ return &m_pixmap;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&)
+{
+ notImplemented();
+}
+
+}
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
new file mode 100644
index 0000000..44ab0d3
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2006 Friedemann Kleint <fkleint@trolltech.com>
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * 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 "ImageDecoderQt.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QBuffer>
+
+#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::ImageDecoderQt( )
+{
+}
+
+ImageDecoderQt::~ImageDecoderQt()
+{
+}
+
+bool ImageDecoderQt::hasFirstImageHeader() const
+{
+ return !m_imageList.empty() && m_imageList[0].m_imageState >= ImageHeaderValid;
+}
+
+void ImageDecoderQt::reset()
+{
+ m_failed = false;
+ m_imageList.clear();
+ m_pixmapCache.clear();
+ m_sizeAvailable = false;
+ m_loopCount = cAnimationNone;
+ m_size = IntSize(-1, -1);
+}
+
+void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived)
+{
+ reset();
+ ReadContext readContext(data, ReadContext::LoadIncrementally, m_imageList);
+
+ if (debugImageDecoderQt)
+ qDebug() << " setData " << data.size() << " image bytes, complete=" << allDataReceived;
+
+ const ReadContext::ReadResult readResult = readContext.read(allDataReceived);
+
+ 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()) {
+ m_sizeAvailable = true;
+ m_size = m_imageList[0].m_image.size();
+
+ if (readContext.reader()->supportsAnimation()) {
+ if (readContext.reader()->loopCount() != -1)
+ m_loopCount = readContext.reader()->loopCount();
+ else
+ m_loopCount = 0; //loop forever
+ }
+ }
+ break;
+ }
+}
+
+
+bool ImageDecoderQt::isSizeAvailable() const
+{
+ if (debugImageDecoderQt)
+ qDebug() << " ImageDecoderQt::isSizeAvailable() returns" << m_sizeAvailable;
+ return m_sizeAvailable;
+}
+
+int ImageDecoderQt::frameCount() const
+{
+ if (debugImageDecoderQt)
+ qDebug() << " ImageDecoderQt::frameCount() returns" << m_imageList.size();
+ return m_imageList.size();
+}
+
+
+int ImageDecoderQt::repetitionCount() const
+{
+ if (debugImageDecoderQt)
+ qDebug() << " ImageDecoderQt::repetitionCount() returns" << m_loopCount;
+ return m_loopCount;
+}
+
+
+bool ImageDecoderQt::supportsAlpha() const
+{
+ return hasFirstImageHeader() && m_imageList[0].m_image.hasAlphaChannel();
+}
+
+int ImageDecoderQt::duration(size_t index) const
+{
+ if (index >= m_imageList.size())
+ return 0;
+ return m_imageList[index].m_duration;
+}
+
+RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
+{
+ Q_ASSERT("use imageAtIndex instead");
+ return 0;
+}
+
+QPixmap* ImageDecoderQt::imageAtIndex(size_t index) const
+{
+ if (debugImageDecoderQt)
+ qDebug() << "ImageDecoderQt::imageAtIndex(" << index << ')';
+
+ if (index >= m_imageList.size())
+ return 0;
+
+ if (!m_pixmapCache.contains(index)) {
+ m_pixmapCache.insert(index,
+ QPixmap::fromImage(m_imageList[index].m_image));
+ }
+ return &m_pixmapCache[index];
+}
+
+void ImageDecoderQt::clearFrame(size_t index)
+{
+ if (m_imageList.size() < (int)index)
+ m_imageList[index].m_image = QImage();
+ m_pixmapCache.take(index);
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
new file mode 100644
index 0000000..32f91d1
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2006 Friedemann Kleint <fkleint@trolltech.com>
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * 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 ImageDecoderQt_h
+#define ImageDecoderQt_h
+
+#include "ImageDecoder.h"
+#include <QtGui/QImage>
+#include <QtGui/QPixmap>
+#include <QtCore/QList>
+#include <QtCore/QHash>
+
+namespace WebCore {
+
+
+class ImageDecoderQt : public ImageDecoder
+{
+ ImageDecoderQt(const ImageDecoderQt&);
+ ImageDecoderQt &operator=(const ImageDecoderQt&);
+public:
+ ImageDecoderQt();
+ ~ImageDecoderQt();
+
+ typedef Vector<char> IncomingData;
+
+ virtual void setData(const IncomingData& data, bool allDataReceived);
+
+ virtual bool isSizeAvailable() const;
+
+ virtual int frameCount() const;
+
+
+ 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;
+
+ void clearFrame(size_t index);
+private:
+ 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;
+ };
+
+ typedef QList<ImageData> ImageList;
+ ImageList m_imageList;
+ mutable QHash<int, QPixmap> m_pixmapCache;
+ int m_loopCount;
+};
+
+
+
+}
+
+#endif
+
diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp
new file mode 100644
index 0000000..206aee3
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "PlatformString.h"
+#include "GraphicsContext.h"
+#include "AffineTransform.h"
+#include "NotImplemented.h"
+#include "qwebsettings.h"
+
+#include <QPixmap>
+#include <QPainter>
+#include <QImage>
+#include <QImageReader>
+#if QT_VERSION >= 0x040300
+#include <QTransform>
+#endif
+
+#include <QDebug>
+
+#include <math.h>
+
+// This function loads resources into WebKit
+static QPixmap loadResourcePixmap(const char *name)
+{
+ const QString resource = name;
+
+ QPixmap pixmap;
+ if (resource == "missingImage")
+ pixmap = QWebSettings::webGraphic(QWebSettings::MissingImageGraphic);
+ else if (resource == "nullPlugin")
+ pixmap = QWebSettings::webGraphic(QWebSettings::MissingPluginGraphic);
+ else if (resource == "urlIcon")
+ pixmap = QWebSettings::webGraphic(QWebSettings::DefaultFaviconGraphic);
+ else if (resource == "textAreaResizeCorner")
+ pixmap = QWebSettings::webGraphic(QWebSettings::TextAreaResizeCornerGraphic);
+
+ return pixmap;
+}
+
+namespace WebCore {
+
+void FrameData::clear()
+{
+ if (m_frame) {
+ m_frame = 0;
+ m_duration = 0.0f;
+ m_hasAlpha = true;
+ }
+}
+
+
+
+// ================================================
+// Image Class
+// ================================================
+
+Image* Image::loadPlatformResource(const char* name)
+{
+ BitmapImage* img = new BitmapImage(loadResourcePixmap(name));
+ return img;
+}
+
+
+void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ notImplemented();
+}
+
+BitmapImage::BitmapImage(const QPixmap &pixmap, ImageObserver *observer)
+ : Image(observer)
+ , m_currentFrame(0)
+ , m_frames(0)
+ , m_frameTimer(0)
+ , m_repetitionCount(0)
+ , m_repetitionsComplete(0)
+ , m_isSolidColor(false)
+ , m_animatingImageType(true)
+ , m_animationFinished(false)
+ , m_allDataReceived(false)
+ , m_haveSize(false)
+ , m_sizeAvailable(false)
+ , m_decodedSize(0)
+{
+ m_pixmap = new QPixmap(pixmap);
+}
+
+void BitmapImage::initPlatformData()
+{
+ m_pixmap = 0;
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+ delete m_pixmap;
+ m_pixmap = 0;
+}
+
+// Drawing Routines
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
+ const FloatRect& src, CompositeOperator op)
+{
+ QPixmap* image = nativeImageForCurrentFrame();
+ if (!image)
+ return;
+
+ if (mayFillWithSolidColor()) {
+ fillWithSolidColor(ctxt, dst, solidColor(), op);
+ return;
+ }
+
+ IntSize selfSize = size();
+
+ ctxt->save();
+
+ // Set the compositing operation.
+ ctxt->setCompositeOperation(op);
+
+ QPainter* painter(ctxt->platformContext());
+
+ // Test using example site at
+ // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ painter->drawPixmap(dst, *image, src);
+
+ ctxt->restore();
+
+ startAnimation();
+}
+
+void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+{
+ QPixmap* framePixmap = nativeImageForCurrentFrame();
+ if (!framePixmap) // If it's too early we won't have an image yet.
+ return;
+
+ QPixmap pixmap = *framePixmap;
+ QRect tr = QRectF(tileRect).toRect();
+ if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) {
+ pixmap = pixmap.copy(tr);
+ }
+
+ if (patternTransform.isIdentity()) {
+ ctxt->save();
+ ctxt->setCompositeOperation(op);
+ QPainter* p = ctxt->platformContext();
+ p->setBrushOrigin(phase);
+ p->drawTiledPixmap(destRect, pixmap);
+ ctxt->restore();
+ } else {
+ QBrush b(pixmap);
+ b.setMatrix(patternTransform);
+ ctxt->save();
+ ctxt->setCompositeOperation(op);
+ QPainter* p = ctxt->platformContext();
+ p->setBrushOrigin(phase);
+ p->fillRect(destRect, b);
+ ctxt->restore();
+ }
+}
+
+void BitmapImage::checkForSolidColor()
+{
+ // FIXME: It's easy to implement this optimization. Just need to check the RGBA32 buffer to see if it is 1x1.
+ m_isSolidColor = false;
+}
+
+QPixmap* BitmapImage::getPixmap() const
+{
+ if (!m_pixmap)
+ return const_cast<BitmapImage*>(this)->frameAtIndex(0);
+ else
+ return m_pixmap;
+}
+
+}
+
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageSourceQt.cpp b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
new file mode 100644
index 0000000..84d503f
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ImageSourceQt.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * 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 <QImage>
+#include <qdebug.h>
+
+
+namespace WebCore {
+ enum ImageFormat { ImageFormat_None, ImageFormat_GIF, ImageFormat_PNG, ImageFormat_JPEG,
+ ImageFormat_BMP, ImageFormat_ICO, ImageFormat_XBM };
+
+ImageFormat detectImageFormat(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 ImageFormat_None;
+
+ 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 ImageFormat_GIF;
+
+ // Test for PNG.
+ if (uContents[0] == 0x89 &&
+ uContents[1] == 0x50 &&
+ uContents[2] == 0x4E &&
+ uContents[3] == 0x47)
+ return ImageFormat_PNG;
+
+ // JPEG
+ if (uContents[0] == 0xFF &&
+ uContents[1] == 0xD8 &&
+ uContents[2] == 0xFF)
+ return ImageFormat_JPEG;
+
+ // BMP
+ if (strncmp(contents, "BM", 2) == 0)
+ return ImageFormat_BMP;
+
+ // 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 ImageFormat_ICO;
+
+ // XBMs require 8 bytes of info.
+ if (length >= 8 && strncmp(contents, "#define ", 8) == 0)
+ return ImageFormat_XBM;
+
+ // Give up. We don't know what the heck this is.
+ return ImageFormat_None;
+}
+
+ImageDecoderQt* createDecoder(const SharedBuffer& data) {
+ if (detectImageFormat(data) != ImageFormat_None)
+ return new ImageDecoderQt();
+ return 0;
+}
+
+ImageSource::ImageSource()
+ : m_decoder(0)
+{
+}
+
+ImageSource::~ImageSource()
+{
+ delete m_decoder;
+}
+
+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);
+
+ if (!m_decoder)
+ return;
+
+ m_decoder->setData(data->buffer(), 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();
+}
+
+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) != 0);
+}
+
+void ImageSource::clear()
+{
+ delete m_decoder;
+ m_decoder = 0;
+}
+
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/IntPointQt.cpp b/WebCore/platform/graphics/qt/IntPointQt.cpp
new file mode 100644
index 0000000..f9d336a
--- /dev/null
+++ b/WebCore/platform/graphics/qt/IntPointQt.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 <QPoint>
+
+namespace WebCore {
+
+IntPoint::IntPoint(const QPoint& p)
+ : m_x(p.x())
+ , m_y(p.y())
+{
+}
+
+IntPoint::operator QPoint() const
+{
+ return QPoint(m_x, m_y);
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/IntRectQt.cpp b/WebCore/platform/graphics/qt/IntRectQt.cpp
new file mode 100644
index 0000000..ccc153e
--- /dev/null
+++ b/WebCore/platform/graphics/qt/IntRectQt.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 <QRect>
+
+namespace WebCore {
+
+IntRect::IntRect(const QRect& r)
+ : m_location(r.topLeft())
+ , m_size(r.width(), r.height())
+{
+}
+
+IntRect::operator QRect() const
+{
+ return QRect(x(), y(), width(), height());
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/IntSizeQt.cpp b/WebCore/platform/graphics/qt/IntSizeQt.cpp
new file mode 100644
index 0000000..4f2bf35
--- /dev/null
+++ b/WebCore/platform/graphics/qt/IntSizeQt.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 <QSize>
+
+#include "IntSize.h"
+
+namespace WebCore {
+
+IntSize::IntSize(const QSize& r)
+ : m_width(r.width())
+ , m_height(r.height())
+{
+}
+
+IntSize::operator QSize() const
+{
+ return QSize(width(), height());
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
new file mode 100644
index 0000000..240350f
--- /dev/null
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * 2006 Rob Buis <buis@kde.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 "PlatformString.h"
+#include "AffineTransform.h"
+#include <QPainterPath>
+#include <QMatrix>
+#include <QString>
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+namespace WebCore {
+
+Path::Path()
+ : m_path(new QPainterPath())
+{
+}
+
+Path::~Path()
+{
+ delete m_path;
+}
+
+Path::Path(const Path& other)
+ : m_path(new QPainterPath(*other.platformPath()))
+{
+}
+
+Path& Path::operator=(const Path& other)
+{
+ if (&other != this) {
+ delete m_path;
+ m_path = new QPainterPath(*other.platformPath());
+ }
+
+ return *this;
+}
+
+bool Path::contains(const FloatPoint& point, WindRule rule) const
+{
+ Qt::FillRule savedRule = m_path->fillRule();
+ m_path->setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
+
+ bool contains = m_path->contains(point);
+
+ m_path->setFillRule(savedRule);
+ return contains;
+}
+
+void Path::translate(const FloatSize& size)
+{
+ QMatrix matrix;
+ matrix.translate(size.width(), size.height());
+ *m_path = (*m_path) * matrix;
+}
+
+FloatRect Path::boundingRect() const
+{
+ return m_path->boundingRect();
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+ m_path->moveTo(point);
+}
+
+void Path::addLineTo(const FloatPoint& p)
+{
+ m_path->lineTo(p);
+}
+
+void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p)
+{
+ m_path->quadTo(cp, p);
+}
+
+void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p)
+{
+ m_path->cubicTo(cp1, cp2, p);
+}
+
+void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
+{
+ //FIXME: busted
+ qWarning("arcTo is busted");
+ m_path->arcTo(p1.x(), p1.y(), p2.x(), p2.y(), radius, 90);
+}
+
+void Path::closeSubpath()
+{
+ m_path->closeSubpath();
+}
+
+#define DEGREES(t) ((t) * 180.0 / M_PI)
+void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool anticlockwise)
+{
+ qreal xc = p.x();
+ qreal yc = p.y();
+ qreal radius = r;
+
+
+ //### HACK
+ // In Qt we don't switch the coordinate system for degrees
+ // and still use the 0,0 as bottom left for degrees so we need
+ // to switch
+ sar = -sar;
+ ear = -ear;
+ anticlockwise = !anticlockwise;
+ //end hack
+
+ float sa = DEGREES(sar);
+ float ea = DEGREES(ear);
+
+ double span = 0;
+
+ double xs = xc - radius;
+ double ys = yc - radius;
+ double width = radius*2;
+ double height = radius*2;
+
+ if (!anticlockwise && (ea < sa))
+ span += 360;
+ else if (anticlockwise && (sa < ea))
+ span -= 360;
+
+ // this is also due to switched coordinate system
+ // we would end up with a 0 span instead of 360
+ if (!(qFuzzyCompare(span + (ea - sa), 0.0) &&
+ qFuzzyCompare(qAbs(span), 360.0))) {
+ span += ea - sa;
+ }
+
+ m_path->moveTo(QPointF(xc + radius * cos(sar),
+ yc - radius * sin(sar)));
+
+ m_path->arcTo(xs, ys, width, height, sa, span);
+}
+
+void Path::addRect(const FloatRect& r)
+{
+ m_path->addRect(r.x(), r.y(), r.width(), r.height());
+}
+
+void Path::addEllipse(const FloatRect& r)
+{
+ m_path->addEllipse(r.x(), r.y(), r.width(), r.height());
+}
+
+void Path::clear()
+{
+ *m_path = QPainterPath();
+}
+
+bool Path::isEmpty() const
+{
+ return m_path->isEmpty();
+}
+
+String Path::debugString() const
+{
+ QString ret;
+ for (int i = 0; i < m_path->elementCount(); ++i) {
+ const QPainterPath::Element &cur = m_path->elementAt(i);
+
+ switch (cur.type) {
+ case QPainterPath::MoveToElement:
+ ret += QString("M %1 %2").arg(cur.x).arg(cur.y);
+ break;
+ case QPainterPath::LineToElement:
+ ret += QString("L %1 %2").arg(cur.x).arg(cur.y);
+ break;
+ case QPainterPath::CurveToElement:
+ {
+ const QPainterPath::Element &c1 = m_path->elementAt(i + 1);
+ const QPainterPath::Element &c2 = m_path->elementAt(i + 2);
+
+ Q_ASSERT(c1.type == QPainterPath::CurveToDataElement);
+ Q_ASSERT(c2.type == QPainterPath::CurveToDataElement);
+
+ ret += QString("C %1 %2 %3 %4 %5 %6").arg(cur.x).arg(cur.y).arg(c1.x).arg(c1.y).arg(c2.x).arg(c2.y);
+
+ i += 2;
+ break;
+ }
+ case QPainterPath::CurveToDataElement:
+ Q_ASSERT(false);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ PathElement pelement;
+ FloatPoint points[3];
+ pelement.points = points;
+ for (int i = 0; i < m_path->elementCount(); ++i) {
+ const QPainterPath::Element& cur = m_path->elementAt(i);
+
+ switch (cur.type) {
+ case QPainterPath::MoveToElement:
+ pelement.type = PathElementMoveToPoint;
+ pelement.points[0] = QPointF(cur);
+ function(info, &pelement);
+ break;
+ case QPainterPath::LineToElement:
+ pelement.type = PathElementAddLineToPoint;
+ pelement.points[0] = QPointF(cur);
+ function(info, &pelement);
+ break;
+ case QPainterPath::CurveToElement:
+ {
+ const QPainterPath::Element& c1 = m_path->elementAt(i + 1);
+ const QPainterPath::Element& c2 = m_path->elementAt(i + 2);
+
+ Q_ASSERT(c1.type == QPainterPath::CurveToDataElement);
+ Q_ASSERT(c2.type == QPainterPath::CurveToDataElement);
+
+ pelement.type = PathElementAddCurveToPoint;
+ pelement.points[0] = QPointF(cur);
+ pelement.points[1] = QPointF(c1);
+ pelement.points[2] = QPointF(c2);
+ function(info, &pelement);
+
+ i += 2;
+ break;
+ }
+ case QPainterPath::CurveToDataElement:
+ Q_ASSERT(false);
+ }
+ }
+}
+
+void Path::transform(const AffineTransform& transform)
+{
+ if (m_path) {
+ QMatrix mat = transform;
+ QPainterPath temp = mat.map(*m_path);
+ delete m_path;
+ m_path = new QPainterPath(temp);
+ }
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
new file mode 100644
index 0000000..1a45ce4
--- /dev/null
+++ b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2007 Trolltech ASA
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ This class provides all functionality needed for loading images, style sheets and html
+ pages from the web. It has a memory cache for these objects.
+*/
+#include "config.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+SimpleFontData::SimpleFontData(const FontPlatformData& font, bool customFont, bool loading, SVGFontData*)
+ : m_font(font), m_isCustomFont(customFont), m_isLoading(loading)
+{
+}
+
+SimpleFontData::~SimpleFontData()
+{
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ return true;
+}
+
+const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
+{
+ return this;
+}
+
+bool SimpleFontData::isSegmented() const
+{
+ return false;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/ColorSafari.cpp b/WebCore/platform/graphics/win/ColorSafari.cpp
new file mode 100644
index 0000000..e7fbf47
--- /dev/null
+++ b/WebCore/platform/graphics/win/ColorSafari.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 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.
+ * 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 "Color.h"
+
+#include "NotImplemented.h"
+#include <CoreGraphics/CGColor.h>
+#include <SafariTheme/SafariTheme.h>
+#include <wtf/Assertions.h>
+#include <wtf/RetainPtr.h>
+
+using namespace SafariTheme;
+
+namespace WebCore {
+
+typedef CGColorRef (APIENTRY*stCopyThemeColorPtr)(unsigned, SafariTheme::ThemeControlState);
+static const unsigned stFocusRingColorID = 4;
+
+static const unsigned aquaFocusRingColor = 0xFF7DADD9;
+
+static RGBA32 makeRGBAFromCGColor(CGColorRef c)
+{
+ const CGFloat* components = CGColorGetComponents(c);
+ return makeRGBA(255 * components[0], 255 * components[1], 255 * components[2], 255 * components[3]);
+}
+
+Color focusRingColor()
+{
+ static Color focusRingColor;
+ focusRingColor.isValid();
+
+ if (!focusRingColor.isValid()) {
+ if (HMODULE module = LoadLibrary(SAFARITHEMEDLL))
+ if (stCopyThemeColorPtr stCopyThemeColor = (stCopyThemeColorPtr)GetProcAddress(module, "STCopyThemeColor")) {
+ RetainPtr<CGColorRef> c(AdoptCF, stCopyThemeColor(stFocusRingColorID, SafariTheme::ActiveState));
+ focusRingColor = makeRGBAFromCGColor(c.get());
+ }
+ if (!focusRingColor.isValid())
+ focusRingColor = aquaFocusRingColor;
+ }
+
+ return focusRingColor;
+}
+
+void setFocusRingColorChangeFunction(void (*)())
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
new file mode 100644
index 0000000..8b59a48
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "SimpleFontData.h"
+#include "UniscribeController.h"
+#include <ApplicationServices/ApplicationServices.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+const int syntheticObliqueAngle = 14;
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs, const FloatPoint& point) const
+{
+ if (font->m_font.useGDI()) {
+ // FIXME: Support alpha blending.
+ // FIXME: Support text stroke/fill.
+ // FIXME: Support text shadow.
+ Color fillColor = graphicsContext->fillColor();
+ if (fillColor.alpha() == 0)
+ return;
+
+ // We have to convert CG's two-dimensional floating point advances to just horizontal integer advances.
+ Vector<int, 2048> gdiAdvances;
+ int totalWidth = 0;
+ for (int i = 0; i < numGlyphs; i++) {
+ gdiAdvances.append(lroundf(glyphBuffer.advanceAt(from + i)));
+ totalWidth += gdiAdvances[i];
+ }
+
+ // We put slop into this rect, since glyphs can overflow the ascent/descent bounds and the left/right edges.
+ int lineGap = font->lineGap();
+ IntRect textRect(point.x() - lineGap, point.y() - font->ascent() - lineGap, totalWidth + 2 * lineGap, font->lineSpacing());
+ HDC hdc = graphicsContext->getWindowsContext(textRect);
+ SelectObject(hdc, font->m_font.hfont());
+
+ // Set the correct color.
+ HDC textDrawingDC = hdc;
+ SetTextColor(hdc, RGB(fillColor.red(), fillColor.green(), fillColor.blue()));
+
+ SetBkMode(hdc, TRANSPARENT);
+ SetTextAlign(hdc, TA_LEFT | TA_BASELINE);
+
+ // Uniscribe gives us offsets to help refine the positioning of combining glyphs.
+ FloatSize translation = glyphBuffer.offsetAt(from);
+ if (translation.width() || translation.height()) {
+ XFORM xform;
+ xform.eM11 = 1.0;
+ xform.eM12 = 0;
+ xform.eM21 = 0;
+ xform.eM22 = 1.0;
+ xform.eDx = translation.width();
+ xform.eDy = translation.height();
+ ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
+ }
+ ExtTextOut(hdc, point.x(), point.y(), ETO_GLYPH_INDEX, 0, (WCHAR*)glyphBuffer.glyphs(from), numGlyphs, gdiAdvances.data());
+
+ graphicsContext->releaseWindowsContext(hdc, textRect);
+ return;
+ }
+
+ CGContextRef cgContext = graphicsContext->platformContext();
+
+ uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext);
+
+ const FontPlatformData& platformData = font->platformData();
+
+ CGContextSetFont(cgContext, platformData.cgFont());
+
+ CGAffineTransform matrix = CGAffineTransformIdentity;
+ matrix.b = -matrix.b;
+ matrix.d = -matrix.d;
+
+ if (platformData.syntheticOblique()) {
+ static float skew = -tanf(syntheticObliqueAngle * acosf(0) / 90.0f);
+ matrix = CGAffineTransformConcat(matrix, CGAffineTransformMake(1, 0, skew, 1, 0, 0));
+ }
+
+ // Uniscribe gives us offsets to help refine the positioning of combining glyphs.
+ FloatSize translation = glyphBuffer.offsetAt(from);
+ if (translation.width() || translation.height())
+ CGAffineTransformTranslate(matrix, translation.width(), translation.height());
+
+ CGContextSetTextMatrix(cgContext, matrix);
+
+ CGContextSetFontSize(cgContext, platformData.size());
+ CGContextSetTextPosition(cgContext, point.x(), point.y());
+ CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ if (font->m_syntheticBoldOffset) {
+ CGContextSetTextPosition(cgContext, point.x() + font->m_syntheticBoldOffset, point.y());
+ CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
+ }
+
+ wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp
new file mode 100644
index 0000000..1ee6818
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontCacheWin.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 <winsock2.h>
+#include "FontCache.h"
+#include "Font.h"
+#include "SimpleFontData.h"
+#include "StringHash.h"
+#include "UnicodeRange.h"
+#include <windows.h>
+#include <mlang.h>
+#if PLATFORM(CG)
+#include <ApplicationServices/ApplicationServices.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
+
+using std::min;
+
+namespace WebCore
+{
+
+void FontCache::platformInit()
+{
+#if PLATFORM(CG)
+ wkSetUpFontCache(1536 * 1024 * 4); // This size matches Mac.
+#endif
+}
+
+IMLangFontLink2* FontCache::getFontLinkInterface()
+{
+ static IMultiLanguage *multiLanguage;
+ if (!multiLanguage) {
+ if (CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_ALL, IID_IMultiLanguage, (void**)&multiLanguage) != S_OK)
+ return 0;
+ }
+
+ static IMLangFontLink2* langFontLink;
+ if (!langFontLink) {
+ if (multiLanguage->QueryInterface(&langFontLink) != S_OK)
+ return 0;
+ }
+
+ return langFontLink;
+}
+
+static int CALLBACK metaFileEnumProc(HDC hdc, HANDLETABLE* table, CONST ENHMETARECORD* record, int tableEntries, LPARAM logFont)
+{
+ if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
+ const EMREXTCREATEFONTINDIRECTW* createFontRecord = reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
+ *reinterpret_cast<LOGFONT*>(logFont) = createFontRecord->elfw.elfLogFont;
+ }
+ return true;
+}
+
+static int CALLBACK linkedFontEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM hfont)
+{
+ *reinterpret_cast<HFONT*>(hfont) = CreateFontIndirect(logFont);
+ return false;
+}
+
+static const Vector<String>* getLinkedFonts(String& family)
+{
+ static HashMap<String, Vector<String>*> systemLinkMap;
+ Vector<String>* result = systemLinkMap.get(family);
+ if (result)
+ return result;
+
+ result = new Vector<String>;
+ systemLinkMap.set(family, result);
+ HKEY fontLinkKey;
+ if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink", 0, KEY_READ, &fontLinkKey)))
+ return result;
+
+ DWORD linkedFontsBufferSize = 0;
+ RegQueryValueEx(fontLinkKey, family.charactersWithNullTermination(), 0, NULL, NULL, &linkedFontsBufferSize);
+ WCHAR* linkedFonts = reinterpret_cast<WCHAR*>(malloc(linkedFontsBufferSize));
+ if (SUCCEEDED(RegQueryValueEx(fontLinkKey, family.charactersWithNullTermination(), 0, NULL, reinterpret_cast<BYTE*>(linkedFonts), &linkedFontsBufferSize))) {
+ unsigned i = 0;
+ unsigned length = linkedFontsBufferSize / sizeof(*linkedFonts);
+ while (i < length) {
+ while (i < length && linkedFonts[i] != ',')
+ i++;
+ i++;
+ unsigned j = i;
+ while (j < length && linkedFonts[j])
+ j++;
+ result->append(String(linkedFonts + i, j - i));
+ i = j + 1;
+ }
+ }
+ free(linkedFonts);
+ RegCloseKey(fontLinkKey);
+ return result;
+}
+
+static const Vector<DWORD, 4>& getCJKCodePageMasks()
+{
+ // The default order in which we look for a font for a CJK character. If the user's default code page is
+ // one of these, we will use it first.
+ static const UINT CJKCodePages[] = {
+ 932, /* Japanese */
+ 936, /* Simplified Chinese */
+ 950, /* Traditional Chinese */
+ 949 /* Korean */
+ };
+
+ static Vector<DWORD, 4> codePageMasks;
+ static bool initialized;
+ if (!initialized) {
+ initialized = true;
+ IMLangFontLink2* langFontLink = FontCache::getFontLinkInterface();
+ if (!langFontLink)
+ return codePageMasks;
+
+ UINT defaultCodePage;
+ DWORD defaultCodePageMask = 0;
+ if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_RETURN_NUMBER | LOCALE_IDEFAULTANSICODEPAGE, reinterpret_cast<LPWSTR>(&defaultCodePage), sizeof(defaultCodePage)))
+ langFontLink->CodePageToCodePages(defaultCodePage, &defaultCodePageMask);
+
+ if (defaultCodePage == CJKCodePages[0] || defaultCodePage == CJKCodePages[1] || defaultCodePage == CJKCodePages[2] || defaultCodePage == CJKCodePages[3])
+ codePageMasks.append(defaultCodePageMask);
+ for (unsigned i = 0; i < 4; ++i) {
+ if (defaultCodePage != CJKCodePages[i]) {
+ DWORD codePageMask;
+ langFontLink->CodePageToCodePages(CJKCodePages[i], &codePageMask);
+ codePageMasks.append(codePageMask);
+ }
+ }
+ }
+ return codePageMasks;
+}
+
+static bool currentFontContainsCharacter(HDC hdc, UChar character)
+{
+ static Vector<char, 512> glyphsetBuffer;
+ glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0));
+ GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data());
+ GetFontUnicodeRanges(hdc, glyphset);
+
+ // FIXME: Change this to a binary search.
+ unsigned i = 0;
+ while (i < glyphset->cRanges && glyphset->ranges[i].wcLow <= character)
+ i++;
+
+ return i && glyphset->ranges[i - 1].wcLow + glyphset->ranges[i - 1].cGlyphs > character;
+}
+
+static HFONT createMLangFont(IMLangFontLink2* langFontLink, HDC hdc, DWORD codePageMask, UChar character = 0)
+{
+ HFONT MLangFont;
+ HFONT hfont = 0;
+ if (SUCCEEDED(langFontLink->MapFont(hdc, codePageMask, character, &MLangFont)) && MLangFont) {
+ LOGFONT lf;
+ GetObject(MLangFont, sizeof(LOGFONT), &lf);
+ langFontLink->ReleaseFont(MLangFont);
+ hfont = CreateFontIndirect(&lf);
+ }
+ return hfont;
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ UChar character = characters[0];
+ SimpleFontData* fontData = 0;
+ HDC hdc = GetDC(0);
+ HFONT primaryFont = font.primaryFont()->fontDataForCharacter(character)->platformData().hfont();
+ HGDIOBJ oldFont = SelectObject(hdc, primaryFont);
+ HFONT hfont = 0;
+
+ if (IMLangFontLink2* langFontLink = getFontLinkInterface()) {
+ // Try MLang font linking first.
+ DWORD codePages = 0;
+ langFontLink->GetCharCodePages(character, &codePages);
+
+ if (codePages && findCharUnicodeRange(character) == cRangeSetCJK) {
+ // The CJK character may belong to multiple code pages. We want to
+ // do font linking against a single one of them, preferring the default
+ // code page for the user's locale.
+ const Vector<DWORD, 4>& CJKCodePageMasks = getCJKCodePageMasks();
+ unsigned numCodePages = CJKCodePageMasks.size();
+ for (unsigned i = 0; i < numCodePages && !hfont; ++i) {
+ hfont = createMLangFont(langFontLink, hdc, CJKCodePageMasks[i]);
+ if (hfont && !(codePages & CJKCodePageMasks[i])) {
+ // We asked about a code page that is not one of the code pages
+ // returned by MLang, so the font might not contain the character.
+ SelectObject(hdc, hfont);
+ if (!currentFontContainsCharacter(hdc, character)) {
+ DeleteObject(hfont);
+ hfont = 0;
+ }
+ SelectObject(hdc, primaryFont);
+ }
+ }
+ } else
+ hfont = createMLangFont(langFontLink, hdc, codePages, character);
+ }
+
+ // A font returned from MLang is trusted to contain the character.
+ bool containsCharacter = hfont;
+
+ if (!hfont) {
+ // To find out what font Uniscribe would use, we make it draw into a metafile and intercept
+ // calls to CreateFontIndirect().
+ HDC metaFileDc = CreateEnhMetaFile(hdc, NULL, NULL, NULL);
+ SelectObject(metaFileDc, primaryFont);
+
+ bool scriptStringOutSucceeded = false;
+ SCRIPT_STRING_ANALYSIS ssa;
+
+ // FIXME: If length is greater than 1, we actually return the font for the last character.
+ // This function should be renamed getFontDataForCharacter and take a single 32-bit character.
+ if (SUCCEEDED(ScriptStringAnalyse(metaFileDc, characters, length, 0, -1, SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
+ 0, NULL, NULL, NULL, NULL, NULL, &ssa))) {
+ scriptStringOutSucceeded = SUCCEEDED(ScriptStringOut(ssa, 0, 0, 0, NULL, 0, 0, FALSE));
+ ScriptStringFree(&ssa);
+ }
+ HENHMETAFILE metaFile = CloseEnhMetaFile(metaFileDc);
+ if (scriptStringOutSucceeded) {
+ LOGFONT logFont;
+ logFont.lfFaceName[0] = 0;
+ EnumEnhMetaFile(0, metaFile, metaFileEnumProc, &logFont, NULL);
+ if (logFont.lfFaceName[0])
+ hfont = CreateFontIndirect(&logFont);
+ }
+ DeleteEnhMetaFile(metaFile);
+ }
+
+ String familyName;
+ const Vector<String>* linkedFonts = 0;
+ unsigned linkedFontIndex = 0;
+ while (hfont) {
+ SelectObject(hdc, hfont);
+ WCHAR name[LF_FACESIZE];
+ GetTextFace(hdc, LF_FACESIZE, name);
+ familyName = name;
+
+ if (containsCharacter || currentFontContainsCharacter(hdc, character))
+ break;
+
+ if (!linkedFonts)
+ linkedFonts = getLinkedFonts(familyName);
+ SelectObject(hdc, oldFont);
+ DeleteObject(hfont);
+ hfont = 0;
+
+ if (linkedFonts->size() <= linkedFontIndex)
+ break;
+
+ LOGFONT logFont;
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ memcpy(logFont.lfFaceName, linkedFonts->at(linkedFontIndex).characters(), linkedFonts->at(linkedFontIndex).length() * sizeof(WCHAR));
+ logFont.lfFaceName[linkedFonts->at(linkedFontIndex).length()] = 0;
+ EnumFontFamiliesEx(hdc, &logFont, linkedFontEnumProc, reinterpret_cast<LPARAM>(&hfont), 0);
+ linkedFontIndex++;
+ }
+
+ if (hfont) {
+ if (!familyName.isEmpty()) {
+ FontPlatformData* result = getCachedFontPlatformData(font.fontDescription(), familyName);
+ if (result)
+ fontData = getCachedFontData(result);
+ }
+
+ SelectObject(hdc, oldFont);
+ DeleteObject(hfont);
+ }
+
+ ReleaseDC(0, hdc);
+ return fontData;
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ 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 timesStr("Times New Roman");
+ return getCachedFontPlatformData(fontDescription, timesStr);
+}
+
+bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicString& family)
+{
+ LOGFONT winfont;
+
+ // The size here looks unusual. The negative number is intentional. The logical size constant is 32.
+ winfont.lfHeight = -fontDescription.computedPixelSize() * 32;
+ winfont.lfWidth = 0;
+ winfont.lfEscapement = 0;
+ winfont.lfOrientation = 0;
+ winfont.lfUnderline = false;
+ winfont.lfStrikeOut = false;
+ winfont.lfCharSet = DEFAULT_CHARSET;
+#if PLATFORM(CG)
+ winfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
+#else
+ winfont.lfOutPrecision = OUT_TT_PRECIS;
+#endif
+ winfont.lfQuality = 5; // Force cleartype.
+ winfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ winfont.lfItalic = fontDescription.italic();
+
+ // FIXME: Support weights for real. Do our own enumeration of the available weights.
+ // We can't rely on Windows here, since we need to follow the CSS2 algorithm for how to fill in
+ // gaps in the weight list.
+ // FIXME: Hardcoding Lucida Grande for now. It uses different weights than typical Win32 fonts
+ // (500/600 instead of 400/700).
+ static AtomicString lucidaStr("Lucida Grande");
+ if (equalIgnoringCase(family, lucidaStr))
+ winfont.lfWeight = fontDescription.bold() ? 600 : 500;
+ else
+ winfont.lfWeight = fontDescription.bold() ? 700 : 400;
+ int len = min(family.length(), (unsigned int)LF_FACESIZE - 1);
+ memcpy(winfont.lfFaceName, family.characters(), len * sizeof(WORD));
+ winfont.lfFaceName[len] = '\0';
+
+ HFONT hfont = CreateFontIndirect(&winfont);
+ // Windows will always give us a valid pointer here, even if the face name is non-existent. We have to double-check
+ // and see if the family name was really used.
+ HDC dc = GetDC(0);
+ SaveDC(dc);
+ SelectObject(dc, hfont);
+ WCHAR name[LF_FACESIZE];
+ GetTextFace(dc, LF_FACESIZE, name);
+ RestoreDC(dc, -1);
+ ReleaseDC(0, dc);
+
+ DeleteObject(hfont);
+
+ return !wcsicmp(winfont.lfFaceName, name);
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ bool isLucidaGrande = false;
+ static AtomicString lucidaStr("Lucida Grande");
+ if (equalIgnoringCase(family, lucidaStr))
+ isLucidaGrande = true;
+
+ bool useGDI = fontDescription.renderingMode() == AlternateRenderingMode && !isLucidaGrande;
+
+ LOGFONT winfont;
+
+ // The size here looks unusual. The negative number is intentional. The logical size constant is 32. We do this
+ // for subpixel precision when rendering using Uniscribe. This masks rounding errors related to the HFONT metrics being
+ // different from the CGFont metrics.
+ // FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't look as nice. That may be solvable though.
+ winfont.lfHeight = -fontDescription.computedPixelSize() * (useGDI ? 1 : 32);
+ winfont.lfWidth = 0;
+ winfont.lfEscapement = 0;
+ winfont.lfOrientation = 0;
+ winfont.lfUnderline = false;
+ winfont.lfStrikeOut = false;
+ winfont.lfCharSet = DEFAULT_CHARSET;
+ winfont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ winfont.lfQuality = DEFAULT_QUALITY;
+ winfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ winfont.lfItalic = fontDescription.italic();
+
+ // FIXME: Support weights for real. Do our own enumeration of the available weights.
+ // We can't rely on Windows here, since we need to follow the CSS2 algorithm for how to fill in
+ // gaps in the weight list.
+ // FIXME: Hardcoding Lucida Grande for now. It uses different weights than typical Win32 fonts
+ // (500/600 instead of 400/700).
+ if (isLucidaGrande) {
+ winfont.lfWeight = fontDescription.bold() ? 600 : 500;
+ useGDI = false; // Never use GDI for Lucida Grande.
+ } else
+ winfont.lfWeight = fontDescription.bold() ? 700 : 400;
+ int len = min(family.length(), (unsigned int)LF_FACESIZE - 1);
+ memcpy(winfont.lfFaceName, family.characters(), len * sizeof(WORD));
+ winfont.lfFaceName[len] = '\0';
+
+ HFONT hfont = CreateFontIndirect(&winfont);
+ // Windows will always give us a valid pointer here, even if the face name is non-existent. We have to double-check
+ // and see if the family name was really used.
+ HDC dc = GetDC(0);
+ SaveDC(dc);
+ SelectObject(dc, hfont);
+ WCHAR name[LF_FACESIZE];
+ GetTextFace(dc, LF_FACESIZE, name);
+ RestoreDC(dc, -1);
+ ReleaseDC(0, dc);
+
+ if (_wcsicmp(winfont.lfFaceName, name)) {
+ DeleteObject(hfont);
+ return 0;
+ }
+
+ FontPlatformData* result = new FontPlatformData(hfont, fontDescription.computedPixelSize(),
+ fontDescription.bold(), fontDescription.italic(), useGDI);
+
+#if PLATFORM(CG)
+ bool fontCreationFailed = !result->cgFont();
+#elif PLATFORM(CAIRO)
+ bool fontCreationFailed = !result->fontFace();
+#endif
+
+ if (fontCreationFailed) {
+ // The creation of the CGFontRef failed for some reason. We already asserted in debug builds, but to make
+ // absolutely sure that we don't use this font, go ahead and return 0 so that we can fall back to the next
+ // font.
+ delete result;
+ DeleteObject(hfont);
+ return 0;
+ }
+
+ return result;
+}
+
+}
+
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
new file mode 100644
index 0000000..cf03502
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FontCustomPlatformData.h"
+
+#include <wtf/RetainPtr.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include "SharedBuffer.h"
+#include "FontPlatformData.h"
+
+namespace WebCore {
+
+FontCustomPlatformData::~FontCustomPlatformData()
+{
+ CGFontRelease(m_cgFont);
+}
+
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic)
+{
+ return FontPlatformData(m_cgFont, size, bold, italic);
+}
+
+const void* getData(void* info)
+{
+ SharedBuffer* buffer = static_cast<SharedBuffer*>(info);
+ buffer->ref();
+ return (void*)buffer->data();
+}
+
+void releaseData(void* info, const void* data)
+{
+ static_cast<SharedBuffer*>(info)->deref();
+}
+
+size_t getBytesWithOffset(void *info, void* buffer, size_t offset, size_t count)
+{
+ SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
+ size_t availBytes = count;
+ if (offset + count > sharedBuffer->size())
+ availBytes -= (offset + count) - sharedBuffer->size();
+ memcpy(buffer, sharedBuffer->data() + offset, availBytes);
+ return availBytes;
+}
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ ASSERT_ARG(buffer, buffer);
+
+ // Get CG to create the font.
+ CGDataProviderDirectAccessCallbacks callbacks = { &getData, &releaseData, &getBytesWithOffset, NULL };
+ RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirectAccess(buffer, buffer->size(), &callbacks));
+ CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider.get());
+ if (!cgFont)
+ return 0;
+ return new FontCustomPlatformData(cgFont);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.h b/WebCore/platform/graphics/win/FontCustomPlatformData.h
new file mode 100644
index 0000000..909b79e
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontCustomPlatformData.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FontCustomPlatformData_h
+#define FontCustomPlatformData_h
+
+#include <wtf/Noncopyable.h>
+
+typedef struct CGFont* CGFontRef;
+
+namespace WebCore {
+
+class FontPlatformData;
+class SharedBuffer;
+
+struct FontCustomPlatformData : Noncopyable {
+ FontCustomPlatformData(CGFontRef cgFont)
+ : m_cgFont(cgFont)
+ {
+ }
+ ~FontCustomPlatformData();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic);
+
+ CGFontRef m_cgFont;
+};
+
+FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
new file mode 100644
index 0000000..e54d85a
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "FontCustomPlatformDataCairo.h"
+
+#include "SharedBuffer.h"
+#include "FontPlatformData.h"
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+FontCustomPlatformDataCairo::~FontCustomPlatformDataCairo()
+{
+ cairo_font_face_destroy(m_fontFace);
+}
+
+FontPlatformData FontCustomPlatformDataCairo::fontPlatformData(int size, bool bold, bool italic)
+{
+ return FontPlatformData(m_fontFace, size, bold, italic);
+}
+
+static void releaseData(void* data)
+{
+ static_cast<SharedBuffer*>(data)->deref();
+}
+
+FontCustomPlatformDataCairo* createFontCustomPlatformData(SharedBuffer* buffer)
+{
+ ASSERT_ARG(buffer, buffer);
+
+ buffer->ref();
+ HFONT font = reinterpret_cast<HFONT>(buffer);
+ cairo_font_face_t* fontFace = cairo_win32_font_face_create_for_hfont(font);
+ if (!fontFace)
+ return 0;
+
+ static cairo_user_data_key_t bufferKey;
+ cairo_font_face_set_user_data(fontFace, &bufferKey, buffer, releaseData);
+
+ return new FontCustomPlatformDataCairo(fontFace);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
new file mode 100644
index 0000000..87794b5
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef FontCustomPlatformDataCairo_h
+#define FontCustomPlatformDataCairo_h
+
+#include <wtf/Noncopyable.h>
+
+#include <cairo.h>
+
+namespace WebCore {
+
+class FontPlatformData;
+class SharedBuffer;
+
+struct FontCustomPlatformDataCairo : Noncopyable {
+ FontCustomPlatformDataCairo(cairo_font_face_t* fontFace)
+ : m_fontFace(fontFace)
+ {
+ }
+ ~FontCustomPlatformDataCairo();
+
+ FontPlatformData fontPlatformData(int size, bool bold, bool italic);
+
+ cairo_font_face_t* m_fontFace;
+};
+
+FontCustomPlatformDataCairo* createFontCustomPlatformData(SharedBuffer*);
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/win/FontDatabase.cpp b/WebCore/platform/graphics/win/FontDatabase.cpp
new file mode 100644
index 0000000..1308ff0
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontDatabase.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2007 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.
+ * 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 "FontDatabase.h"
+
+#include "CString.h"
+#include "FileSystem.h"
+#include "PlatformString.h"
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <shlobj.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+static String systemFontsDirectory()
+{
+ static bool initialized;
+ static String directory;
+
+ if (!initialized) {
+ initialized = true;
+
+ Vector<UChar> buffer(MAX_PATH);
+ if (FAILED(SHGetFolderPath(0, CSIDL_FONTS | CSIDL_FLAG_CREATE, 0, 0, buffer.data())))
+ return directory;
+ buffer.resize(wcslen(buffer.data()));
+
+ directory = String::adopt(buffer);
+ }
+
+ return directory;
+}
+
+static String fontsPlistPath()
+{
+ static String path = pathByAppendingComponent(localUserSpecificStorageDirectory(), "FontsList.plist");
+ return path;
+}
+
+static bool systemHasFontsNewerThanFontsPlist()
+{
+ WIN32_FILE_ATTRIBUTE_DATA plistAttributes = {0};
+ if (!GetFileAttributesEx(fontsPlistPath().charactersWithNullTermination(), GetFileExInfoStandard, &plistAttributes))
+ return true;
+
+ WIN32_FILE_ATTRIBUTE_DATA fontsDirectoryAttributes = {0};
+ if (!GetFileAttributesEx(systemFontsDirectory().charactersWithNullTermination(), GetFileExInfoStandard, &fontsDirectoryAttributes))
+ return true;
+
+ return CompareFileTime(&plistAttributes.ftLastWriteTime, &fontsDirectoryAttributes.ftLastWriteTime) < 0;
+}
+
+static RetainPtr<CFPropertyListRef> readFontPlist()
+{
+ CString plistPath = fontsPlistPath().utf8();
+
+ RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateFromFileSystemRepresentation(0, reinterpret_cast<const UInt8*>(plistPath.data()), plistPath.length(), false));
+ if (!url)
+ return 0;
+
+ RetainPtr<CFReadStreamRef> stream(AdoptCF, CFReadStreamCreateWithFile(0, url.get()));
+ if (!stream)
+ return 0;
+
+ if (!CFReadStreamOpen(stream.get()))
+ return 0;
+
+ CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0 | kCFPropertyListXMLFormat_v1_0;
+ RetainPtr<CFPropertyListRef> plist(AdoptCF, CFPropertyListCreateFromStream(0, stream.get(), 0, kCFPropertyListMutableContainersAndLeaves, &format, 0));
+
+ CFReadStreamClose(stream.get());
+
+ return plist;
+}
+
+static bool populateFontDatabaseFromPlist()
+{
+ RetainPtr<CFPropertyListRef> plist = readFontPlist();
+ if (!plist)
+ return false;
+
+ RetainPtr<CFDataRef> data(AdoptCF, CFPropertyListCreateXMLData(0, plist.get()));
+ if (!data)
+ return false;
+
+ wkAddFontsFromPlistRepresentation(data.get());
+ return true;
+}
+
+static bool populateFontDatabaseFromFileSystem()
+{
+ RetainPtr<CFStringRef> directory(AdoptCF, systemFontsDirectory().createCFString());
+ if (!directory)
+ return false;
+
+ wkAddFontsInDirectory(directory.get());
+ return true;
+}
+
+static void writeFontDatabaseToPlist()
+{
+ RetainPtr<CFDataRef> data(AdoptCF, wkCreateFontsPlistRepresentation());
+ if (!data)
+ return;
+
+ safeCreateFile(fontsPlistPath(), data.get());
+}
+
+void populateFontDatabase()
+{
+ static bool initialized;
+ if (initialized)
+ return;
+ initialized = true;
+
+ if (!systemHasFontsNewerThanFontsPlist())
+ if (populateFontDatabaseFromPlist())
+ return;
+
+ if (populateFontDatabaseFromFileSystem())
+ writeFontDatabaseToPlist();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/FontDatabase.h b/WebCore/platform/graphics/win/FontDatabase.h
new file mode 100644
index 0000000..4f76c9e
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontDatabase.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 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.
+ * 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.
+ */
+
+#ifndef FontDatabase_h
+#define FontDatabase_h
+
+namespace WebCore {
+
+ void populateFontDatabase();
+
+} // namespace WebCore
+
+#endif // !defined(FontDatabase_h)
diff --git a/WebCore/platform/graphics/win/FontPlatformData.h b/WebCore/platform/graphics/win/FontPlatformData.h
new file mode 100644
index 0000000..5bbda2f
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontPlatformData.h
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006, 2007, 2008 Apple 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 FontPlatformData_H
+#define FontPlatformData_H
+
+#include "StringImpl.h"
+
+#if PLATFORM(CAIRO)
+#include <cairo-win32.h>
+#endif
+
+typedef struct HFONT__* HFONT;
+typedef struct CGFont* CGFontRef;
+
+namespace WebCore {
+
+class FontDescription;
+
+class FontPlatformData
+{
+public:
+ class Deleted {};
+
+ // Used for deleted values in the font cache's hash tables.
+ FontPlatformData(Deleted)
+ : m_font((HFONT)-1)
+#if PLATFORM(CG)
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_fontFace(0)
+#endif
+ , m_size(0)
+ , m_syntheticBold(false)
+ , m_syntheticOblique(false)
+ , m_useGDI(false)
+ {
+ }
+
+ FontPlatformData()
+ : m_font(0)
+#if PLATFORM(CG)
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_fontFace(0)
+#endif
+ , m_size(0)
+ , m_syntheticBold(false)
+ , m_syntheticOblique(false)
+ , m_useGDI(false)
+ {
+ }
+
+ FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI);
+ FontPlatformData(float size, bool bold, bool oblique);
+
+#if PLATFORM(CG)
+ FontPlatformData(CGFontRef, float size, bool bold, bool oblique);
+#elif PLATFORM(CAIRO)
+ FontPlatformData(cairo_font_face_t*, float size, bool bold, bool oblique);
+#endif
+ ~FontPlatformData();
+
+ void platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName);
+
+ HFONT hfont() const { return m_font; }
+#if PLATFORM(CG)
+ CGFontRef cgFont() const { return m_cgFont; }
+#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
+
+ float size() const { return m_size; }
+ void setSize(float size) { m_size = size; }
+ bool syntheticBold() const { return m_syntheticBold; }
+ bool syntheticOblique() const { return m_syntheticOblique; }
+ bool useGDI() const { return m_useGDI; }
+
+ unsigned hash() const
+ {
+ return StringImpl::computeHash((UChar*)(&m_font), sizeof(HFONT) / sizeof(UChar));
+ }
+
+ bool operator==(const FontPlatformData& other) const
+ {
+ return m_font == other.m_font &&
+#if PLATFORM(CG)
+ m_cgFont == other.m_cgFont &&
+#elif PLATFORM(CAIRO)
+ m_fontFace == other.m_fontFace &&
+ m_scaledFont == other.m_scaledFont &&
+#endif
+ m_size == other.m_size &&
+ m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique &&
+ m_useGDI == other.m_useGDI;
+ }
+
+private:
+ HFONT m_font;
+#if PLATFORM(CG)
+ CGFontRef m_cgFont;
+#elif PLATFORM(CAIRO)
+ cairo_font_face_t* m_fontFace;
+ cairo_scaled_font_t* m_scaledFont;
+#endif
+
+ float m_size;
+ bool m_syntheticBold;
+ bool m_syntheticOblique;
+ bool m_useGDI;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
new file mode 100644
index 0000000..ddd3104
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp
@@ -0,0 +1,134 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006, 2007, 2008 Apple 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 "FontPlatformData.h"
+
+#include "PlatformString.h"
+#include "StringHash.h"
+#include <ApplicationServices/ApplicationServices.h>
+#include <wtf/HashMap.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+using std::min;
+
+namespace WebCore {
+
+static inline USHORT readBigEndianWord(const BYTE* word) { return (word[0] << 8) | word[1]; }
+
+static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc)
+{
+ const DWORD cMaxNameTableSize = 1024 * 1024;
+
+ static HashMap<String, RetainPtr<CFStringRef> > nameMap;
+
+ // Check our hash first.
+ String faceString(faceName);
+ RetainPtr<CFStringRef> result = nameMap.get(faceString);
+ if (result)
+ return result.get();
+
+ // We need to obtain the PostScript name from the name table and use it instead,.
+ DWORD bufferSize = GetFontData(dc, 'eman', 0, NULL, 0); // "name" backwards
+ if (bufferSize == 0 || bufferSize == GDI_ERROR || bufferSize > cMaxNameTableSize)
+ return NULL;
+
+ Vector<BYTE> bufferVector(bufferSize);
+ BYTE* buffer = bufferVector.data();
+ if (GetFontData(dc, 'eman', 0, buffer, bufferSize) == GDI_ERROR)
+ return NULL;
+
+ if (bufferSize < 6)
+ return NULL;
+
+ USHORT numberOfRecords = readBigEndianWord(buffer + 2);
+ UINT stringsOffset = readBigEndianWord(buffer + 4);
+ if (bufferSize < stringsOffset)
+ return NULL;
+
+ BYTE* strings = buffer + stringsOffset;
+
+ // Now walk each name record looking for a Mac or Windows PostScript name.
+ UINT offset = 6;
+ for (int i = 0; i < numberOfRecords; i++) {
+ if (bufferSize < offset + 12)
+ return NULL;
+
+ USHORT platformID = readBigEndianWord(buffer + offset);
+ USHORT encodingID = readBigEndianWord(buffer + offset + 2);
+ USHORT languageID = readBigEndianWord(buffer + offset + 4);
+ USHORT nameID = readBigEndianWord(buffer + offset + 6);
+ USHORT length = readBigEndianWord(buffer + offset + 8);
+ USHORT nameOffset = readBigEndianWord(buffer + offset + 10);
+
+ if (platformID == 3 && encodingID == 1 && languageID == 0x409 && nameID == 6) {
+ // This is a Windows PostScript name and is therefore UTF-16.
+ // Pass Big Endian as the encoding.
+ if (bufferSize < stringsOffset + nameOffset + length)
+ return NULL;
+ result.adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingUTF16BE, false));
+ break;
+ } else if (platformID == 1 && encodingID == 0 && languageID == 0 && nameID == 6) {
+ // This is a Mac PostScript name and is therefore ASCII.
+ // See http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
+ if (bufferSize < stringsOffset + nameOffset + length)
+ return NULL;
+ result.adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingASCII, false));
+ break;
+ }
+
+ offset += 12;
+ }
+
+ if (result)
+ nameMap.set(faceString, result);
+ return result.get();
+}
+
+void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
+{
+ // Try the face name first. Windows may end up localizing this name, and CG doesn't know about
+ // the localization. If the create fails, we'll try the PostScript name.
+ RetainPtr<CFStringRef> fullName(AdoptCF, CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName)));
+ m_cgFont = CGFontCreateWithFontName(fullName.get());
+ if (!m_cgFont) {
+ CFStringRef postScriptName = getPostScriptName(fullName.get(), hdc);
+ if (postScriptName) {
+ m_cgFont = CGFontCreateWithFontName(postScriptName);
+ ASSERT(m_cgFont);
+ }
+ }
+}
+
+FontPlatformData::FontPlatformData(CGFontRef font, float size, bool bold, bool oblique)
+ : m_font(0)
+ , m_size(size)
+ , m_cgFont(font)
+ , m_syntheticBold(bold)
+ , m_syntheticOblique(oblique)
+ , m_useGDI(false)
+{
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
new file mode 100644
index 0000000..438d0a9
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006, 2007, 2008 Apple Inc.
+ * Copyright (C) 2007 Alp Toker
+ * Copyright (C) 2008 Brent Fulgham
+ *
+ * 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 "FontPlatformData.h"
+
+#include "PlatformString.h"
+#include "StringHash.h"
+#include <wtf/HashMap.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+#include <cairo-win32.h>
+
+using std::min;
+
+namespace WebCore {
+
+void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName)
+{
+ m_fontFace = cairo_win32_font_face_create_for_hfont(font);
+ cairo_matrix_t sizeMatrix, ctm;
+ cairo_matrix_init_identity(&ctm);
+ cairo_matrix_init_scale(&sizeMatrix, size, size);
+
+ static cairo_font_options_t* fontOptions = 0;
+ if (!fontOptions)
+ {
+ fontOptions = cairo_font_options_create();
+ cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL);
+ }
+
+ m_scaledFont = cairo_scaled_font_create(m_fontFace, &sizeMatrix, &ctm, fontOptions);
+}
+
+FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool oblique)
+ : m_font(0)
+ , m_size(size)
+ , m_fontFace(fontFace)
+ , m_scaledFont(0)
+ , m_syntheticBold(bold)
+ , m_syntheticOblique(oblique)
+ , m_useGDI(false)
+{
+ cairo_matrix_t fontMatrix;
+ cairo_matrix_init_scale(&fontMatrix, size, size);
+ cairo_matrix_t ctm;
+ cairo_matrix_init_identity(&ctm);
+ cairo_font_options_t* options = cairo_font_options_create();
+
+ // We force antialiasing and disable hinting to provide consistent
+ // typographic qualities for custom fonts on all platforms.
+ cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
+
+ m_scaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options);
+ cairo_font_options_destroy(options);
+}
+
+void FontPlatformData::setFont(cairo_t* cr) const
+{
+ ASSERT(m_scaledFont);
+
+ cairo_set_scaled_font(cr, m_scaledFont);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
new file mode 100644
index 0000000..f209dbf
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp
@@ -0,0 +1,144 @@
+/*
+ * This file is part of the internal font implementation. It should not be included by anyone other than
+ * FontMac.cpp, FontWin.cpp and Font.cpp.
+ *
+ * Copyright (C) 2006, 2007, 2008 Apple Inc.
+ * Copyright (C) 2008 Brent Fulgham
+ *
+ * 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 "FontPlatformData.h"
+
+#include "PlatformString.h"
+#include "StringHash.h"
+#include <wtf/HashMap.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+using std::min;
+
+namespace WebCore {
+
+static const int Bold = (1 << 0);
+static const int Italic = (1 << 1);
+static const int BoldOblique = (1 << 2);
+
+static int CALLBACK enumStylesCallback(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
+{
+ int *style = reinterpret_cast<int*>(lParam);
+
+ // FIXME: In order to accommodate Lucida we go ahead and consider a weight of 600 to be bold.
+ // This does mean we'll consider demibold and semibold fonts on windows to also be bold. This
+ // is rare enough that it seems like an ok hack for now.
+ if (logFont->lfWeight >= 600) {
+ if (logFont->lfItalic)
+ *style |= BoldOblique;
+ else
+ *style |= Bold;
+ } else if (logFont->lfItalic)
+ *style |= Italic;
+
+ return 1;
+}
+
+FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI)
+ : m_font(font)
+ , m_size(size)
+#if PLATFORM(CG)
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_fontFace(0)
+ , m_scaledFont(0)
+#endif
+ , m_syntheticBold(false)
+ , m_syntheticOblique(false)
+ , m_useGDI(useGDI)
+{
+ HDC hdc = GetDC(0);
+ SaveDC(hdc);
+
+ SelectObject(hdc, font);
+ UINT bufferSize = GetOutlineTextMetrics(hdc, 0, NULL);
+
+ ASSERT_WITH_MESSAGE(bufferSize != 0, "Bitmap fonts not supported with CoreGraphics.");
+
+ if (bufferSize != 0) {
+ OUTLINETEXTMETRICW* metrics = (OUTLINETEXTMETRICW*)malloc(bufferSize);
+
+ GetOutlineTextMetricsW(hdc, bufferSize, metrics);
+ WCHAR* faceName = (WCHAR*)((uintptr_t)metrics + (uintptr_t)metrics->otmpFaceName);
+
+ if (!useGDI && (bold || oblique)) {
+ LOGFONT logFont;
+
+ int len = min((int)wcslen(faceName), LF_FACESIZE - 1);
+ memcpy(logFont.lfFaceName, faceName, len * sizeof(WORD));
+ logFont.lfFaceName[len] = '\0';
+ logFont.lfCharSet = metrics->otmTextMetrics.tmCharSet;
+ logFont.lfPitchAndFamily = 0;
+
+ int styles = 0;
+ EnumFontFamiliesEx(hdc, &logFont, enumStylesCallback, reinterpret_cast<LPARAM>(&styles), 0);
+
+ // Check if we need to synthesize bold or oblique. The rule that complicates things here
+ // is that if the requested font is bold and oblique, and both a bold font and an oblique font
+ // exist, the bold font should be used, and oblique synthesized.
+ if (bold && oblique) {
+ if (styles == 0) {
+ m_syntheticBold = true;
+ m_syntheticOblique = true;
+ } else if (styles & Bold)
+ m_syntheticOblique = true;
+ else if (styles & Italic)
+ m_syntheticBold = true;
+ } else if (bold && (!(styles & Bold)))
+ m_syntheticBold = true;
+ else if (oblique && !(styles & Italic))
+ m_syntheticOblique = true;
+ }
+
+ platformDataInit(font, size, hdc, faceName);
+
+ free(metrics);
+ }
+
+ RestoreDC(hdc, -1);
+ ReleaseDC(0, hdc);
+}
+
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+ : m_font(0)
+ , m_size(size)
+#if PLATFORM(CG)
+ , m_cgFont(0)
+#elif PLATFORM(CAIRO)
+ , m_fontFace(0)
+ , m_scaledFont(0)
+#endif
+ , m_syntheticBold(bold)
+ , m_syntheticOblique(oblique)
+ , m_useGDI(false)
+{
+}
+
+FontPlatformData::~FontPlatformData()
+{
+}
+
+}
diff --git a/WebCore/platform/graphics/win/FontWin.cpp b/WebCore/platform/graphics/win/FontWin.cpp
new file mode 100644
index 0000000..5e423e0
--- /dev/null
+++ b/WebCore/platform/graphics/win/FontWin.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "FontFallbackList.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+#include "UniscribeController.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
+ int from, int to) const
+{
+ UniscribeController it(this, run);
+ it.advance(from);
+ float beforeWidth = it.runWidthSoFar();
+ it.advance(to);
+ float afterWidth = it.runWidthSoFar();
+
+ // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
+ if (run.rtl()) {
+ it.advance(run.length());
+ float totalWidth = it.runWidthSoFar();
+ return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
+ }
+
+ return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
+ int from, int to) const
+{
+ // This glyph buffer holds our glyphs + advances + font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x();
+ UniscribeController controller(this, run);
+ controller.advance(from);
+ float beforeWidth = controller.runWidthSoFar();
+ controller.advance(to, &glyphBuffer);
+
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return;
+
+ float afterWidth = controller.runWidthSoFar();
+
+ if (run.rtl()) {
+ controller.advance(run.length());
+ startX += controller.runWidthSoFar() - afterWidth;
+ } else
+ startX += beforeWidth;
+
+ // Draw the glyph buffer now at the starting point returned in startX.
+ FloatPoint startPoint(startX, point.y());
+ drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ UniscribeController controller(this, run);
+ controller.advance(run.length());
+ return controller.runWidthSoFar();
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+ UniscribeController controller(this, run);
+ return controller.offsetForPosition(x, includePartialGlyphs);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/GlyphPageTreeNodeCGWin.cpp b/WebCore/platform/graphics/win/GlyphPageTreeNodeCGWin.cpp
new file mode 100644
index 0000000..c11fc1b
--- /dev/null
+++ b/WebCore/platform/graphics/win/GlyphPageTreeNodeCGWin.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 "GlyphPageTreeNode.h"
+
+#include "SimpleFontData.h"
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+
+namespace WebCore {
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ // bufferLength will be greater than the requested number of glyphs if the buffer contains surrogate pairs.
+ // We won't support this for now.
+ if (bufferLength > length)
+ return false;
+
+ bool haveGlyphs = false;
+ CGGlyph localGlyphBuffer[GlyphPage::size];
+ wkGetGlyphs(fontData->platformData().cgFont(), buffer, localGlyphBuffer, bufferLength);
+ for (unsigned i = 0; i < length; i++) {
+ Glyph glyph = localGlyphBuffer[i];
+ if (!glyph)
+ setGlyphDataForIndex(offset + i, 0, 0);
+ else {
+ setGlyphDataForIndex(offset + i, glyph, fontData);
+ haveGlyphs = true;
+ }
+ }
+ return haveGlyphs;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/GlyphPageTreeNodeCairoWin.cpp b/WebCore/platform/graphics/win/GlyphPageTreeNodeCairoWin.cpp
new file mode 100644
index 0000000..b679ced
--- /dev/null
+++ b/WebCore/platform/graphics/win/GlyphPageTreeNodeCairoWin.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 "GlyphPageTreeNode.h"
+
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ // bufferLength will be greater than the requested number of glyphs if the buffer contains surrogate pairs.
+ // We won't support this for now.
+ if (bufferLength > length)
+ return false;
+
+ bool haveGlyphs = false;
+
+ HDC dc = GetDC((HWND)0);
+ SaveDC(dc);
+ SelectObject(dc, fontData->platformData().hfont());
+
+ TEXTMETRIC tm;
+ GetTextMetrics(dc, &tm);
+
+ WORD localGlyphBuffer[GlyphPage::size * 2];
+ DWORD result = GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, 0);
+ bool success = result != GDI_ERROR && static_cast<unsigned>(result) == bufferLength;
+ if (success) {
+ for (unsigned i = 0; i < length; i++) {
+ Glyph glyph = localGlyphBuffer[i];
+ if (!glyph)
+ setGlyphDataForIndex(offset + i, 0, 0);
+ else {
+ setGlyphDataForIndex(offset + i, glyph, fontData);
+ haveGlyphs = true;
+ }
+ }
+ }
+ RestoreDC(dc, -1);
+ ReleaseDC(0, dc);
+
+ return haveGlyphs;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
new file mode 100644
index 0000000..99d528d
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "AffineTransform.h"
+#include "NotImplemented.h"
+#include "Path.h"
+
+#include <CoreGraphics/CGBitmapContext.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include "GraphicsContextPlatformPrivateCG.h"
+
+using namespace std;
+
+namespace WebCore {
+
+static CGContextRef CGContextWithHDC(HDC hdc)
+{
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
+ BITMAP info;
+
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+ CGContextRef context = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
+ info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
+ CGColorSpaceRelease(deviceRGB);
+
+ // Flip coords
+ CGContextTranslateCTM(context, 0, info.bmHeight);
+ CGContextScaleCTM(context, 1, -1);
+
+ // Put the HDC In advanced mode so it will honor affine transforms.
+ SetGraphicsMode(hdc, GM_ADVANCED);
+
+ return context;
+}
+
+GraphicsContext::GraphicsContext(HDC hdc)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate(CGContextWithHDC(hdc)))
+{
+ CGContextRelease(m_data->m_cgContext);
+ m_data->m_hdc = hdc;
+ setPaintingDisabled(!m_data->m_cgContext);
+ if (m_data->m_cgContext) {
+ // Make sure the context starts in sync with our state.
+ setPlatformFillColor(fillColor());
+ setPlatformStrokeColor(strokeColor());
+ }
+}
+
+bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
+
+HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend)
+{
+ if (inTransparencyLayer()) {
+ if (dstRect.isEmpty())
+ return 0;
+
+ // Create a bitmap DC in which to draw.
+ BITMAPINFO bitmapInfo;
+ bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.bmiHeader.biWidth = dstRect.width();
+ bitmapInfo.bmiHeader.biHeight = dstRect.height();
+ bitmapInfo.bmiHeader.biPlanes = 1;
+ bitmapInfo.bmiHeader.biBitCount = 32;
+ bitmapInfo.bmiHeader.biCompression = BI_RGB;
+ bitmapInfo.bmiHeader.biSizeImage = 0;
+ bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biClrUsed = 0;
+ bitmapInfo.bmiHeader.biClrImportant = 0;
+
+ void* pixels = 0;
+ HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
+ if (!bitmap)
+ return 0;
+
+ HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc);
+ ::SelectObject(bitmapDC, bitmap);
+
+ // Fill our buffer with clear if we're going to alpha blend.
+ if (supportAlphaBlend) {
+ BITMAP bmpInfo;
+ GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ memset(bmpInfo.bmBits, 0, bufferSize);
+ }
+
+ // Make sure we can do world transforms.
+ SetGraphicsMode(bitmapDC, GM_ADVANCED);
+
+ // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
+ XFORM xform;
+ xform.eM11 = 1.0f;
+ xform.eM12 = 0.0f;
+ xform.eM21 = 0.0f;
+ xform.eM22 = 1.0f;
+ xform.eDx = -dstRect.x();
+ xform.eDy = -dstRect.y();
+ ::SetWorldTransform(bitmapDC, &xform);
+
+ return bitmapDC;
+ }
+
+ CGContextFlush(platformContext());
+ m_data->save();
+ return m_data->m_hdc;
+}
+
+void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend)
+{
+ if (hdc && inTransparencyLayer()) {
+ if (dstRect.isEmpty())
+ return;
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+
+ // Need to make a CGImage out of the bitmap's pixel buffer and then draw
+ // it into our context.
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
+ CGContextRef bitmapContext = CGBitmapContextCreate(info.bmBits, info.bmWidth, info.bmHeight, 8,
+ info.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little |
+ (supportAlphaBlend ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst));
+ CGColorSpaceRelease(deviceRGB);
+
+ CGImageRef image = CGBitmapContextCreateImage(bitmapContext);
+ CGContextDrawImage(m_data->m_cgContext, dstRect, image);
+
+ // Delete all our junk.
+ CGImageRelease(image);
+ CGContextRelease(bitmapContext);
+ ::DeleteDC(hdc);
+ ::DeleteObject(bitmap);
+
+ return;
+ }
+
+ m_data->restore();
+}
+
+void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform)
+{
+ if (!m_hdc)
+ return;
+
+ CGAffineTransform mat = transform;
+ XFORM xform;
+ xform.eM11 = mat.a;
+ xform.eM12 = mat.b;
+ xform.eM21 = mat.c;
+ xform.eM22 = mat.d;
+ xform.eDx = mat.tx;
+ xform.eDy = mat.ty;
+
+ ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ float radius = (focusRingWidth() - 1) / 2.0f;
+ int offset = radius + focusRingOffset();
+ CGColorRef colorRef = color.isValid() ? cgColor(color) : 0;
+
+ CGMutablePathRef focusRingPath = 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));
+
+ CGContextRef context = platformContext();
+ CGContextSaveGState(context);
+
+ CGContextBeginPath(context);
+ CGContextAddPath(context, focusRingPath);
+
+ wkDrawFocusRing(context, colorRef, radius);
+
+ CGColorRelease(colorRef);
+
+ CGPathRelease(focusRingPath);
+
+ CGContextRestoreGState(context);
+}
+
+// Pulled from GraphicsContextCG
+static void setCGStrokeColor(CGContextRef context, const Color& color)
+{
+ CGFloat red, green, blue, alpha;
+ color.getRGBA(red, green, blue, alpha);
+ CGContextSetRGBStrokeColor(context, red, green, blue, alpha);
+}
+
+static const Color& spellingPatternColor() {
+ static const Color spellingColor(255, 0, 0);
+ return spellingColor;
+}
+
+static const Color& grammarPatternColor() {
+ static const Color grammarColor(0, 128, 0);
+ return grammarColor;
+}
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
+{
+ if (paintingDisabled())
+ return;
+
+ // These are the same for misspelling or bad grammar
+ const int patternHeight = 3; // 3 rows
+ ASSERT(cMisspellingLineThickness == patternHeight);
+ const int patternWidth = 4; // 4 pixels
+ ASSERT(patternWidth == cMisspellingLinePatternWidth);
+
+ // Make sure to draw only complete dots.
+ // NOTE: Code here used to shift the underline to the left and increase the width
+ // to make sure everything gets underlined, but that results in drawing out of
+ // bounds (e.g. when at the edge of a view) and could make it appear that the
+ // space between adjacent misspelled words was underlined.
+ // allow slightly more considering that the pattern ends with a transparent pixel
+ int widthMod = width % patternWidth;
+ if (patternWidth - widthMod > cMisspellingLinePatternGapWidth)
+ width -= widthMod;
+
+ // Draw the underline
+ CGContextRef context = platformContext();
+ CGContextSaveGState(context);
+
+ const Color& patternColor = grammar ? grammarPatternColor() : spellingPatternColor();
+ setCGStrokeColor(context, patternColor);
+
+ wkSetPatternPhaseInUserSpace(context, point);
+ CGContextSetBlendMode(context, kCGBlendModeNormal);
+
+ // 3 rows, each offset by half a pixel for blending purposes
+ const CGPoint upperPoints [] = {{point.x(), point.y() + patternHeight - 2.5 }, {point.x() + width, point.y() + patternHeight - 2.5}};
+ const CGPoint middlePoints [] = {{point.x(), point.y() + patternHeight - 1.5 }, {point.x() + width, point.y() + patternHeight - 1.5}};
+ const CGPoint lowerPoints [] = {{point.x(), point.y() + patternHeight - 0.5 }, {point.x() + width, point.y() + patternHeight - 0.5 }};
+
+ // Dash lengths for the top and bottom of the error underline are the same.
+ // These are magic.
+ static const float edge_dash_lengths[] = {2.0f, 2.0f};
+ static const float middle_dash_lengths[] = {2.76f, 1.24f};
+ static const float edge_offset = -(edge_dash_lengths[1] - 1.0f) / 2.0f;
+ static const float middle_offset = -(middle_dash_lengths[1] - 1.0f) / 2.0f;
+
+ // Line opacities. Once again, these are magic.
+ const float upperOpacity = 0.33f;
+ const float middleOpacity = 0.75f;
+ const float lowerOpacity = 0.88f;
+
+ //Top line
+ CGContextSetLineDash(context, edge_offset, edge_dash_lengths,
+ sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0]));
+ CGContextSetAlpha(context, upperOpacity);
+ CGContextStrokeLineSegments(context, upperPoints, 2);
+
+ // Middle line
+ CGContextSetLineDash(context, middle_offset, middle_dash_lengths,
+ sizeof(middle_dash_lengths) / sizeof(middle_dash_lengths[0]));
+ CGContextSetAlpha(context, middleOpacity);
+ CGContextStrokeLineSegments(context, middlePoints, 2);
+
+ // Bottom line
+ CGContextSetLineDash(context, edge_offset, edge_dash_lengths,
+ sizeof(edge_dash_lengths) / sizeof(edge_dash_lengths[0]));
+ CGContextSetAlpha(context, lowerOpacity);
+ CGContextStrokeLineSegments(context, lowerPoints, 2);
+
+ CGContextRestoreGState(context);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
new file mode 100644
index 0000000..0e9c636
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "AffineTransform.h"
+#include "NotImplemented.h"
+#include "Path.h"
+
+#include <cairo-win32.h>
+#include "GraphicsContextPlatformPrivateCairo.h"
+
+using namespace std;
+
+namespace WebCore {
+
+GraphicsContext::GraphicsContext(HDC dc)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate)
+{
+ if (dc) {
+ cairo_surface_t* surface = cairo_win32_surface_create(dc);
+ m_data->cr = cairo_create(surface);
+ m_data->m_hdc = dc;
+ } else {
+ setPaintingDisabled(true);
+ m_data->cr = 0;
+ m_data->m_hdc = 0;
+ }
+
+ if (m_data->cr) {
+ // Make sure the context starts in sync with our state.
+ setPlatformFillColor(fillColor());
+ setPlatformStrokeColor(strokeColor());
+ }
+}
+
+HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend)
+{
+ // This is probably wrong, and definitely out of date. Pulled from old SVN
+ cairo_surface_t* surface = cairo_get_target(platformContext());
+ HDC hdc = cairo_win32_surface_get_dc(surface);
+ SaveDC(hdc);
+
+ // FIXME: We need to make sure a clip is really set on the HDC.
+ // Call SetWorldTransform to honor the current Cairo transform.
+ SetGraphicsMode(hdc, GM_ADVANCED); // We need this call for themes to honor world transforms.
+ cairo_matrix_t mat;
+ cairo_get_matrix(platformContext(), &mat);
+ XFORM xform;
+ xform.eM11 = mat.xx;
+ xform.eM12 = mat.xy;
+ xform.eM21 = mat.yx;
+ xform.eM22 = mat.yy;
+ xform.eDx = mat.x0;
+ xform.eDy = mat.y0;
+ SetWorldTransform(hdc, &xform);
+
+ return hdc;
+}
+
+bool GraphicsContext::inTransparencyLayer() const { return m_data->m_transparencyCount; }
+
+void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend)
+{
+ cairo_surface_t* surface = cairo_get_target(platformContext());
+ HDC hdc2 = cairo_win32_surface_get_dc(surface);
+ RestoreDC(hdc2, -1);
+ cairo_surface_mark_dirty(surface);
+}
+
+void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform)
+{
+ cairo_surface_t* surface = cairo_get_target(cr);
+ HDC hdc = cairo_win32_surface_get_dc(surface);
+ SaveDC(hdc);
+
+ const cairo_matrix_t* matrix = reinterpret_cast<const cairo_matrix_t*>(&transform);
+
+ XFORM xform;
+ xform.eM11 = matrix->xx;
+ xform.eM12 = matrix->xy;
+ xform.eM21 = matrix->yx;
+ xform.eM22 = matrix->yy;
+ xform.eDx = matrix->x0;
+ xform.eDy = matrix->y0;
+
+ ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/WebCore/platform/graphics/win/GraphicsContextWin.cpp
new file mode 100644
index 0000000..373d2cf
--- /dev/null
+++ b/WebCore/platform/graphics/win/GraphicsContextWin.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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"
+
+#if PLATFORM(CG)
+#include "GraphicsContextPlatformPrivateCG.h"
+#elif PLATFORM(CAIRO)
+#include "GraphicsContextPlatformPrivateCairo.h"
+#endif
+
+#include "AffineTransform.h"
+#include "NotImplemented.h"
+#include "Path.h"
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+class SVGResourceImage;
+
+void GraphicsContextPlatformPrivate::save()
+{
+ if (!m_hdc)
+ return;
+ SaveDC(m_hdc);
+}
+
+void GraphicsContextPlatformPrivate::restore()
+{
+ if (!m_hdc)
+ return;
+ RestoreDC(m_hdc, -1);
+}
+
+void GraphicsContextPlatformPrivate::clip(const IntRect& clipRect)
+{
+ if (!m_hdc)
+ return;
+ IntersectClipRect(m_hdc, clipRect.x(), clipRect.y(), clipRect.right(), clipRect.bottom());
+}
+
+void GraphicsContextPlatformPrivate::clip(const Path&)
+{
+ notImplemented();
+}
+
+void GraphicsContextPlatformPrivate::scale(const FloatSize& size)
+{
+ if (!m_hdc)
+ return;
+ XFORM xform;
+ xform.eM11 = size.width();
+ xform.eM12 = 0.0f;
+ xform.eM21 = 0.0f;
+ xform.eM22 = size.height();
+ xform.eDx = 0.0f;
+ xform.eDy = 0.0f;
+ ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
+}
+
+static const double deg2rad = 0.017453292519943295769; // pi/180
+
+void GraphicsContextPlatformPrivate::rotate(float degreesAngle)
+{
+ float radiansAngle = degreesAngle * deg2rad;
+ float cosAngle = cosf(radiansAngle);
+ float sinAngle = sinf(radiansAngle);
+ XFORM xform;
+ xform.eM11 = cosAngle;
+ xform.eM12 = -sinAngle;
+ xform.eM21 = sinAngle;
+ xform.eM22 = cosAngle;
+ xform.eDx = 0.0f;
+ xform.eDy = 0.0f;
+ ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
+}
+
+void GraphicsContextPlatformPrivate::translate(float x , float y)
+{
+ if (!m_hdc)
+ return;
+ XFORM xform;
+ xform.eM11 = 1.0f;
+ xform.eM12 = 0.0f;
+ xform.eM21 = 0.0f;
+ xform.eM22 = 1.0f;
+ xform.eDx = x;
+ xform.eDy = y;
+ ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY);
+}
+
+#if ENABLE(SVG)
+GraphicsContext* contextForImage(SVGResourceImage*)
+{
+ // FIXME: This should go in GraphicsContextCG.cpp
+ notImplemented();
+ return 0;
+}
+#endif
+
+}
diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp
new file mode 100644
index 0000000..b6bc926
--- /dev/null
+++ b/WebCore/platform/graphics/win/IconWin.cpp
@@ -0,0 +1,74 @@
+/*
+* Copyright (C) 2006, 2007 Apple 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 "Icon.h"
+
+#include "GraphicsContext.h"
+#include "PlatformString.h"
+#include <windows.h>
+
+namespace WebCore {
+
+Icon::Icon()
+ : RefCounted<Icon>(0)
+ , m_hIcon(0)
+{
+}
+
+Icon::Icon(HICON icon)
+ : RefCounted<Icon>(0)
+ , m_hIcon(icon)
+{
+}
+
+Icon::~Icon()
+{
+ if (m_hIcon)
+ DestroyIcon(m_hIcon);
+}
+
+PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+{
+ SHFILEINFO sfi;
+ memset(&sfi, 0, sizeof(sfi));
+
+ String tmpFilename = filename;
+ if (!SHGetFileInfo(tmpFilename.charactersWithNullTermination(), 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_SHELLICONSIZE | SHGFI_SMALLICON))
+ return 0;
+
+ Icon* icon = new Icon();
+ icon->m_hIcon = sfi.hIcon;
+ return icon;
+}
+
+void Icon::paint(GraphicsContext* context, const IntRect& r)
+{
+ if (context->paintingDisabled())
+ return;
+
+ HDC hdc = context->getWindowsContext(r);
+
+ DrawIconEx(hdc, r.x(), r.y(), m_hIcon, r.width(), r.height(), 0, 0, DI_NORMAL);
+
+ context->releaseWindowsContext(hdc, r);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp
new file mode 100644
index 0000000..752729c
--- /dev/null
+++ b/WebCore/platform/graphics/win/ImageCGWin.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "GraphicsContext.h"
+#include <ApplicationServices/ApplicationServices.h>
+
+#include <windows.h>
+#include "PlatformString.h"
+
+namespace WebCore {
+
+bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
+{
+ ASSERT(bmp);
+
+ BITMAP bmpInfo;
+ GetObject(bmp, sizeof(BITMAP), &bmpInfo);
+
+ ASSERT(bmpInfo.bmBitsPixel == 32);
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+
+ CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
+ CGContextRef cgContext = CGBitmapContextCreate(bmpInfo.bmBits, bmpInfo.bmWidth, bmpInfo.bmHeight,
+ 8, bmpInfo.bmWidthBytes, deviceRGB, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
+
+ GraphicsContext gc(cgContext);
+
+ IntSize imageSize = BitmapImage::size();
+ if (size)
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), CompositeCopy);
+ else
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
+
+ // Do cleanup
+ CGContextRelease(cgContext);
+ CGColorSpaceRelease(deviceRGB);
+
+ return true;
+}
+
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+{
+ int frames = frameCount();
+ for (int i = 0; i < frames; ++i) {
+ CGImageRef image = frameAtIndex(i);
+ if (CGImageGetHeight(image) == static_cast<size_t>(srcSize.height()) && CGImageGetWidth(image) == static_cast<size_t>(srcSize.width())) {
+ size_t currentFrame = m_currentFrame;
+ m_currentFrame = i;
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp);
+ m_currentFrame = currentFrame;
+ return;
+ }
+ }
+
+ // No image of the correct size was found, fallback to drawing the current frame
+ IntSize imageSize = BitmapImage::size();
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/ImageCairoWin.cpp b/WebCore/platform/graphics/win/ImageCairoWin.cpp
new file mode 100644
index 0000000..95bb7bc
--- /dev/null
+++ b/WebCore/platform/graphics/win/ImageCairoWin.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "GraphicsContext.h"
+#include <cairo.h>
+
+#include <windows.h>
+#include "PlatformString.h"
+
+namespace WebCore {
+
+bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
+{
+ ASSERT(bmp);
+
+ BITMAP bmpInfo;
+ GetObject(bmp, sizeof(BITMAP), &bmpInfo);
+
+ // If this is a 32bpp bitmap, which it always should be, we'll clear it so alpha-wise it will be visible
+ if (bmpInfo.bmBitsPixel == 32) {
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ memset(bmpInfo.bmBits, 255, bufferSize);
+ }
+
+ HDC tempDC = CreateCompatibleDC(0);
+ if (!tempDC) {
+ LOG_ERROR("Failed to create in-memory DC for Image::blit()");
+ return false;
+ }
+ SelectObject(tempDC, bmp);
+ GraphicsContext gc(tempDC);
+
+ IntSize imageSize = BitmapImage::size();
+ if (size)
+ drawFrameMatchingSourceSize(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), CompositeCopy);
+ else
+ draw(&gc, FloatRect(0.0f, 0.0f, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), CompositeCopy);
+
+ // Do cleanup
+ DeleteDC(tempDC);
+
+ return true;
+}
+
+void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, CompositeOperator compositeOp)
+{
+ int frames = frameCount();
+ for (int i = 0; i < frames; ++i) {
+ cairo_surface_t* image = frameAtIndex(i);
+ if (cairo_image_surface_get_height(image) == static_cast<size_t>(srcSize.height()) && cairo_image_surface_get_width(image) == static_cast<size_t>(srcSize.width())) {
+ size_t currentFrame = m_currentFrame;
+ m_currentFrame = i;
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, srcSize.width(), srcSize.height()), compositeOp);
+ m_currentFrame = currentFrame;
+ return;
+ }
+ }
+
+ // No image of the correct size was found, fallback to drawing the current frame
+ IntSize imageSize = BitmapImage::size();
+ draw(ctxt, dstRect, FloatRect(0.0f, 0.0f, imageSize.width(), imageSize.height()), compositeOp);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/ImageWin.cpp b/WebCore/platform/graphics/win/ImageWin.cpp
new file mode 100644
index 0000000..2d3a87a
--- /dev/null
+++ b/WebCore/platform/graphics/win/ImageWin.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 "SharedBuffer.h"
+
+// This function loads resources from WebKit
+PassRefPtr<WebCore::SharedBuffer> loadResourceIntoBuffer(const char*);
+
+namespace WebCore {
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+Image* Image::loadPlatformResource(const char *name)
+{
+ RefPtr<SharedBuffer> buffer = loadResourceIntoBuffer(name);
+ BitmapImage* img = new BitmapImage;
+ img->setData(buffer.release(), true);
+ return img;
+}
+
+bool BitmapImage::getHBITMAP(HBITMAP bmp)
+{
+ return getHBITMAPOfSize(bmp, 0);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/win/IntPointWin.cpp b/WebCore/platform/graphics/win/IntPointWin.cpp
new file mode 100644
index 0000000..a6ce0bb
--- /dev/null
+++ b/WebCore/platform/graphics/win/IntPointWin.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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 "IntPoint.h"
+
+#include <windows.h>
+
+namespace WebCore {
+
+IntPoint::IntPoint(const POINT& p)
+ : m_x(p.x)
+ , m_y(p.y)
+{
+}
+
+IntPoint::operator POINT() const
+{
+ POINT p = {m_x, m_y};
+ return p;
+}
+
+IntPoint::IntPoint(const POINTS& p)
+ : m_x(p.x)
+ , m_y(p.y)
+{
+}
+
+IntPoint::operator POINTS() const
+{
+ POINTS p = {m_x, m_y};
+ return p;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/IntRectWin.cpp b/WebCore/platform/graphics/win/IntRectWin.cpp
new file mode 100644
index 0000000..6228be8
--- /dev/null
+++ b/WebCore/platform/graphics/win/IntRectWin.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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 "IntRect.h"
+
+#include <windows.h>
+
+namespace WebCore {
+
+IntRect::IntRect(const RECT& r)
+ : m_location(IntPoint(r.left, r.top)), m_size(IntSize(r.right-r.left, r.bottom-r.top))
+{
+}
+
+IntRect::operator RECT() const
+{
+ RECT rect = { x(), y(), right(), bottom() };
+ return rect;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/IntSizeWin.cpp b/WebCore/platform/graphics/win/IntSizeWin.cpp
new file mode 100644
index 0000000..8a27cdb
--- /dev/null
+++ b/WebCore/platform/graphics/win/IntSizeWin.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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 "IntSize.h"
+
+#include <windows.h>
+
+namespace WebCore {
+
+IntSize::IntSize(const SIZE& s)
+ : m_width(s.cx)
+ , m_height(s.cy)
+{
+}
+
+IntSize::operator SIZE() const
+{
+ SIZE s = {m_width, m_height};
+ return s;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
new file mode 100644
index 0000000..c7d3bf8
--- /dev/null
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2007 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(VIDEO)
+#include "MediaPlayerPrivateQuickTimeWin.h"
+
+#include "GraphicsContext.h"
+#include "KURL.h"
+#include "QTMovieWin.h"
+#include "ScrollView.h"
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static const double endPointTimerInterval = 0.020;
+
+MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
+ : m_player(player)
+ , m_seekTo(-1)
+ , m_endTime(numeric_limits<float>::infinity())
+ , m_seekTimer(this, &MediaPlayerPrivate::seekTimerFired)
+ , m_endPointTimer(this, &MediaPlayerPrivate::endPointTimerFired)
+ , m_networkState(MediaPlayer::Empty)
+ , m_readyState(MediaPlayer::DataUnavailable)
+ , m_startedPlaying(false)
+ , m_isStreaming(false)
+{
+}
+
+MediaPlayerPrivate::~MediaPlayerPrivate()
+{
+}
+
+void MediaPlayerPrivate::load(const String& url)
+{
+ if (!QTMovieWin::initializeQuickTime()) {
+ m_networkState = MediaPlayer::LoadFailed;
+ m_player->networkStateChanged();
+ return;
+ }
+
+ if (m_networkState != MediaPlayer::Loading) {
+ m_networkState = MediaPlayer::Loading;
+ m_player->networkStateChanged();
+ }
+ if (m_readyState != MediaPlayer::DataUnavailable) {
+ m_readyState = MediaPlayer::DataUnavailable;
+ m_player->readyStateChanged();
+ }
+ cancelSeek();
+ m_endPointTimer.stop();
+
+ m_qtMovie.set(new QTMovieWin(this));
+ m_qtMovie->load(url.characters(), url.length());
+ m_qtMovie->setVolume(m_player->m_volume);
+ m_qtMovie->setVisible(m_player->m_visible);
+}
+
+void MediaPlayerPrivate::play()
+{
+ if (!m_qtMovie)
+ return;
+ m_startedPlaying = true;
+
+ m_qtMovie->play();
+ startEndPointTimerIfNeeded();
+}
+
+void MediaPlayerPrivate::pause()
+{
+ if (!m_qtMovie)
+ return;
+ m_startedPlaying = false;
+ m_qtMovie->pause();
+ m_endPointTimer.stop();
+}
+
+float MediaPlayerPrivate::duration() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return m_qtMovie->duration();
+}
+
+float MediaPlayerPrivate::currentTime() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return min(m_qtMovie->currentTime(), m_endTime);
+}
+
+void MediaPlayerPrivate::seek(float time)
+{
+ cancelSeek();
+
+ if (!m_qtMovie)
+ return;
+
+ if (time > duration())
+ time = duration();
+
+ m_seekTo = time;
+ if (maxTimeLoaded() >= m_seekTo)
+ doSeek();
+ else
+ m_seekTimer.start(0, 0.5f);
+}
+
+void MediaPlayerPrivate::doSeek()
+{
+ float oldRate = m_qtMovie->rate();
+ m_qtMovie->setRate(0);
+ m_qtMovie->setCurrentTime(m_seekTo);
+ float timeAfterSeek = currentTime();
+ // restore playback only if not at end, othewise QTMovie will loop
+ if (timeAfterSeek < duration() && timeAfterSeek < m_endTime)
+ m_qtMovie->setRate(oldRate);
+ cancelSeek();
+}
+
+void MediaPlayerPrivate::cancelSeek()
+{
+ m_seekTo = -1;
+ m_seekTimer.stop();
+}
+
+void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*)
+{
+ if (!m_qtMovie || !seeking() || currentTime() == m_seekTo) {
+ cancelSeek();
+ updateStates();
+ m_player->timeChanged();
+ return;
+ }
+
+ if (maxTimeLoaded() >= m_seekTo)
+ doSeek();
+ else {
+ MediaPlayer::NetworkState state = networkState();
+ if (state == MediaPlayer::Empty || state == MediaPlayer::Loaded) {
+ cancelSeek();
+ updateStates();
+ m_player->timeChanged();
+ }
+ }
+}
+
+void MediaPlayerPrivate::setEndTime(float time)
+{
+ m_endTime = time;
+ startEndPointTimerIfNeeded();
+}
+
+void MediaPlayerPrivate::startEndPointTimerIfNeeded()
+{
+ if (m_endTime < duration() && m_startedPlaying && !m_endPointTimer.isActive())
+ m_endPointTimer.startRepeating(endPointTimerInterval);
+}
+
+void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*)
+{
+ float time = currentTime();
+ if (time >= m_endTime) {
+ pause();
+ didEnd();
+ }
+}
+
+bool MediaPlayerPrivate::paused() const
+{
+ if (!m_qtMovie)
+ return true;
+ return m_qtMovie->rate() == 0.0f;
+}
+
+bool MediaPlayerPrivate::seeking() const
+{
+ if (!m_qtMovie)
+ return false;
+ return m_seekTo >= 0;
+}
+
+IntSize MediaPlayerPrivate::naturalSize() const
+{
+ if (!m_qtMovie)
+ return IntSize();
+ int width;
+ int height;
+ m_qtMovie->getNaturalSize(width, height);
+ return IntSize(width, height);
+}
+
+bool MediaPlayerPrivate::hasVideo() const
+{
+ // This is not used at the moment
+ return true;
+}
+
+void MediaPlayerPrivate::setVolume(float volume)
+{
+ if (!m_qtMovie)
+ return;
+ m_qtMovie->setVolume(volume);
+}
+
+void MediaPlayerPrivate::setRate(float rate)
+{
+ if (!m_qtMovie)
+ return;
+ if (!paused())
+ m_qtMovie->setRate(rate);
+}
+
+int MediaPlayerPrivate::dataRate() const
+{
+ // This is not used at the moment
+ return 0;
+}
+
+float MediaPlayerPrivate::maxTimeBuffered() const
+{
+ // rtsp streams are not buffered
+ return m_isStreaming ? 0 : maxTimeLoaded();
+}
+
+float MediaPlayerPrivate::maxTimeSeekable() const
+{
+ // infinite duration means live stream
+ return !isfinite(duration()) ? 0 : maxTimeLoaded();
+}
+
+float MediaPlayerPrivate::maxTimeLoaded() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return m_qtMovie->maxTimeLoaded();
+}
+
+unsigned MediaPlayerPrivate::bytesLoaded() const
+{
+ if (!m_qtMovie)
+ return 0;
+ float dur = duration();
+ float maxTime = maxTimeLoaded();
+ if (!dur)
+ return 0;
+ return totalBytes() * maxTime / dur;
+}
+
+bool MediaPlayerPrivate::totalBytesKnown() const
+{
+ return totalBytes() > 0;
+}
+
+unsigned MediaPlayerPrivate::totalBytes() const
+{
+ if (!m_qtMovie)
+ return 0;
+ return m_qtMovie->dataSize();
+}
+
+void MediaPlayerPrivate::cancelLoad()
+{
+ if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
+ return;
+
+ // Cancel the load by destroying the movie.
+ m_qtMovie.clear();
+
+ updateStates();
+}
+
+void MediaPlayerPrivate::updateStates()
+{
+ MediaPlayer::NetworkState oldNetworkState = m_networkState;
+ MediaPlayer::ReadyState oldReadyState = m_readyState;
+
+ long loadState = m_qtMovie ? m_qtMovie->loadState() : QTMovieLoadStateError;
+
+ if (loadState >= QTMovieLoadStateLoaded && m_networkState < MediaPlayer::LoadedMetaData) {
+ unsigned enabledTrackCount;
+ m_qtMovie->disableUnsupportedTracks(enabledTrackCount);
+ // FIXME: We should differentiate between load errors and decode errors <rdar://problem/5605692>
+ if (!enabledTrackCount)
+ loadState = QTMovieLoadStateError;
+ }
+
+ // "Loaded" is reserved for fully buffered movies, never the case when streaming
+ if (loadState >= QTMovieLoadStateComplete && !m_isStreaming) {
+ if (m_networkState < MediaPlayer::Loaded)
+ m_networkState = MediaPlayer::Loaded;
+ m_readyState = MediaPlayer::CanPlayThrough;
+ } else if (loadState >= QTMovieLoadStatePlaythroughOK) {
+ if (m_networkState < MediaPlayer::LoadedFirstFrame && !seeking())
+ m_networkState = MediaPlayer::LoadedFirstFrame;
+ m_readyState = MediaPlayer::CanPlayThrough;
+ } else if (loadState >= QTMovieLoadStatePlayable) {
+ if (m_networkState < MediaPlayer::LoadedFirstFrame && !seeking())
+ m_networkState = MediaPlayer::LoadedFirstFrame;
+ m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::CanPlay : MediaPlayer::DataUnavailable;
+ } else if (loadState >= QTMovieLoadStateLoaded) {
+ if (m_networkState < MediaPlayer::LoadedMetaData)
+ m_networkState = MediaPlayer::LoadedMetaData;
+ m_readyState = MediaPlayer::DataUnavailable;
+ } else if (loadState > QTMovieLoadStateError) {
+ if (m_networkState < MediaPlayer::Loading)
+ m_networkState = MediaPlayer::Loading;
+ m_readyState = MediaPlayer::DataUnavailable;
+ } else {
+ m_networkState = MediaPlayer::LoadFailed;
+ m_readyState = MediaPlayer::DataUnavailable;
+ }
+
+ if (seeking())
+ m_readyState = MediaPlayer::DataUnavailable;
+
+ if (m_networkState != oldNetworkState)
+ m_player->networkStateChanged();
+ if (m_readyState != oldReadyState)
+ m_player->readyStateChanged();
+}
+
+
+void MediaPlayerPrivate::didEnd()
+{
+ m_endPointTimer.stop();
+ m_startedPlaying = false;
+ updateStates();
+ m_player->timeChanged();
+}
+
+void MediaPlayerPrivate::setRect(const IntRect& r)
+{
+ if (m_qtMovie)
+ m_qtMovie->setSize(r.width(), r.height());
+}
+
+void MediaPlayerPrivate::setVisible(bool b)
+{
+ if (!m_qtMovie)
+ return;
+ m_qtMovie->setVisible(b);
+}
+
+void MediaPlayerPrivate::paint(GraphicsContext* p, const IntRect& r)
+{
+ if (p->paintingDisabled() || !m_qtMovie)
+ return;
+ HDC hdc = p->getWindowsContext(r);
+ m_qtMovie->paint(hdc, r.x(), r.y());
+ p->releaseWindowsContext(hdc, r);
+}
+
+void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
+{
+ unsigned count = QTMovieWin::countSupportedTypes();
+ for (unsigned n = 0; n < count; n++) {
+ const UChar* character;
+ unsigned len;
+ QTMovieWin::getSupportedType(n, character, len);
+ if (len)
+ types.add(String(character, len));
+ }
+}
+
+bool MediaPlayerPrivate::isAvailable()
+{
+ return QTMovieWin::initializeQuickTime();
+}
+
+void MediaPlayerPrivate::movieEnded(QTMovieWin* movie)
+{
+ ASSERT(m_qtMovie.get() == movie);
+ didEnd();
+}
+
+void MediaPlayerPrivate::movieLoadStateChanged(QTMovieWin* movie)
+{
+ ASSERT(m_qtMovie.get() == movie);
+ updateStates();
+}
+
+void MediaPlayerPrivate::movieTimeChanged(QTMovieWin* movie)
+{
+ ASSERT(m_qtMovie.get() == movie);
+ updateStates();
+ m_player->timeChanged();
+}
+
+void MediaPlayerPrivate::movieNewImageAvailable(QTMovieWin* movie)
+{
+ ASSERT(m_qtMovie.get() == movie);
+ m_player->repaint();
+}
+
+}
+
+#endif
+
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
new file mode 100644
index 0000000..37b5b05
--- /dev/null
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007 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 MediaPlayerPrivateQTKit_h
+#define MediaPlayerPrivateQTKit_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayer.h"
+#include "Timer.h"
+#include <QTMovieWin.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext;
+class IntSize;
+class IntRect;
+class String;
+
+class MediaPlayerPrivate : QTMovieWinClient, Noncopyable {
+public:
+ MediaPlayerPrivate(MediaPlayer*);
+ ~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; }
+
+ float maxTimeBuffered() const;
+ float maxTimeSeekable() const;
+ unsigned bytesLoaded() const;
+ bool totalBytesKnown() const;
+ unsigned totalBytes() const;
+
+ void setVisible(bool);
+ void setRect(const IntRect&);
+
+ void loadStateChanged();
+ void didEnd();
+
+ void paint(GraphicsContext*, const IntRect&);
+
+ static void getSupportedTypes(HashSet<String>& types);
+ static bool isAvailable();
+
+private:
+ void updateStates();
+ void doSeek();
+ void cancelSeek();
+ void seekTimerFired(Timer<MediaPlayerPrivate>*);
+ void endPointTimerFired(Timer<MediaPlayerPrivate>*);
+ float maxTimeLoaded() const;
+ void startEndPointTimerIfNeeded();
+
+ virtual void movieEnded(QTMovieWin*);
+ virtual void movieLoadStateChanged(QTMovieWin*);
+ virtual void movieTimeChanged(QTMovieWin*);
+ virtual void movieNewImageAvailable(QTMovieWin*);
+
+ MediaPlayer* m_player;
+ OwnPtr<QTMovieWin> m_qtMovie;
+ float m_seekTo;
+ float m_endTime;
+ Timer<MediaPlayerPrivate> m_seekTimer;
+ Timer<MediaPlayerPrivate> m_endPointTimer;
+ MediaPlayer::NetworkState m_networkState;
+ MediaPlayer::ReadyState m_readyState;
+ bool m_startedPlaying;
+ bool m_isStreaming;
+};
+
+}
+
+#endif
+#endif
diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp
new file mode 100644
index 0000000..80c6d50
--- /dev/null
+++ b/WebCore/platform/graphics/win/QTMovieWin.cpp
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2007 Apple Computer, 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"
+
+#include <windows.h>
+
+#include "QTMovieWin.h"
+
+// Put Movies.h first so build failures here point clearly to QuickTime
+#include <Movies.h>
+#include <GXMath.h>
+#include <QTML.h>
+
+#include "QTMovieWinTimer.h"
+
+#include <wtf/Assertions.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+using namespace std;
+
+static const long minimumQuickTimeVersion = 0x07300000; // 7.3
+
+// Resizing GWorlds is slow, give them a minimum size so size of small
+// videos can be animated smoothly
+static const int cGWorldMinWidth = 640;
+static const int cGWorldMinHeight = 360;
+
+static const float cNonContinuousTimeChange = 0.2f;
+
+union UppParam {
+ long longValue;
+ void* ptr;
+};
+
+static MovieDrawingCompleteUPP gMovieDrawingCompleteUPP = 0;
+static HashSet<QTMovieWinPrivate*>* gTaskList;
+static Vector<CFStringRef>* gSupportedTypes = 0;
+
+static void updateTaskTimer(int maxInterval = 1000)
+{
+ if (!gTaskList->size()) {
+ stopSharedTimer();
+ return;
+ }
+
+ long intervalInMS;
+ QTGetTimeUntilNextTask(&intervalInMS, 1000);
+ if (intervalInMS > maxInterval)
+ intervalInMS = maxInterval;
+ setSharedTimerFireDelay(static_cast<float>(intervalInMS) / 1000);
+}
+
+class QTMovieWinPrivate : Noncopyable {
+public:
+ QTMovieWinPrivate();
+ ~QTMovieWinPrivate();
+ void task();
+ void startTask();
+ void endTask();
+
+ void registerDrawingCallback();
+ void drawingComplete();
+ void updateGWorld();
+ void createGWorld();
+ void deleteGWorld();
+
+ void setSize(int, int);
+
+ QTMovieWin* m_movieWin;
+ Movie m_movie;
+ bool m_tasking;
+ QTMovieWinClient* m_client;
+ long m_loadState;
+ bool m_ended;
+ bool m_seeking;
+ float m_lastMediaTime;
+ double m_lastLoadStateCheckTime;
+ int m_width;
+ int m_height;
+ bool m_visible;
+ GWorldPtr m_gWorld;
+ int m_gWorldWidth;
+ int m_gWorldHeight;
+ GWorldPtr m_savedGWorld;
+ long m_loadError;
+};
+
+QTMovieWinPrivate::QTMovieWinPrivate()
+ : m_movieWin(0)
+ , m_movie(0)
+ , m_tasking(false)
+ , m_client(0)
+ , m_loadState(0)
+ , m_ended(false)
+ , m_seeking(false)
+ , m_lastMediaTime(0)
+ , m_lastLoadStateCheckTime(0)
+ , m_width(0)
+ , m_height(0)
+ , m_visible(false)
+ , m_gWorld(0)
+ , m_gWorldWidth(0)
+ , m_gWorldHeight(0)
+ , m_savedGWorld(0)
+ , m_loadError(0)
+{
+}
+
+QTMovieWinPrivate::~QTMovieWinPrivate()
+{
+ endTask();
+ if (m_gWorld)
+ deleteGWorld();
+ if (m_movie)
+ DisposeMovie(m_movie);
+}
+
+static void taskTimerFired()
+{
+ // The hash content might change during task()
+ Vector<QTMovieWinPrivate*> tasks;
+ copyToVector(*gTaskList, tasks);
+ size_t count = tasks.size();
+ for (unsigned n = 0; n < count; ++n)
+ tasks[n]->task();
+
+ updateTaskTimer();
+}
+
+void QTMovieWinPrivate::startTask()
+{
+ if (m_tasking)
+ return;
+ if (!gTaskList)
+ gTaskList = new HashSet<QTMovieWinPrivate*>;
+ gTaskList->add(this);
+ m_tasking = true;
+ updateTaskTimer();
+}
+
+void QTMovieWinPrivate::endTask()
+{
+ if (!m_tasking)
+ return;
+ gTaskList->remove(this);
+ m_tasking = false;
+ updateTaskTimer();
+}
+
+void QTMovieWinPrivate::task()
+{
+ ASSERT(m_tasking);
+
+ if (!m_loadError)
+ MoviesTask(m_movie, 0);
+
+ // GetMovieLoadState documentation says that you should not call it more often than every quarter of a second.
+ if (systemTime() >= m_lastLoadStateCheckTime + 0.25 || m_loadError) {
+ // If load fails QT's load state is kMovieLoadStateComplete.
+ // This is different from QTKit API and seems strange.
+ long loadState = m_loadError ? kMovieLoadStateError : GetMovieLoadState(m_movie);
+ if (loadState != m_loadState) {
+ m_loadState = loadState;
+ m_client->movieLoadStateChanged(m_movieWin);
+ }
+ m_lastLoadStateCheckTime = systemTime();
+ }
+
+ bool ended = !!IsMovieDone(m_movie);
+ if (ended != m_ended) {
+ m_ended = ended;
+ if (m_client && ended)
+ m_client->movieEnded(m_movieWin);
+ }
+
+ float time = m_movieWin->currentTime();
+ if (time < m_lastMediaTime || time >= m_lastMediaTime + cNonContinuousTimeChange || m_seeking) {
+ m_seeking = false;
+ if (m_client)
+ m_client->movieTimeChanged(m_movieWin);
+ }
+ m_lastMediaTime = time;
+
+ if (m_loadError)
+ endTask();
+}
+
+void QTMovieWinPrivate::registerDrawingCallback()
+{
+ UppParam param;
+ param.ptr = this;
+ SetMovieDrawingCompleteProc(m_movie, movieDrawingCallWhenChanged, gMovieDrawingCompleteUPP, param.longValue);
+}
+
+void QTMovieWinPrivate::drawingComplete()
+{
+ if (!m_gWorld)
+ return;
+ m_client->movieNewImageAvailable(m_movieWin);
+}
+
+void QTMovieWinPrivate::updateGWorld()
+{
+ bool shouldBeVisible = m_visible;
+ if (!m_height || !m_width)
+ shouldBeVisible = false;
+
+ if (shouldBeVisible && !m_gWorld)
+ createGWorld();
+ else if (!shouldBeVisible && m_gWorld)
+ deleteGWorld();
+ else if (m_gWorld && (m_width > m_gWorldWidth || m_height > m_gWorldHeight)) {
+ // need a bigger, better gWorld
+ deleteGWorld();
+ createGWorld();
+ }
+}
+
+void QTMovieWinPrivate::createGWorld()
+{
+ ASSERT(!m_gWorld);
+ if (!m_movie)
+ return;
+
+ m_gWorldWidth = max(cGWorldMinWidth, m_width);
+ m_gWorldHeight = max(cGWorldMinHeight, m_height);
+ Rect bounds;
+ bounds.top = 0;
+ bounds.left = 0;
+ bounds.right = m_gWorldWidth;
+ bounds.bottom = m_gWorldHeight;
+ OSErr err = QTNewGWorld(&m_gWorld, k32BGRAPixelFormat, &bounds, NULL, NULL, NULL);
+ if (err)
+ return;
+ GetMovieGWorld(m_movie, &m_savedGWorld, 0);
+ SetMovieGWorld(m_movie, m_gWorld, 0);
+ bounds.right = m_width;
+ bounds.bottom = m_height;
+ SetMovieBox(m_movie, &bounds);
+}
+
+void QTMovieWinPrivate::setSize(int width, int height)
+{
+ if (m_width == width && m_height == height)
+ return;
+ m_width = width;
+ m_height = height;
+ if (!m_movie)
+ return;
+ Rect bounds;
+ bounds.top = 0;
+ bounds.left = 0;
+ bounds.right = width;
+ bounds.bottom = height;
+ SetMovieBox(m_movie, &bounds);
+ updateGWorld();
+}
+
+void QTMovieWinPrivate::deleteGWorld()
+{
+ ASSERT(m_gWorld);
+ if (m_movie)
+ SetMovieGWorld(m_movie, m_savedGWorld, 0);
+ m_savedGWorld = 0;
+ DisposeGWorld(m_gWorld);
+ m_gWorld = 0;
+ m_gWorldWidth = 0;
+ m_gWorldHeight = 0;
+}
+
+
+QTMovieWin::QTMovieWin(QTMovieWinClient* client)
+ : m_private(new QTMovieWinPrivate())
+{
+ m_private->m_movieWin = this;
+ m_private->m_client = client;
+ initializeQuickTime();
+}
+
+QTMovieWin::~QTMovieWin()
+{
+ delete m_private;
+}
+
+void QTMovieWin::play()
+{
+ StartMovie(m_private->m_movie);
+ m_private->startTask();
+}
+
+void QTMovieWin::pause()
+{
+ StopMovie(m_private->m_movie);
+ updateTaskTimer();
+}
+
+float QTMovieWin::rate() const
+{
+ return FixedToFloat(GetMovieRate(m_private->m_movie));
+}
+
+void QTMovieWin::setRate(float rate)
+{
+ SetMovieRate(m_private->m_movie, FloatToFixed(rate));
+ updateTaskTimer();
+}
+
+float QTMovieWin::duration() const
+{
+ if (!m_private->m_movie)
+ return 0;
+ TimeValue val = GetMovieDuration(m_private->m_movie);
+ TimeScale scale = GetMovieTimeScale(m_private->m_movie);
+ return static_cast<float>(val) / scale;
+}
+
+float QTMovieWin::currentTime() const
+{
+ if (!m_private->m_movie)
+ return 0;
+ TimeValue val = GetMovieTime(m_private->m_movie, 0);
+ TimeScale scale = GetMovieTimeScale(m_private->m_movie);
+ return static_cast<float>(val) / scale;
+}
+
+void QTMovieWin::setCurrentTime(float time) const
+{
+ if (!m_private->m_movie)
+ return;
+ m_private->m_seeking = true;
+ TimeScale scale = GetMovieTimeScale(m_private->m_movie);
+ SetMovieTimeValue(m_private->m_movie, TimeValue(time * scale));
+ updateTaskTimer();
+}
+
+void QTMovieWin::setVolume(float volume)
+{
+ SetMovieVolume(m_private->m_movie, static_cast<short>(volume * 256));
+}
+
+unsigned QTMovieWin::dataSize() const
+{
+ // FIXME: How to get this?
+ return 1000;
+}
+
+float QTMovieWin::maxTimeLoaded() const
+{
+ if (!m_private->m_movie)
+ return 0;
+ TimeValue val;
+ GetMaxLoadedTimeInMovie(m_private->m_movie, &val);
+ TimeScale scale = GetMovieTimeScale(m_private->m_movie);
+ return static_cast<float>(val) / scale;
+}
+
+long QTMovieWin::loadState() const
+{
+ return m_private->m_loadState;
+}
+
+void QTMovieWin::getNaturalSize(int& width, int& height)
+{
+ Rect rect;
+ GetMovieNaturalBoundsRect(m_private->m_movie, &rect);
+ width = rect.right;
+ height = rect.bottom;
+}
+
+void QTMovieWin::setSize(int width, int height)
+{
+ m_private->setSize(width, height);
+ updateTaskTimer(0);
+}
+
+void QTMovieWin::setVisible(bool b)
+{
+ m_private->m_visible = b;
+ m_private->updateGWorld();
+}
+
+void QTMovieWin::paint(HDC hdc, int x, int y)
+{
+ if (!m_private->m_gWorld)
+ return;
+
+ HDC hdcSrc = static_cast<HDC>(GetPortHDC(reinterpret_cast<GrafPtr>(m_private->m_gWorld)));
+ if (!hdcSrc)
+ return;
+
+ // FIXME: If we could determine the movie has no alpha, we could use BitBlt for those cases, which might be faster.
+ BLENDFUNCTION blendFunction;
+ blendFunction.BlendOp = AC_SRC_OVER;
+ blendFunction.BlendFlags = 0;
+ blendFunction.SourceConstantAlpha = 255;
+ blendFunction.AlphaFormat = AC_SRC_ALPHA;
+ AlphaBlend(hdc, x, y, m_private->m_width, m_private->m_height, hdcSrc,
+ 0, 0, m_private->m_width, m_private->m_height, blendFunction);
+}
+
+void QTMovieWin::load(const UChar* url, int len)
+{
+ if (m_private->m_movie) {
+ m_private->endTask();
+ if (m_private->m_gWorld)
+ m_private->deleteGWorld();
+ DisposeMovie(m_private->m_movie);
+ m_private->m_movie = 0;
+ }
+
+ // Define a property array for NewMovieFromProperties. 8 should be enough for our needs.
+ QTNewMoviePropertyElement movieProps[8];
+ ItemCount moviePropCount = 0;
+
+ bool boolTrue = true;
+
+ // Create a URL data reference of type CFURL
+ CFStringRef urlStringRef = CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar*>(url), len);
+
+ // Disable streaming support for now.
+ if (CFStringHasPrefix(urlStringRef, CFSTR("rtsp:"))) {
+ m_private->m_loadError = noMovieFound;
+ goto end;
+ }
+
+ CFURLRef urlRef = CFURLCreateWithString(kCFAllocatorDefault, urlStringRef, 0);
+
+ // Add the movie data location to the property array
+ movieProps[moviePropCount].propClass = kQTPropertyClass_DataLocation;
+ movieProps[moviePropCount].propID = kQTDataLocationPropertyID_CFURL;
+ movieProps[moviePropCount].propValueSize = sizeof(urlRef);
+ movieProps[moviePropCount].propValueAddress = &urlRef;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ movieProps[moviePropCount].propClass = kQTPropertyClass_MovieInstantiation;
+ movieProps[moviePropCount].propID = kQTMovieInstantiationPropertyID_DontAskUnresolvedDataRefs;
+ movieProps[moviePropCount].propValueSize = sizeof(boolTrue);
+ movieProps[moviePropCount].propValueAddress = &boolTrue;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ movieProps[moviePropCount].propClass = kQTPropertyClass_MovieInstantiation;
+ movieProps[moviePropCount].propID = kQTMovieInstantiationPropertyID_AsyncOK;
+ movieProps[moviePropCount].propValueSize = sizeof(boolTrue);
+ movieProps[moviePropCount].propValueAddress = &boolTrue;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ movieProps[moviePropCount].propClass = kQTPropertyClass_NewMovieProperty;
+ movieProps[moviePropCount].propID = kQTNewMoviePropertyID_Active;
+ movieProps[moviePropCount].propValueSize = sizeof(boolTrue);
+ movieProps[moviePropCount].propValueAddress = &boolTrue;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ movieProps[moviePropCount].propClass = kQTPropertyClass_NewMovieProperty;
+ movieProps[moviePropCount].propID = kQTNewMoviePropertyID_DontInteractWithUser;
+ movieProps[moviePropCount].propValueSize = sizeof(boolTrue);
+ movieProps[moviePropCount].propValueAddress = &boolTrue;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ movieProps[moviePropCount].propClass = kQTPropertyClass_MovieInstantiation;
+ movieProps[moviePropCount].propID = '!url';
+ movieProps[moviePropCount].propValueSize = sizeof(boolTrue);
+ movieProps[moviePropCount].propValueAddress = &boolTrue;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ movieProps[moviePropCount].propClass = kQTPropertyClass_MovieInstantiation;
+ movieProps[moviePropCount].propID = 'site';
+ movieProps[moviePropCount].propValueSize = sizeof(boolTrue);
+ movieProps[moviePropCount].propValueAddress = &boolTrue;
+ movieProps[moviePropCount].propStatus = 0;
+ moviePropCount++;
+
+ m_private->m_loadError = NewMovieFromProperties(moviePropCount, movieProps, 0, NULL, &m_private->m_movie);
+
+ CFRelease(urlRef);
+end:
+ m_private->startTask();
+ // get the load fail callback quickly
+ if (m_private->m_loadError)
+ updateTaskTimer(0);
+ else
+ m_private->registerDrawingCallback();
+
+ CFRelease(urlStringRef);
+}
+
+void QTMovieWin::disableUnsupportedTracks(unsigned& enabledTrackCount)
+{
+ if (!m_private->m_movie) {
+ enabledTrackCount = 0;
+ return;
+ }
+
+ static HashSet<OSType>* allowedTrackTypes = 0;
+ if (!allowedTrackTypes) {
+ allowedTrackTypes = new HashSet<OSType>;
+ allowedTrackTypes->add(VideoMediaType);
+ allowedTrackTypes->add(SoundMediaType);
+ allowedTrackTypes->add(TextMediaType);
+ allowedTrackTypes->add(BaseMediaType);
+ allowedTrackTypes->add('clcp'); // Closed caption
+ allowedTrackTypes->add('sbtl'); // Subtitle
+ }
+
+ long trackCount = GetMovieTrackCount(m_private->m_movie);
+ enabledTrackCount = trackCount;
+
+ // Track indexes are 1-based. yuck. These things must descend from old-
+ // school mac resources or something.
+ for (long trackIndex = 1; trackIndex <= trackCount; trackIndex++) {
+ // Grab the track at the current index. If there isn't one there, then
+ // we can move onto the next one.
+ Track currentTrack = GetMovieIndTrack(m_private->m_movie, trackIndex);
+ if (!currentTrack)
+ continue;
+
+ // Check to see if the track is disabled already, we should move along.
+ // We don't need to re-disable it.
+ if (!GetTrackEnabled(currentTrack))
+ continue;
+
+ // Grab the track's media. We're going to check to see if we need to
+ // disable the tracks. They could be unsupported.
+ Media trackMedia = GetTrackMedia(currentTrack);
+ if (!trackMedia)
+ continue;
+
+ // Grab the media type for this track. Make sure that we don't
+ // get an error in doing so. If we do, then something really funky is
+ // wrong.
+ OSType mediaType;
+ GetMediaHandlerDescription(trackMedia, &mediaType, nil, nil);
+ OSErr mediaErr = GetMoviesError();
+ if (mediaErr != noErr)
+ continue;
+
+ if (!allowedTrackTypes->contains(mediaType)) {
+ SetTrackEnabled(currentTrack, false);
+ --enabledTrackCount;
+ }
+
+ // Grab the track reference count for chapters. This will tell us if it
+ // has chapter tracks in it. If there aren't any references, then we
+ // can move on the next track.
+ long referenceCount = GetTrackReferenceCount(currentTrack, kTrackReferenceChapterList);
+ if (referenceCount <= 0)
+ continue;
+
+ long referenceIndex = 0;
+ while (1) {
+ // If we get nothing here, we've overstepped our bounds and can stop
+ // looking. Chapter indices here are 1-based as well - hence, the
+ // pre-increment.
+ referenceIndex++;
+ Track chapterTrack = GetTrackReference(currentTrack, kTrackReferenceChapterList, referenceIndex);
+ if (!chapterTrack)
+ break;
+
+ // Try to grab the media for the track.
+ Media chapterMedia = GetTrackMedia(chapterTrack);
+ if (!chapterMedia)
+ continue;
+
+ // Grab the media type for this track. Make sure that we don't
+ // get an error in doing so. If we do, then something really
+ // funky is wrong.
+ OSType mediaType;
+ GetMediaHandlerDescription(chapterMedia, &mediaType, nil, nil);
+ OSErr mediaErr = GetMoviesError();
+ if (mediaErr != noErr)
+ continue;
+
+ // Check to see if the track is a video track. We don't care about
+ // other non-video tracks.
+ if (mediaType != VideoMediaType)
+ continue;
+
+ // Check to see if the track is already disabled. If it is, we
+ // should move along.
+ if (!GetTrackEnabled(chapterTrack))
+ continue;
+
+ // Disabled the evil, evil track.
+ SetTrackEnabled(chapterTrack, false);
+ --enabledTrackCount;
+ }
+ }
+}
+
+pascal OSErr movieDrawingCompleteProc(Movie movie, long data)
+{
+ UppParam param;
+ param.longValue = data;
+ QTMovieWinPrivate* mp = static_cast<QTMovieWinPrivate*>(param.ptr);
+ if (mp)
+ mp->drawingComplete();
+ return 0;
+}
+
+static void initializeSupportedTypes()
+{
+ if (gSupportedTypes)
+ return;
+ // FIXME: This list might not be complete.
+ // There must be some way to get it out from QuickTime.
+ gSupportedTypes = new Vector<CFStringRef>;
+ gSupportedTypes->append(CFSTR("video/3gpp"));
+ gSupportedTypes->append(CFSTR("video/3gpp2"));
+ gSupportedTypes->append(CFSTR("video/mp4"));
+ gSupportedTypes->append(CFSTR("video/mpeg"));
+ gSupportedTypes->append(CFSTR("video/quicktime"));
+ gSupportedTypes->append(CFSTR("audio/ac3"));
+ gSupportedTypes->append(CFSTR("audio/aiff"));
+ gSupportedTypes->append(CFSTR("audio/basic"));
+ gSupportedTypes->append(CFSTR("audio/mpeg"));
+}
+
+unsigned QTMovieWin::countSupportedTypes()
+{
+ initializeSupportedTypes();
+ return static_cast<unsigned>(gSupportedTypes->size());
+}
+
+void QTMovieWin::getSupportedType(unsigned index, const UChar*& str, unsigned& len)
+{
+ initializeSupportedTypes();
+ ASSERT(index < gSupportedTypes->size());
+
+ // Allocate sufficient buffer to hold any MIME type
+ static UniChar* staticBuffer = 0;
+ if (!staticBuffer)
+ staticBuffer = new UniChar[32];
+
+ CFStringRef cfstr = gSupportedTypes->at(index);
+ len = CFStringGetLength(cfstr);
+ CFRange range = { 0, len };
+ CFStringGetCharacters(cfstr, range, staticBuffer);
+ str = reinterpret_cast<const UChar*>(staticBuffer);
+
+}
+
+bool QTMovieWin::initializeQuickTime()
+{
+ static bool initialized = false;
+ static bool initializationSucceeded = false;
+ if (!initialized) {
+ initialized = true;
+ // Initialize and check QuickTime version
+ OSErr result = InitializeQTML(0);
+ SInt32 version = 0;
+ if (result == noErr)
+ result = Gestalt(gestaltQuickTime, &version);
+ if (result != noErr) {
+ LOG_ERROR("No QuickTime available. Disabling <video> and <audio> support.");
+ return false;
+ }
+ if (version < minimumQuickTimeVersion) {
+ LOG_ERROR("QuickTime version %x detected, at least %x required. Disabling <video> and <audio> support.", version, minimumQuickTimeVersion);
+ return false;
+ }
+ EnterMovies();
+ setSharedTimerFiredFunction(taskTimerFired);
+ gMovieDrawingCompleteUPP = NewMovieDrawingCompleteUPP(movieDrawingCompleteProc);
+ initializationSucceeded = true;
+ }
+ return initializationSucceeded;
+}
+
+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:
+ case DLL_THREAD_DETACH:
+ return FALSE;
+ }
+ ASSERT_NOT_REACHED();
+ return FALSE;
+}
diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h
new file mode 100644
index 0000000..e31780a
--- /dev/null
+++ b/WebCore/platform/graphics/win/QTMovieWin.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2007 Apple Computer, 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 QTMovieWin_h
+#define QTMovieWin_h
+
+#include <Unicode.h>
+
+#ifdef QTMOVIEWIN_EXPORTS
+#define QTMOVIEWIN_API __declspec(dllexport)
+#else
+#define QTMOVIEWIN_API __declspec(dllimport)
+#endif
+
+class QTMovieWin;
+class QTMovieWinPrivate;
+
+class QTMovieWinClient {
+public:
+ virtual void movieEnded(QTMovieWin*) = 0;
+ virtual void movieLoadStateChanged(QTMovieWin*) = 0;
+ virtual void movieTimeChanged(QTMovieWin*) = 0;
+ virtual void movieNewImageAvailable(QTMovieWin*) = 0;
+};
+
+enum {
+ QTMovieLoadStateError = -1L,
+ QTMovieLoadStateLoaded = 2000L,
+ QTMovieLoadStatePlayable = 10000L,
+ QTMovieLoadStatePlaythroughOK = 20000L,
+ QTMovieLoadStateComplete = 100000L
+};
+
+class QTMOVIEWIN_API QTMovieWin {
+public:
+ static bool initializeQuickTime();
+
+ QTMovieWin(QTMovieWinClient*);
+ ~QTMovieWin();
+
+ void load(const UChar* url, int len);
+ long loadState() const;
+ float maxTimeLoaded() const;
+
+ void play();
+ void pause();
+
+ float rate() const;
+ void setRate(float);
+
+ float duration() const;
+ float currentTime() const;
+ void setCurrentTime(float) const;
+
+ void setVolume(float);
+
+ unsigned dataSize() const;
+
+ void getNaturalSize(int& width, int& height);
+ void setSize(int width, int height);
+
+ void setVisible(bool);
+ void paint(HDC, int x, int y);
+
+ void disableUnsupportedTracks(unsigned& enabledTrackCount);
+
+ static unsigned countSupportedTypes();
+ static void getSupportedType(unsigned index, const UChar*& str, unsigned& len);
+
+private:
+ QTMovieWinPrivate* m_private;
+ friend class QTMovieWinPrivate;
+};
+
+#endif
diff --git a/WebCore/platform/graphics/win/QTMovieWinTimer.cpp b/WebCore/platform/graphics/win/QTMovieWinTimer.cpp
new file mode 100644
index 0000000..d0aa3e6
--- /dev/null
+++ b/WebCore/platform/graphics/win/QTMovieWinTimer.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, 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"
+
+#include <windows.h>
+
+#include "QTMovieWinTimer.h"
+
+#include <wtf/Assertions.h>
+
+// This file is used by the QuickTime access DLL. It copies some WebCore code
+// which can't be used directly due to dependency issues.
+
+// FIXME: Find a way to do timers that can manage <10ms resolution properly too.
+
+static UINT_PTR timerID;
+static void (*sharedTimerFiredFunction)();
+
+static HINSTANCE instanceHandle = 0;
+
+static HWND timerWindowHandle = 0;
+static UINT timerFiredMessage = 0;
+static const LPCWSTR kTimerWindowClassName = L"TimerWindowClass";
+static bool processingCustomTimerMessage = false;
+
+static LRESULT CALLBACK TimerWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (message == timerFiredMessage) {
+ processingCustomTimerMessage = true;
+ sharedTimerFiredFunction();
+ processingCustomTimerMessage = false;
+ } else
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ return 0;
+}
+
+static void initializeOffScreenTimerWindow()
+{
+ if (timerWindowHandle)
+ return;
+
+ WNDCLASSEX wcex;
+ memset(&wcex, 0, sizeof(WNDCLASSEX));
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.lpfnWndProc = TimerWindowWndProc;
+ wcex.hInstance = instanceHandle;
+ wcex.lpszClassName = kTimerWindowClassName;
+ RegisterClassEx(&wcex);
+
+ timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, instanceHandle, 0);
+ timerFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.TimerFired");
+}
+
+void setSharedTimerFiredFunction(void (*f)())
+{
+ sharedTimerFiredFunction = f;
+}
+
+static void CALLBACK timerFired(HWND, UINT, UINT_PTR, DWORD)
+{
+ sharedTimerFiredFunction();
+}
+
+void setSharedTimerFireDelay(double interval)
+{
+ ASSERT(sharedTimerFiredFunction);
+
+ unsigned intervalInMS;
+ if (interval < 0)
+ intervalInMS = 0;
+ else {
+ interval *= 1000;
+ if (interval > USER_TIMER_MAXIMUM)
+ intervalInMS = USER_TIMER_MAXIMUM;
+ else
+ intervalInMS = (unsigned)interval;
+ }
+
+ if (timerID) {
+ KillTimer(0, timerID);
+ timerID = 0;
+ }
+
+ // We don't allow nested PostMessages, since the custom messages will effectively starve
+ // painting and user input. (Win32 has a tri-level queue with application messages >
+ // user input > WM_PAINT/WM_TIMER.)
+ // In addition, if the queue contains input events that have been there since the last call to
+ // GetQueueStatus, PeekMessage or GetMessage we favor timers.
+ if (intervalInMS < USER_TIMER_MINIMUM && processingCustomTimerMessage &&
+ !LOWORD(::GetQueueStatus(QS_ALLINPUT))) {
+ // Windows SetTimer does not allow timeouts smaller than 10ms (USER_TIMER_MINIMUM)
+ initializeOffScreenTimerWindow();
+ PostMessage(timerWindowHandle, timerFiredMessage, 0, 0);
+ } else
+ timerID = SetTimer(0, 0, intervalInMS, timerFired);
+}
+
+void stopSharedTimer()
+{
+ if (timerID) {
+ KillTimer(0, timerID);
+ timerID = 0;
+ }
+}
+
+void setSharedTimerInstanceHandle(HINSTANCE handle)
+{
+ instanceHandle = handle;
+}
+
+double systemTime()
+{
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ ULARGE_INTEGER t;
+ memcpy(&t, &ft, sizeof(t));
+ return t.QuadPart * 0.0000001 - 11644473600.0;
+}
diff --git a/WebCore/platform/graphics/win/QTMovieWinTimer.h b/WebCore/platform/graphics/win/QTMovieWinTimer.h
new file mode 100644
index 0000000..3e3c2bc
--- /dev/null
+++ b/WebCore/platform/graphics/win/QTMovieWinTimer.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, 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 QTMovieViewTimer_h
+#define QTMovieViewTimer_h
+
+// This header should not be included from WebCore.
+// It is used by the QuickTime access DLL. It copies some WebCore code
+// which can't be used directly due to dependency issues.
+
+void setSharedTimerFiredFunction(void (*)());
+void setSharedTimerFireDelay(double delay);
+void stopSharedTimer();
+void setSharedTimerInstanceHandle(HINSTANCE handle);
+double systemTime();
+
+#endif
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
new file mode 100644
index 0000000..4040ed8
--- /dev/null
+++ b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 <winsock2.h>
+#include "Font.h"
+#include "FontCache.h"
+#include "FloatRect.h"
+#include "FontDescription.h"
+#include <wtf/MathExtras.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <mlang.h>
+#include <tchar.h>
+
+namespace WebCore {
+
+using std::max;
+
+static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return unitsPerEm ? x / static_cast<float>(unitsPerEm) : x; }
+
+void SimpleFontData::platformInit()
+{
+ m_syntheticBoldOffset = m_font.syntheticBold() ? 1.0f : 0.f;
+ m_scriptCache = 0;
+ m_scriptFontProperties = 0;
+ m_isSystemFont = false;
+
+ if (m_font.useGDI())
+ return initGDIFont();
+
+ CGFontRef font = m_font.cgFont();
+ int iAscent = CGFontGetAscent(font);
+ int iDescent = CGFontGetDescent(font);
+ int iLineGap = CGFontGetLeading(font);
+ m_unitsPerEm = CGFontGetUnitsPerEm(font);
+ float pointSize = m_font.size();
+ float fAscent = scaleEmToUnits(iAscent, m_unitsPerEm) * pointSize;
+ float fDescent = -scaleEmToUnits(iDescent, m_unitsPerEm) * pointSize;
+ float fLineGap = scaleEmToUnits(iLineGap, m_unitsPerEm) * pointSize;
+
+ if (!isCustomFont()) {
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_font.hfont());
+ int faceLength = GetTextFace(dc, 0, 0);
+ Vector<TCHAR> faceName(faceLength);
+ GetTextFace(dc, faceLength, faceName.data());
+ m_isSystemFont = !_tcscmp(faceName.data(), _T("Lucida Grande"));
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+
+ if (shouldApplyMacAscentHack()) {
+ // This code comes from FontDataMac.mm. We only ever do this when running regression tests so that our metrics will match Mac.
+
+ // We need to adjust Times, Helvetica, and Courier to closely match the
+ // vertical metrics of their Microsoft counterparts that are the de facto
+ // web standard. The AppKit adjustment of 20% is too big and is
+ // incorrectly added to line spacing, so we use a 15% adjustment instead
+ // and add it to the ascent.
+ if (!_tcscmp(faceName.data(), _T("Times")) || !_tcscmp(faceName.data(), _T("Helvetica")) || !_tcscmp(faceName.data(), _T("Courier")))
+ fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
+ }
+ }
+
+ m_ascent = lroundf(fAscent);
+ m_descent = lroundf(fDescent);
+ m_lineGap = lroundf(fLineGap);
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font.
+ // Unfortunately, NSFont will round this for us so we don't quite get the right value.
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ Glyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
+ if (xGlyph) {
+ CGRect xBox;
+ CGFontGetGlyphBBoxes(font, &xGlyph, 1, &xBox);
+ // Use the maximum of either width or height because "x" is nearly square
+ // 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 = scaleEmToUnits(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox)), m_unitsPerEm) * pointSize;
+ } else {
+ int iXHeight = CGFontGetXHeight(font);
+ m_xHeight = scaleEmToUnits(iXHeight, m_unitsPerEm) * pointSize;
+ }
+}
+
+void SimpleFontData::platformDestroy()
+{
+ if (!isCustomFont()) {
+ DeleteObject(m_font.hfont());
+ CGFontRelease(m_font.cgFont());
+ }
+
+ platformCommonDestroy();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ if (m_font.useGDI())
+ return widthForGDIGlyph(glyph);
+
+ CGFontRef font = m_font.cgFont();
+ float pointSize = m_font.size();
+ CGSize advance;
+ CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
+
+ // FIXME: Need to add real support for printer fonts.
+ bool isPrinterFont = false;
+ wkGetGlyphAdvances(font, m, m_isSystemFont, isPrinterFont, glyph, advance);
+
+ return advance.width + m_syntheticBoldOffset;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
new file mode 100644
index 0000000..fd017b4
--- /dev/null
+++ b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 <windows.h>
+
+#include "Font.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "MathExtras.h"
+#include "NotImplemented.h"
+#include <cairo.h>
+#include <cairo-win32.h>
+#include <mlang.h>
+#include <tchar.h>
+
+namespace WebCore {
+
+void SimpleFontData::platformInit()
+{
+ m_scriptCache = 0;
+ m_scriptFontProperties = 0;
+ m_isSystemFont = false;
+
+ if (m_font.useGDI())
+ return initGDIFont();
+
+ HDC hdc = GetDC(0);
+ SaveDC(hdc);
+
+ cairo_scaled_font_t* scaledFont = m_font.scaledFont();
+ const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_font.size();
+
+ cairo_win32_scaled_font_select_font(scaledFont, hdc);
+
+ TEXTMETRIC textMetrics;
+ GetTextMetrics(hdc, &textMetrics);
+ m_ascent = lroundf(textMetrics.tmAscent * metricsMultiplier);
+ m_descent = lroundf(textMetrics.tmDescent * metricsMultiplier);
+ m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
+ m_lineGap = lroundf(textMetrics.tmExternalLeading * metricsMultiplier);
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ OUTLINETEXTMETRIC metrics;
+ if (GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics) > 0) {
+ // This is a TrueType font. We might be able to get an accurate xHeight
+ GLYPHMETRICS gm;
+ MAT2 mat = { 1, 0, 0, 1 };
+ DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
+ if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
+ m_xHeight = gm.gmptGlyphOrigin.y * metricsMultiplier;
+ }
+
+ cairo_win32_scaled_font_done_font(scaledFont);
+
+ m_isSystemFont = false;
+ m_scriptCache = 0;
+ m_scriptFontProperties = 0;
+
+ RestoreDC(hdc, -1);
+ ReleaseDC(0, hdc);
+}
+
+void SimpleFontData::platformDestroy()
+{
+ cairo_font_face_destroy(m_font.fontFace());
+ cairo_scaled_font_destroy(m_font.scaledFont());
+
+ DeleteObject(m_font.hfont());
+
+ platformCommonDestroy();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ if (m_font.useGDI())
+ return widthForGDIGlyph(glyph);
+
+ HDC hdc = GetDC(0);
+ SaveDC(hdc);
+
+ cairo_scaled_font_t* scaledFont = m_font.scaledFont();
+ cairo_win32_scaled_font_select_font(scaledFont, hdc);
+
+ int width;
+ GetCharWidthI(hdc, glyph, 1, 0, &width);
+
+ cairo_win32_scaled_font_done_font(scaledFont);
+
+ RestoreDC(hdc, -1);
+ ReleaseDC(0, hdc);
+
+ const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_font.size();
+ return width * metricsMultiplier;
+}
+
+void SimpleFontData::setFont(cairo_t* cr) const
+{
+ ASSERT(cr);
+ m_font.setFont(cr);
+}
+
+}
diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
new file mode 100644
index 0000000..6d1c417
--- /dev/null
+++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 <winsock2.h>
+#include "Font.h"
+#include "FontCache.h"
+#include "FloatRect.h"
+#include "FontDescription.h"
+#include <wtf/MathExtras.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <mlang.h>
+#include <tchar.h>
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+
+namespace WebCore {
+
+using std::max;
+
+const float cSmallCapsFontSizeMultiplier = 0.7f;
+
+static bool g_shouldApplyMacAscentHack;
+
+void SimpleFontData::setShouldApplyMacAscentHack(bool b)
+{
+ g_shouldApplyMacAscentHack = b;
+}
+
+bool SimpleFontData::shouldApplyMacAscentHack()
+{
+ return g_shouldApplyMacAscentHack;
+}
+
+void SimpleFontData::initGDIFont()
+{
+ HDC hdc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont());
+ OUTLINETEXTMETRIC metrics;
+ GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
+ TEXTMETRIC& textMetrics = metrics.otmTextMetrics;
+ m_ascent = textMetrics.tmAscent;
+ m_descent = textMetrics.tmDescent;
+ m_lineGap = textMetrics.tmExternalLeading;
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ m_xHeight = m_ascent * 0.56f; // Best guess for xHeight if no x glyph is present.
+
+ GLYPHMETRICS gm;
+ MAT2 mat = { 1, 0, 0, 1 };
+ DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
+ if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
+ m_xHeight = gm.gmptGlyphOrigin.y;
+
+ m_unitsPerEm = metrics.otmEMSquare;
+
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+
+ return;
+}
+
+void SimpleFontData::platformCommonDestroy()
+{
+ // We don't hash this on Win32, so it's effectively owned by us.
+ delete m_smallCapsFontData;
+
+ ScriptFreeCache(&m_scriptCache);
+ delete m_scriptFontProperties;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData) {
+ float smallCapsHeight = cSmallCapsFontSizeMultiplier * m_font.size();
+ if (isCustomFont()) {
+ FontPlatformData smallCapsFontData(m_font);
+ smallCapsFontData.setSize(smallCapsHeight);
+ m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
+ } else {
+ LOGFONT winfont;
+ GetObject(m_font.hfont(), sizeof(LOGFONT), &winfont);
+ winfont.lfHeight = -lroundf(smallCapsHeight * (m_font.useGDI() ? 1 : 32));
+ HFONT hfont = CreateFontIndirect(&winfont);
+ m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, fontDescription.bold(), fontDescription.italic(), m_font.useGDI()));
+ }
+ }
+ return m_smallCapsFontData;
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ // FIXME: Support custom fonts.
+ if (isCustomFont())
+ return false;
+
+ // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC
+ // merely by testing code page intersection. This seems suspect though. Can't a font only partially
+ // cover a given code page?
+ IMLangFontLink2* langFontLink = FontCache::getFontLinkInterface();
+ if (!langFontLink)
+ return false;
+
+ HDC dc = GetDC(0);
+
+ DWORD acpCodePages;
+ langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages);
+
+ DWORD fontCodePages;
+ langFontLink->GetFontCodePages(dc, m_font.hfont(), &fontCodePages);
+
+ DWORD actualCodePages;
+ long numCharactersProcessed;
+ long offset = 0;
+ while (offset < length) {
+ langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &numCharactersProcessed);
+ if ((actualCodePages & fontCodePages) == 0)
+ return false;
+ offset += numCharactersProcessed;
+ }
+
+ ReleaseDC(0, dc);
+
+ return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+ if (isCustomFont()) {
+ m_treatAsFixedPitch = false;
+ return;
+ }
+
+ // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
+ HDC dc = GetDC(0);
+ SaveDC(dc);
+ SelectObject(dc, m_font.hfont());
+
+ // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
+ // is *not* fixed pitch. Unbelievable but true.
+ TEXTMETRIC tm;
+ GetTextMetrics(dc, &tm);
+ m_treatAsFixedPitch = ((tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
+
+ RestoreDC(dc, -1);
+ ReleaseDC(0, dc);
+}
+
+float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
+{
+ HDC hdc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(hdc, m_font.hfont());
+ int width;
+ GetCharWidthI(hdc, glyph, 1, 0, &width);
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+ return width;
+}
+
+SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const
+{
+ if (!m_scriptFontProperties) {
+ m_scriptFontProperties = new SCRIPT_FONTPROPERTIES;
+ memset(m_scriptFontProperties, 0, sizeof(SCRIPT_FONTPROPERTIES));
+ m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
+ HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties);
+ if (result == E_PENDING) {
+ HDC dc = GetDC(0);
+ SaveDC(dc);
+ SelectObject(dc, m_font.hfont());
+ ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties);
+ RestoreDC(dc, -1);
+ ReleaseDC(0, dc);
+ }
+ }
+ return m_scriptFontProperties;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp
new file mode 100644
index 0000000..876ff43
--- /dev/null
+++ b/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2007 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.
+ * 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 "UniscribeController.h"
+#include "Font.h"
+#include "SimpleFontData.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+// FIXME: Rearchitect this to be more like WidthIterator in Font.cpp. Have an advance() method
+// that does stuff in that method instead of doing everything in the constructor. Have advance()
+// take the GlyphBuffer as an arg so that we don't have to populate the glyph buffer when
+// measuring.
+UniscribeController::UniscribeController(const Font* font, const TextRun& run)
+: m_font(*font)
+, m_run(run)
+, m_end(run.length())
+, m_currentCharacter(0)
+, m_runWidthSoFar(0)
+, m_computingOffsetPosition(false)
+, m_includePartialGlyphs(false)
+, m_offsetX(0)
+, m_offsetPosition(0)
+{
+ m_padding = m_run.padding();
+ if (!m_padding)
+ m_padPerSpace = 0;
+ else {
+ float numSpaces = 0;
+ for (int s = 0; s < m_run.length(); s++)
+ if (Font::treatAsSpace(m_run[s]))
+ numSpaces++;
+
+ if (numSpaces == 0)
+ m_padPerSpace = 0;
+ else
+ m_padPerSpace = ceilf(m_run.padding() / numSpaces);
+ }
+
+ // Null out our uniscribe structs
+ resetControlAndState();
+}
+
+int UniscribeController::offsetForPosition(int x, bool includePartialGlyphs)
+{
+ m_computingOffsetPosition = true;
+ m_includePartialGlyphs = includePartialGlyphs;
+ m_offsetX = x;
+ m_offsetPosition = 0;
+ advance(m_run.length());
+ if (m_computingOffsetPosition) {
+ // The point is to the left or to the right of the entire run.
+ if (m_offsetX >= m_runWidthSoFar && m_run.ltr() || m_offsetX < 0 && m_run.rtl())
+ m_offsetPosition = m_end;
+ }
+ m_computingOffsetPosition = false;
+ return m_offsetPosition;
+}
+
+void UniscribeController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
+{
+ // FIXME: We really want to be using a newer version of Uniscribe that supports the new OpenType
+ // functions. Those functions would allow us to turn off kerning and ligatures. Without being able
+ // to do that, we will have buggy line breaking and metrics when simple and complex text are close
+ // together (the complex code path will narrow the text because of kerning and ligatures and then
+ // when bidi processing splits into multiple runs, the simple portions will get wider and cause us to
+ // spill off the edge of a line).
+ if (static_cast<int>(offset) > m_end)
+ offset = m_end;
+
+ // Itemize the string.
+ const UChar* cp = m_run.data(m_currentCharacter);
+ int length = offset - m_currentCharacter;
+ if (length <= 0)
+ return;
+
+ unsigned baseCharacter = m_currentCharacter;
+
+ // We break up itemization of the string by fontData and (if needed) the use of small caps.
+
+ // FIXME: It's inconsistent that we use logical order when itemizing, since this
+ // does not match normal RTL.
+
+ // FIXME: This function should decode surrogate pairs. Currently it makes little difference that
+ // it does not because the font cache on Windows does not support non-BMP characters.
+ Vector<UChar, 256> smallCapsBuffer;
+ if (m_font.isSmallCaps())
+ smallCapsBuffer.resize(length);
+
+ unsigned indexOfFontTransition = m_run.rtl() ? length - 1 : 0;
+ const UChar* curr = m_run.rtl() ? cp + length - 1 : cp;
+ const UChar* end = m_run.rtl() ? cp - 1 : cp + length;
+
+ const SimpleFontData* fontData;
+ const SimpleFontData* nextFontData = m_font.glyphDataForCharacter(*curr, false).fontData;
+
+ UChar newC = 0;
+
+ bool isSmallCaps;
+ bool nextIsSmallCaps = m_font.isSmallCaps() && !(U_GET_GC_MASK(*curr) & U_GC_M_MASK) && (newC = u_toupper(*curr)) != *curr;
+
+ if (nextIsSmallCaps)
+ smallCapsBuffer[curr - cp] = newC;
+
+ while (true) {
+ curr = m_run.rtl() ? curr - 1 : curr + 1;
+ if (curr == end)
+ break;
+
+ fontData = nextFontData;
+ isSmallCaps = nextIsSmallCaps;
+ int index = curr - cp;
+ UChar c = *curr;
+
+ bool forceSmallCaps = isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK);
+ nextFontData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps).fontData;
+ if (m_font.isSmallCaps()) {
+ nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;
+ if (nextIsSmallCaps)
+ smallCapsBuffer[index] = forceSmallCaps ? c : newC;
+ }
+
+ if (nextFontData != fontData || nextIsSmallCaps != isSmallCaps) {
+ int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;
+ int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
+ m_currentCharacter = baseCharacter + itemStart;
+ itemizeShapeAndPlace((isSmallCaps ? smallCapsBuffer.data() : cp) + itemStart, itemLength, fontData, glyphBuffer);
+ indexOfFontTransition = index;
+ }
+ }
+
+ int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : length - indexOfFontTransition;
+ if (itemLength) {
+ int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
+ m_currentCharacter = baseCharacter + itemStart;
+ itemizeShapeAndPlace((nextIsSmallCaps ? smallCapsBuffer.data() : cp) + itemStart, itemLength, nextFontData, glyphBuffer);
+ }
+
+ m_currentCharacter = baseCharacter + length;
+}
+
+void UniscribeController::itemizeShapeAndPlace(const UChar* cp, unsigned length, const SimpleFontData* fontData, GlyphBuffer* glyphBuffer)
+{
+ // ScriptItemize (in Windows XP versions prior to SP2) can overflow by 1. This is why there is an extra empty item
+ // hanging out at the end of the array
+ m_items.resize(6);
+ int numItems = 0;
+ while (ScriptItemize(cp, length, m_items.size() - 1, &m_control, &m_state, m_items.data(), &numItems) == E_OUTOFMEMORY) {
+ m_items.resize(m_items.size() * 2);
+ resetControlAndState();
+ }
+ m_items.resize(numItems + 1);
+
+ if (m_run.rtl()) {
+ for (int i = m_items.size() - 2; i >= 0; i--) {
+ if (!shapeAndPlaceItem(cp, i, fontData, glyphBuffer))
+ return;
+ }
+ } else {
+ for (unsigned i = 0; i < m_items.size() - 1; i++) {
+ if (!shapeAndPlaceItem(cp, i, fontData, glyphBuffer))
+ return;
+ }
+ }
+}
+
+void UniscribeController::resetControlAndState()
+{
+ memset(&m_control, 0, sizeof(SCRIPT_CONTROL));
+ memset(&m_state, 0, sizeof(SCRIPT_STATE));
+
+ // Set up the correct direction for the run.
+ m_state.uBidiLevel = m_run.rtl();
+
+ // Lock the correct directional override.
+ m_state.fOverrideDirection = m_run.directionalOverride();
+}
+
+bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const SimpleFontData* fontData, GlyphBuffer* glyphBuffer)
+{
+ // Determine the string for this item.
+ const UChar* str = cp + m_items[i].iCharPos;
+ int len = m_items[i+1].iCharPos - m_items[i].iCharPos;
+ SCRIPT_ITEM item = m_items[i];
+
+ // Set up buffers to hold the results of shaping the item.
+ Vector<WORD> glyphs;
+ Vector<WORD> clusters;
+ Vector<SCRIPT_VISATTR> visualAttributes;
+ clusters.resize(len);
+
+ // Shape the item.
+ // The recommended size for the glyph buffer is 1.5 * the character length + 16 in the uniscribe docs.
+ // Apparently this is a good size to avoid having to make repeated calls to ScriptShape.
+ glyphs.resize(1.5 * len + 16);
+ visualAttributes.resize(glyphs.size());
+
+ if (!shape(str, len, item, fontData, glyphs, clusters, visualAttributes))
+ return true;
+
+ // We now have a collection of glyphs.
+ Vector<GOFFSET> offsets;
+ Vector<int> advances;
+ offsets.resize(glyphs.size());
+ advances.resize(glyphs.size());
+ int glyphCount = 0;
+ HRESULT placeResult = ScriptPlace(0, fontData->scriptCache(), glyphs.data(), glyphs.size(), visualAttributes.data(),
+ &item.a, advances.data(), offsets.data(), 0);
+ if (placeResult == E_PENDING) {
+ // The script cache isn't primed with enough info yet. We need to select our HFONT into
+ // a DC and pass the DC in to ScriptPlace.
+ HDC hdc = GetDC(0);
+ HFONT hfont = fontData->platformData().hfont();
+ HFONT oldFont = (HFONT)SelectObject(hdc, hfont);
+ placeResult = ScriptPlace(hdc, fontData->scriptCache(), glyphs.data(), glyphs.size(), visualAttributes.data(),
+ &item.a, advances.data(), offsets.data(), 0);
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+ }
+
+ if (FAILED(placeResult) || glyphs.isEmpty())
+ return true;
+
+ // Convert all chars that should be treated as spaces to use the space glyph.
+ // We also create a map that allows us to quickly go from space glyphs or rounding
+ // hack glyphs back to their corresponding characters.
+ Vector<int> spaceCharacters(glyphs.size());
+ spaceCharacters.fill(-1);
+ Vector<int> roundingHackCharacters(glyphs.size());
+ roundingHackCharacters.fill(-1);
+ Vector<int> roundingHackWordBoundaries(glyphs.size());
+ roundingHackWordBoundaries.fill(-1);
+
+ const float cLogicalScale = fontData->m_font.useGDI() ? 1.0f : 32.0f;
+ unsigned logicalSpaceWidth = fontData->m_spaceWidth * cLogicalScale;
+ float roundedSpaceWidth = roundf(fontData->m_spaceWidth);
+
+ for (int k = 0; k < len; k++) {
+ UChar ch = *(str + k);
+ if (Font::treatAsSpace(ch)) {
+ // Substitute in the space glyph at the appropriate place in the glyphs
+ // array.
+ glyphs[clusters[k]] = fontData->m_spaceGlyph;
+ advances[clusters[k]] = logicalSpaceWidth;
+ spaceCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos;
+ }
+
+ if (Font::isRoundingHackCharacter(ch))
+ roundingHackCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos;
+
+ int boundary = k + m_currentCharacter + item.iCharPos;
+ if (boundary < m_run.length() &&
+ Font::isRoundingHackCharacter(*(str + k + 1)))
+ roundingHackWordBoundaries[clusters[k]] = boundary;
+ }
+
+ // Populate our glyph buffer with this information.
+ bool hasExtraSpacing = m_font.letterSpacing() || m_font.wordSpacing() || m_padding;
+
+ float leftEdge = m_runWidthSoFar;
+
+ for (unsigned k = 0; k < glyphs.size(); k++) {
+ Glyph glyph = glyphs[k];
+ float advance = advances[k] / cLogicalScale;
+ float offsetX = offsets[k].du / cLogicalScale;
+ float offsetY = offsets[k].dv / cLogicalScale;
+
+ // Match AppKit's rules for the integer vs. non-integer rendering modes.
+ float roundedAdvance = roundf(advance);
+ if (!m_font.isPrinterFont() && !fontData->isSystemFont()) {
+ advance = roundedAdvance;
+ offsetX = roundf(offsetX);
+ offsetY = roundf(offsetY);
+ }
+
+ // We special case spaces in two ways when applying word rounding.
+ // First, we round spaces to an adjusted width in all fonts.
+ // Second, in fixed-pitch fonts we ensure that all glyphs that
+ // match the width of the space glyph have the same width as the space glyph.
+ if (roundedAdvance == roundedSpaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) &&
+ m_run.applyWordRounding())
+ advance = fontData->m_adjustedSpaceWidth;
+
+ if (hasExtraSpacing) {
+ // If we're a glyph with an advance, go ahead and add in letter-spacing.
+ // That way we weed out zero width lurkers. This behavior matches the fast text code path.
+ if (advance && m_font.letterSpacing())
+ advance += m_font.letterSpacing();
+
+ // Handle justification and word-spacing.
+ if (glyph == fontData->m_spaceGlyph) {
+ // Account for padding. WebCore uses space padding to justify text.
+ // We distribute the specified padding over the available spaces in the run.
+ if (m_padding) {
+ // Use leftover padding if not evenly divisible by number of spaces.
+ if (m_padding < m_padPerSpace) {
+ advance += m_padding;
+ m_padding = 0;
+ } else {
+ advance += m_padPerSpace;
+ m_padding -= m_padPerSpace;
+ }
+ }
+
+ // Account for word-spacing.
+ int characterIndex = spaceCharacters[k];
+ if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
+ advance += m_font.wordSpacing();
+ }
+ }
+
+ // Deal with the float/integer impedance mismatch between CG and WebCore. "Words" (characters
+ // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
+ // We adjust the width of the last character of a "word" to ensure an integer width.
+ // Force characters that are used to determine word boundaries for the rounding hack
+ // to be integer width, so the following words will start on an integer boundary.
+ int roundingHackIndex = roundingHackCharacters[k];
+ if (m_run.applyWordRounding() && roundingHackIndex != -1)
+ advance = ceilf(advance);
+
+ // Check to see if the next character is a "rounding hack character", if so, adjust the
+ // width so that the total run width will be on an integer boundary.
+ int position = m_currentCharacter + len;
+ bool lastGlyph = (k == glyphs.size() - 1) && (m_run.rtl() ? i == 0 : i == m_items.size() - 2) && (position >= m_end);
+ if ((m_run.applyWordRounding() && roundingHackWordBoundaries[k] != -1) ||
+ (m_run.applyRunRounding() && lastGlyph)) {
+ float totalWidth = m_runWidthSoFar + advance;
+ advance += ceilf(totalWidth) - totalWidth;
+ }
+
+ m_runWidthSoFar += advance;
+
+ // FIXME: We need to take the GOFFSETS for combining glyphs and store them in the glyph buffer
+ // as well, so that when the time comes to draw those glyphs, we can apply the appropriate
+ // translation.
+ if (glyphBuffer) {
+ FloatSize size(offsetX, offsetY);
+ glyphBuffer->add(glyph, fontData, advance, &size);
+ }
+
+ // Mutate the glyph array to contain our altered advances.
+ if (m_computingOffsetPosition)
+ advances[k] = advance;
+ }
+
+ while (m_computingOffsetPosition && m_offsetX >= leftEdge && m_offsetX < m_runWidthSoFar) {
+ // The position is somewhere inside this run.
+ int trailing = 0;
+ ScriptXtoCP(m_offsetX - leftEdge, clusters.size(), glyphs.size(), clusters.data(), visualAttributes.data(),
+ advances.data(), &item.a, &m_offsetPosition, &trailing);
+ if (trailing && m_includePartialGlyphs && m_offsetPosition < len - 1) {
+ m_offsetPosition += m_currentCharacter + m_items[i].iCharPos;
+ m_offsetX += m_run.rtl() ? -trailing : trailing;
+ } else {
+ m_computingOffsetPosition = false;
+ m_offsetPosition += m_currentCharacter + m_items[i].iCharPos;
+ if (trailing && m_includePartialGlyphs)
+ m_offsetPosition++;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool UniscribeController::shape(const UChar* str, int len, SCRIPT_ITEM item, const SimpleFontData* fontData,
+ Vector<WORD>& glyphs, Vector<WORD>& clusters,
+ Vector<SCRIPT_VISATTR>& visualAttributes)
+{
+ HDC hdc = 0;
+ HFONT oldFont = 0;
+ HRESULT shapeResult = E_PENDING;
+ int glyphCount = 0;
+ do {
+ shapeResult = ScriptShape(hdc, fontData->scriptCache(), str, len, glyphs.size(), &item.a,
+ glyphs.data(), clusters.data(), visualAttributes.data(), &glyphCount);
+ if (shapeResult == E_PENDING) {
+ // The script cache isn't primed with enough info yet. We need to select our HFONT into
+ // a DC and pass the DC in to ScriptShape.
+ ASSERT(!hdc);
+ hdc = GetDC(0);
+ HFONT hfont = fontData->platformData().hfont();
+ oldFont = (HFONT)SelectObject(hdc, hfont);
+ } else if (shapeResult == E_OUTOFMEMORY) {
+ // Need to resize our buffers.
+ glyphs.resize(glyphs.size() * 2);
+ visualAttributes.resize(glyphs.size());
+ }
+ } while (shapeResult == E_PENDING || shapeResult == E_OUTOFMEMORY);
+
+ if (hdc) {
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+ }
+
+ if (FAILED(shapeResult))
+ return false;
+
+ // FIXME: We need to do better than this. Falling back on the entire item is not good enough.
+ // We may still have missing glyphs even if we succeeded. We need to treat missing glyphs as
+ // a failure so that we will fall back to another font.
+ bool containsMissingGlyphs = false;
+ SCRIPT_FONTPROPERTIES* fontProperties = fontData->scriptFontProperties();
+ for (int i = 0; i < glyphCount; i++) {
+ WORD glyph = glyphs[i];
+ if (glyph == fontProperties->wgDefault) {
+ containsMissingGlyphs = true;
+ break;
+ }
+ }
+
+ if (containsMissingGlyphs)
+ return false;
+
+ glyphs.resize(glyphCount);
+ visualAttributes.resize(glyphCount);
+
+ return true;
+}
+
+}
diff --git a/WebCore/platform/graphics/win/UniscribeController.h b/WebCore/platform/graphics/win/UniscribeController.h
new file mode 100644
index 0000000..6ea45e1
--- /dev/null
+++ b/WebCore/platform/graphics/win/UniscribeController.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 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.
+ * 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.
+ */
+
+#ifndef UniscribeController_h
+#define UniscribeController_h
+
+#include <usp10.h>
+#include "Font.h"
+#include "GlyphBuffer.h"
+#include "Vector.h"
+
+namespace WebCore {
+
+class UniscribeController {
+public:
+ UniscribeController(const Font*, const TextRun&);
+
+ // Advance and measure/place up to the specified character.
+ void advance(unsigned to, GlyphBuffer* = 0);
+
+ // Compute the character offset for a given x coordinate.
+ int offsetForPosition(int x, bool includePartialGlyphs);
+
+ // Returns the width of everything we've consumed so far.
+ float runWidthSoFar() const { return m_runWidthSoFar; }
+
+private:
+ void resetControlAndState();
+
+ void itemizeShapeAndPlace(const UChar*, unsigned length, const SimpleFontData*, GlyphBuffer*);
+ bool shapeAndPlaceItem(const UChar*, unsigned index, const SimpleFontData*, GlyphBuffer*);
+ bool shape(const UChar* str, int len, SCRIPT_ITEM item, const SimpleFontData* fontData,
+ Vector<WORD>& glyphs, Vector<WORD>& clusters,
+ Vector<SCRIPT_VISATTR>& visualAttributes);
+
+ const Font& m_font;
+ const TextRun& m_run;
+
+ SCRIPT_CONTROL m_control;
+ SCRIPT_STATE m_state;
+ Vector<SCRIPT_ITEM> m_items;
+
+ unsigned m_currentCharacter;
+ int m_end;
+
+ float m_runWidthSoFar;
+ float m_padding;
+ float m_padPerSpace;
+
+ bool m_computingOffsetPosition;
+ bool m_includePartialGlyphs;
+ float m_offsetX;
+ int m_offsetPosition;
+};
+
+}
+#endif
diff --git a/WebCore/platform/graphics/wx/AffineTransformWx.cpp b/WebCore/platform/graphics/wx/AffineTransformWx.cpp
new file mode 100644
index 0000000..b9c504d
--- /dev/null
+++ b/WebCore/platform/graphics/wx/AffineTransformWx.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2007 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 "AffineTransform.h"
+
+#include "FloatRect.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+
+#include <stdio.h>
+#include <wx/defs.h>
+#include <wx/graphics.h>
+
+namespace WebCore {
+
+#if USE(WXGC)
+AffineTransform::AffineTransform(const wxGraphicsMatrix &matrix)
+{
+ m_transform = matrix;
+}
+#endif
+
+AffineTransform::AffineTransform(double a, double b, double c, double d, double e, double f)
+{
+#if USE(WXGC)
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ m_transform = renderer->CreateMatrix();
+ m_transform.Set(a, b, c, d, e, f);
+#endif
+}
+
+AffineTransform::AffineTransform()
+{
+ // NB: If we ever support using Cairo backend on Win/Mac, this will need to be
+ // changed somehow (though I'm not sure how as we don't have a reference to the
+ // graphics context here.
+#if USE(WXGC)
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ m_transform = renderer->CreateMatrix();
+#endif
+}
+
+AffineTransform AffineTransform::inverse() const
+{
+ notImplemented();
+ return *this;
+}
+
+void AffineTransform::map(double x, double y, double *x2, double *y2) const
+{
+ notImplemented();
+}
+
+IntRect AffineTransform::mapRect(const IntRect &rect) const
+{
+ notImplemented();
+ return IntRect();
+}
+
+FloatRect AffineTransform::mapRect(const FloatRect &rect) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+
+AffineTransform& AffineTransform::scale(double sx, double sy)
+{
+#if USE(WXGC)
+ m_transform.Scale((wxDouble)sx, (wxDouble)sy);
+#endif
+ return *this;
+}
+
+void AffineTransform::reset()
+{
+ notImplemented();
+}
+
+AffineTransform& AffineTransform::rotate(double d)
+{
+#if USE(WXGC)
+ m_transform.Rotate((wxDouble)d);
+#endif
+ return *this;
+}
+
+AffineTransform& AffineTransform::translate(double tx, double ty)
+{
+#if USE(WXGC)
+ m_transform.Translate((wxDouble)tx, (wxDouble)ty);
+#endif
+ return *this;
+}
+
+AffineTransform& AffineTransform::shear(double sx, double sy)
+{
+ notImplemented();
+ return *this;
+}
+
+AffineTransform& AffineTransform::operator*=(const AffineTransform& other)
+{
+ notImplemented();
+ return *this;
+}
+
+bool AffineTransform::operator== (const AffineTransform &other) const
+{
+#if USE(WXGC)
+ return m_transform.IsEqual((wxGraphicsMatrix)other);
+#endif
+}
+
+AffineTransform AffineTransform::operator* (const AffineTransform &other)
+{
+ notImplemented();
+ return *this; //m_transform * other.m_transform;
+}
+
+double AffineTransform::det() const
+{
+ notImplemented();
+ return 0;
+}
+
+#if USE(WXGC)
+AffineTransform::operator wxGraphicsMatrix() const
+{
+ return m_transform;
+}
+#endif
+
+}
diff --git a/WebCore/platform/graphics/wx/ColorWx.cpp b/WebCore/platform/graphics/wx/ColorWx.cpp
new file mode 100644
index 0000000..0381c59
--- /dev/null
+++ b/WebCore/platform/graphics/wx/ColorWx.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006, 2007 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 "Color.h"
+
+#include <wx/defs.h>
+#include <wx/colour.h>
+
+namespace WebCore {
+
+Color::Color(const wxColour& color)
+{
+ m_color = makeRGBA((int)color.Red(), (int)color.Green(), (int)color.Blue(), (int)color.Alpha());
+}
+
+Color::operator wxColour() const
+{
+ return wxColour(red(), green(), blue(), alpha());
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/FloatRectWx.cpp b/WebCore/platform/graphics/wx/FloatRectWx.cpp
new file mode 100644
index 0000000..bb460e5
--- /dev/null
+++ b/WebCore/platform/graphics/wx/FloatRectWx.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 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 "FloatRect.h"
+
+#include <wx/defs.h>
+#include <wx/graphics.h>
+
+namespace WebCore {
+
+#if USE(WXGC)
+FloatRect::FloatRect(const wxRect2DDouble& r)
+ : m_location(FloatPoint(r.m_x, r.m_y))
+ , m_size(FloatSize(r.m_width, r.m_height))
+{
+}
+
+FloatRect::operator wxRect2DDouble() const
+{
+ return wxRect2DDouble(x(), y(), width(), height());
+}
+#endif
+
+}
diff --git a/WebCore/platform/graphics/wx/FontCacheWx.cpp b/WebCore/platform/graphics/wx/FontCacheWx.cpp
new file mode 100755
index 0000000..eb41c89
--- /dev/null
+++ b/WebCore/platform/graphics/wx/FontCacheWx.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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 "FontPlatformData.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+void FontCache::platformInit()
+{
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ SimpleFontData* fontData = 0;
+ fontData = new SimpleFontData(FontPlatformData(font.fontDescription(), font.family().family()));
+ return fontData;
+}
+
+FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ return new FontPlatformData(font.fontDescription(), font.family().family());
+}
+
+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 timesStr("systemfont");
+ return getCachedFontPlatformData(fontDescription, timesStr);
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ return new FontPlatformData(fontDescription,family);
+}
+
+bool FontCache::fontExists(const FontDescription& fontDescription, const AtomicString& family)
+{
+ notImplemented();
+ return true;
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h
new file mode 100644
index 0000000..0f4c29b
--- /dev/null
+++ b/WebCore/platform/graphics/wx/FontPlatformData.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 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.
+ * 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.
+ */
+
+#ifndef FontPlatformData_H
+#define FontPlatformData_H
+
+#include "FontDescription.h"
+#include "CString.h"
+#include "AtomicString.h"
+#include "StringImpl.h"
+
+#include <wx/defs.h>
+#include <wx/font.h>
+
+namespace WebCore {
+
+class FontPlatformData {
+public:
+ class Deleted {};
+
+ enum FontState { UNINITIALIZED, DELETED, VALID };
+
+ FontPlatformData(Deleted)
+ : m_fontState(DELETED)
+ { }
+
+ ~FontPlatformData();
+
+ FontPlatformData(wxFont f)
+ : m_font(f)
+ , m_fontState(VALID)
+ {
+ m_fontHash = computeHash();
+ }
+
+ FontPlatformData(const FontDescription&, const AtomicString&);
+
+ FontPlatformData()
+ : m_fontState(UNINITIALIZED)
+ {
+ }
+
+ wxFont font() const {
+ return m_font;
+ }
+
+ unsigned hash() const {
+ switch (m_fontState) {
+ case DELETED:
+ return -1;
+ case UNINITIALIZED:
+ return 0;
+ case VALID:
+ return computeHash();
+ }
+ }
+
+ bool operator==(const FontPlatformData& other) const
+ {
+ if (m_fontState == VALID)
+ return other.m_fontState == VALID && m_font.Ok() && other.m_font.Ok() && m_font.IsSameAs(other.m_font);
+ else
+ return m_fontState == other.m_fontState;
+ }
+
+ unsigned computeHash() const {
+ ASSERT(m_font.Ok());
+ return reinterpret_cast<unsigned>(&m_font);
+ }
+
+private:
+ wxFont m_font;
+ FontState m_fontState;
+ unsigned m_fontHash;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
new file mode 100755
index 0000000..8e7c621
--- /dev/null
+++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier <kevino@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 "FontPlatformData.h"
+
+#include "FontDescription.h"
+
+#include <wx/defs.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+
+namespace WebCore {
+
+static wxFontFamily fontFamilyToWxFontFamily(const int family)
+{
+ switch (family) {
+ case FontDescription::StandardFamily:
+ return wxFONTFAMILY_DEFAULT;
+ case FontDescription::SerifFamily:
+ return wxFONTFAMILY_ROMAN;
+ case FontDescription::SansSerifFamily:
+ return wxFONTFAMILY_MODERN;
+ case FontDescription::MonospaceFamily:
+ return wxFONTFAMILY_TELETYPE; // TODO: Check these are equivalent
+ case FontDescription::CursiveFamily:
+ return wxFONTFAMILY_SCRIPT;
+ case FontDescription::FantasyFamily:
+ return wxFONTFAMILY_DECORATIVE;
+ default:
+ return wxFONTFAMILY_DEFAULT;
+ }
+}
+
+static wxFontWeight fontWeightToWxFontWeight(bool isBold)
+{
+ if (isBold)
+ return wxFONTWEIGHT_BOLD;
+
+ return wxFONTWEIGHT_NORMAL;
+}
+
+static int italicToWxFontStyle(bool isItalic)
+{
+ if (isItalic)
+ return wxFONTSTYLE_ITALIC;
+
+ return wxFONTSTYLE_NORMAL;
+}
+
+FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicString& family)
+{
+// NB: The Windows wxFont constructor has two forms, one taking a wxSize (with pixels)
+// and one taking an int (points). When points are used, Windows calculates
+// a pixel size using an algorithm which causes the size to be way off. However,
+// this is a moot issue on Linux and Mac as they only accept the point argument. So,
+// we use the pixel size constructor on Windows, but we use point size on Linux and Mac.
+#if __WXMSW__
+ m_font = wxFont( wxSize(0, -desc.computedPixelSize()),
+ fontFamilyToWxFontFamily(desc.genericFamily()),
+ italicToWxFontStyle(desc.italic()),
+ fontWeightToWxFontWeight(desc.bold()),
+ false,
+ family.string()
+ );
+#else
+ m_font = wxFont( desc.computedPixelSize(),
+ fontFamilyToWxFontFamily(desc.genericFamily()),
+ italicToWxFontStyle(desc.italic()),
+ fontWeightToWxFontWeight(desc.bold()),
+ false,
+ family.string()
+ );
+#endif
+ m_fontState = VALID;
+ m_fontHash = computeHash();
+
+}
+
+FontPlatformData::~FontPlatformData()
+{
+ m_fontState = UNINITIALIZED;
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp
new file mode 100644
index 0000000..07223e9
--- /dev/null
+++ b/WebCore/platform/graphics/wx/FontWx.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 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 "Font.h"
+
+#include "FontFallbackList.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+
+#include <wx/dcclient.h>
+#include "fontprops.h"
+#include "non-kerned-drawing.h"
+
+namespace WebCore {
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs, const FloatPoint& point) const
+{
+ // prepare DC
+ Color color = graphicsContext->fillColor();
+
+ // We can't use wx drawing methods on Win/Linux because they automatically kern text
+ // so we've created a function with platform dependent drawing implementations that
+ // will hopefully be folded into wx once the API has solidified.
+ // see platform/wx/wxcode/<platform> for the implementations.
+ drawTextWithSpacing(graphicsContext, font, color, glyphBuffer, from, numGlyphs, point);
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
+{
+ notImplemented();
+ return FloatRect();
+}
+
+void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ notImplemented();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+ notImplemented();
+ return 0;
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/GlyphMapWx.cpp b/WebCore/platform/graphics/wx/GlyphMapWx.cpp
new file mode 100755
index 0000000..ebf86e4
--- /dev/null
+++ b/WebCore/platform/graphics/wx/GlyphMapWx.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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 "GlyphPageTreeNode.h"
+
+#include "SimpleFontData.h"
+#include <unicode/utf16.h>
+
+namespace WebCore
+{
+
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ bool isUtf16 = bufferLength != length;
+
+ for (unsigned i = 0; i < length; i++) {
+ UChar32 character;
+
+ if(isUtf16) {
+ UChar lead = buffer[i * 2];
+ UChar trail = buffer[i * 2 + 1];
+ character = U16_GET_SUPPLEMENTARY(lead, trail);
+ } else {
+ character = buffer[i];
+ }
+
+ setGlyphDataForIndex(offset + i, character, fontData);
+ }
+
+ return true;
+}
+
+} \ No newline at end of file
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
new file mode 100644
index 0000000..951d3a3
--- /dev/null
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier <kevino@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 "GraphicsContext.h"
+
+#include "AffineTransform.h"
+#include "FloatRect.h"
+#include "Font.h"
+#include "IntRect.h"
+#include "NotImplemented.h"
+#include "Pen.h"
+#include <wtf/MathExtras.h>
+
+#include <math.h>
+#include <stdio.h>
+
+#include <wx/defs.h>
+#include <wx/window.h>
+#include <wx/dcclient.h>
+#include <wx/dcgraph.h>
+#include <wx/graphics.h>
+
+#if __WXMAC__
+#include <Carbon/Carbon.h>
+#elif __WXMSW__
+#include <windows.h>
+#endif
+
+namespace WebCore {
+
+int getWxCompositingOperation(CompositeOperator op, bool hasAlpha)
+{
+ // FIXME: Add support for more operators.
+ if (op == CompositeSourceOver && !hasAlpha)
+ op = CompositeCopy;
+
+ int function;
+ switch (op) {
+ case CompositeClear:
+ function = wxCLEAR;
+ case CompositeCopy:
+ function = wxCOPY;
+ break;
+ default:
+ function = wxCOPY;
+ }
+ return function;
+}
+
+static int strokeStyleToWxPenStyle(int p)
+{
+ if (p == SolidStroke)
+ return wxSOLID;
+ if (p == DottedStroke)
+ return wxDOT;
+ if (p == DashedStroke)
+ return wxLONG_DASH;
+ if (p == NoStroke)
+ return wxTRANSPARENT;
+
+ return wxSOLID;
+}
+
+class GraphicsContextPlatformPrivate {
+public:
+ GraphicsContextPlatformPrivate();
+ ~GraphicsContextPlatformPrivate();
+
+#if USE(WXGC)
+ wxGCDC* context;
+#else
+ wxWindowDC* context;
+#endif
+ int mswDCStateID;
+ wxRegion gtkCurrentClipRgn;
+ wxRegion gtkPaintClipRgn;
+};
+
+GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate() :
+ context(0),
+ mswDCStateID(0),
+ gtkCurrentClipRgn(wxRegion()),
+ gtkPaintClipRgn(wxRegion())
+{
+}
+
+GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
+{
+}
+
+
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
+ : m_common(createGraphicsContextPrivate())
+ , m_data(new GraphicsContextPlatformPrivate)
+{
+ setPaintingDisabled(!context);
+ if (context) {
+ // Make sure the context starts in sync with our state.
+ setPlatformFillColor(fillColor());
+ setPlatformStrokeColor(strokeColor());
+ }
+#if USE(WXGC)
+ m_data->context = (wxGCDC*)context;
+#else
+ m_data->context = (wxWindowDC*)context;
+#endif
+}
+
+GraphicsContext::~GraphicsContext()
+{
+ destroyGraphicsContextPrivate(m_common);
+ delete m_data;
+}
+
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+ return (PlatformGraphicsContext*)m_data->context;
+}
+
+void GraphicsContext::savePlatformState()
+{
+ if (m_data->context)
+ {
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ gc->PushState();
+#else
+ // when everything is working with USE_WXGC, we can remove this
+ #if __WXMAC__
+ CGContextRef context;
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ context = (CGContextRef)gc->GetNativeContext();
+ if (context)
+ CGContextSaveGState(context);
+ #elif __WXMSW__
+ HDC dc = (HDC)m_data->context->GetHDC();
+ m_data->mswDCStateID = ::SaveDC(dc);
+ #elif __WXGTK__
+ m_data->gtkCurrentClipRgn = m_data->context->m_currentClippingRegion;
+ m_data->gtkPaintClipRgn = m_data->context->m_paintClippingRegion;
+ #endif
+#endif // __WXMAC__
+ }
+}
+
+void GraphicsContext::restorePlatformState()
+{
+ if (m_data->context)
+ {
+#if USE(WXGC)
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ gc->PopState();
+#else
+ #if __WXMAC__
+ CGContextRef context;
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ if (gc)
+ context = (CGContextRef)gc->GetNativeContext();
+ if (context)
+ CGContextRestoreGState(context);
+ #elif __WXMSW__
+ HDC dc = (HDC)m_data->context->GetHDC();
+ ::RestoreDC(dc, m_data->mswDCStateID);
+ #elif __WXGTK__
+ m_data->context->m_currentClippingRegion = m_data->gtkCurrentClipRgn;
+ m_data->context->m_paintClippingRegion = m_data->gtkPaintClipRgn;
+ #endif
+
+#endif // USE_WXGC
+ }
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+ m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+// This is only used to draw borders.
+void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
+{
+ if (paintingDisabled())
+ return;
+
+ FloatPoint p1 = point1;
+ FloatPoint p2 = point2;
+
+ m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+ m_data->context->DrawLine(point1.x(), point1.y(), point2.x(), point2.y());
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+ m_data->context->DrawEllipse(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+void GraphicsContext::drawImage(WebCore::ImageBuffer*, WebCore::FloatRect const&, WebCore::FloatRect const&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+ m_data->context->DrawEllipticArc(rect.x(), rect.y(), rect.width(), rect.height(), startAngle, angleSpan);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
+{
+ if (paintingDisabled())
+ return;
+
+ if (npoints <= 1)
+ return;
+
+ wxPoint* polygon = new wxPoint[npoints];
+ for (size_t i = 0; i < npoints; i++)
+ polygon[i] = wxPoint(points[i].x(), points[i].y());
+ m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+ m_data->context->DrawPolygon((int)npoints, polygon);
+ delete [] polygon;
+}
+
+void GraphicsContext::fillRect(const IntRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->context->SetPen(*wxTRANSPARENT_PEN);
+ m_data->context->SetBrush(wxBrush(color));
+ m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ m_data->context->SetPen(wxPen(color));
+ m_data->context->SetBrush(wxBrush(color));
+ m_data->context->DrawRectangle(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::drawFocusRing(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+}
+
+void GraphicsContext::clip(const IntRect& r)
+{
+ wxWindowDC* windc = dynamic_cast<wxWindowDC*>(m_data->context);
+ wxPoint pos(0, 0);
+
+ if (windc) {
+#ifndef __WXGTK__
+ wxWindow* window = windc->GetWindow();
+#else
+ wxWindow* window = windc->m_owner;
+#endif
+ if (window) {
+ wxWindow* parent = window->GetParent();
+ // we need to convert from WebView "global" to WebFrame "local" coords.
+ // FIXME: We only want to go to the top WebView.
+ while (parent) {
+ pos += window->GetPosition();
+ parent = parent->GetParent();
+ }
+ }
+ }
+
+ m_data->context->SetClippingRegion(r.x() - pos.x, r.y() - pos.y, r.width() + pos.x, r.height() + pos.y);
+}
+
+void GraphicsContext::clipOut(const Path&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clipOut(const IntRect&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::clipOutEllipseInRect(const IntRect&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
+{
+ if (paintingDisabled())
+ return;
+
+ IntPoint endPoint = origin + IntSize(width, 0);
+ m_data->context->SetPen(wxPen(strokeColor(), strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+ m_data->context->DrawLine(origin.x(), origin.y(), endPoint.x(), endPoint.y());
+}
+
+
+void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar)
+{
+ if (grammar)
+ m_data->context->SetPen(wxPen(*wxGREEN, 2, wxLONG_DASH));
+ else
+ m_data->context->SetPen(wxPen(*wxRED, 2, wxLONG_DASH));
+
+ m_data->context->DrawLine(origin.x(), origin.y(), origin.x() + width, origin.y());
+}
+
+void GraphicsContext::clip(const Path&)
+{
+ notImplemented();
+}
+
+AffineTransform GraphicsContext::getCTM() const
+{
+ notImplemented();
+ return AffineTransform();
+}
+
+void GraphicsContext::translate(float tx, float ty)
+{
+#if USE(WXGC)
+ if (m_data->context) {
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ gc->Translate(tx, ty);
+ }
+#endif
+}
+
+void GraphicsContext::rotate(float angle)
+{
+#if USE(WXGC)
+ if (m_data->context) {
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ gc->Rotate(angle);
+ }
+#endif
+}
+
+void GraphicsContext::scale(const FloatSize& scale)
+{
+#if USE(WXGC)
+ if (m_data->context) {
+ wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
+ gc->Scale(scale.width(), scale.height());
+ }
+#endif
+}
+
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
+{
+ FloatRect result;
+
+ wxCoord x = (wxCoord)frect.x();
+ wxCoord y = (wxCoord)frect.y();
+
+ x = m_data->context->LogicalToDeviceX(x);
+ y = m_data->context->LogicalToDeviceY(y);
+ result.setX((float)x);
+ result.setY((float)y);
+ x = (wxCoord)frect.width();
+ y = (wxCoord)frect.height();
+ x = m_data->context->LogicalToDeviceXRel(x);
+ y = m_data->context->LogicalToDeviceYRel(y);
+ result.setWidth((float)x);
+ result.setHeight((float)y);
+ return result;
+}
+
+void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setCompositeOperation(CompositeOperator op)
+{
+ if (m_data->context)
+ m_data->context->SetLogicalFunction(getWxCompositingOperation(op, false));
+}
+
+void GraphicsContext::beginPath()
+{
+ notImplemented();
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ notImplemented();
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ if (m_data->context)
+ m_data->context->SetPen(wxPen(color, strokeThickness(), strokeStyleToWxPenStyle(strokeStyle())));
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float thickness)
+{
+ if (paintingDisabled())
+ return;
+
+ if (m_data->context)
+ m_data->context->SetPen(wxPen(strokeColor(), thickness, strokeStyleToWxPenStyle(strokeStyle())));
+
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& color)
+{
+ if (paintingDisabled())
+ return;
+
+ if (m_data->context)
+ m_data->context->SetBrush(wxBrush(color));
+}
+
+void GraphicsContext::concatCTM(const AffineTransform& transform)
+{
+ if (paintingDisabled())
+ return;
+
+ notImplemented();
+ return;
+}
+
+void GraphicsContext::setUseAntialiasing(bool enable)
+{
+ if (paintingDisabled())
+ return;
+ notImplemented();
+}
+
+void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
+{
+ if (paintingDisabled())
+ return;
+ notImplemented();
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
new file mode 100644
index 0000000..0c832ea
--- /dev/null
+++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier <kevino@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 "ImageBuffer.h"
+
+#include "GraphicsContext.h"
+#include "ImageData.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+std::auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize&, bool grayScale)
+{
+ return std::auto_ptr<ImageBuffer>(new ImageBuffer());
+}
+
+ImageBuffer::~ImageBuffer()
+{
+}
+
+GraphicsContext* ImageBuffer::context() const
+{
+ return 0;
+}
+
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void ImageBuffer::putImageData(ImageData*, const IntRect&, const IntPoint&)
+{
+ notImplemented();
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/ImageSourceWx.cpp b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
new file mode 100644
index 0000000..fc36635
--- /dev/null
+++ b/WebCore/platform/graphics/wx/ImageSourceWx.cpp
@@ -0,0 +1,233 @@
+/*
+ * 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 "PNGImageDecoder.h"
+#include "SharedBuffer.h"
+#include "XBMImageDecoder.h"
+
+#include <wx/defs.h>
+#include <wx/bitmap.h>
+#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()
+{
+ delete m_decoder;
+}
+
+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.
+ 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();
+}
+
+int ImageSource::repetitionCount()
+{
+ if (!m_decoder)
+ return cAnimationNone;
+
+ return m_decoder->repetitionCount();
+}
+
+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()
+{
+ delete m_decoder;
+ m_decoder = 0;
+}
+
+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;
+
+ IntRect imageRect = buffer->rect();
+ unsigned char* bytes = (unsigned char*)buffer->bytes().data();
+ long colorSize = buffer->bytes().size();
+
+ typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> PixelData;
+
+ int width = size().width();
+ int height = size().height();
+
+ wxBitmap* bmp = new wxBitmap(width, height, 32);
+ PixelData data(*bmp);
+
+ int rowCounter = 0;
+ long pixelCounter = 0;
+
+ PixelData::Iterator p(data);
+
+ PixelData::Iterator rowStart = p;
+
+ // NB: It appears that the data is in BGRA format instead of RGBA format.
+ // This code works properly on both ppc and intel, meaning the issue is
+ // likely not an issue of byte order getting mixed up on different archs.
+ for (long i = 0; i < buffer->bytes().size()*4; i+=4) {
+ p.Red() = bytes[i+2];
+ p.Green() = bytes[i+1];
+ p.Blue() = bytes[i+0];
+ p.Alpha() = bytes[i+3];
+
+ p++;
+
+ pixelCounter++;
+ if ( (pixelCounter % width ) == 0 ) {
+ rowCounter++;
+ p = rowStart;
+ p.MoveTo(data, 0, rowCounter);
+ }
+
+ }
+
+ bmp->UseAlpha();
+ ASSERT(bmp->IsOk());
+ return bmp;
+}
+
+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;
+
+ return buffer->duration() / 1000.0f;
+}
+
+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
new file mode 100644
index 0000000..785466c
--- /dev/null
+++ b/WebCore/platform/graphics/wx/ImageWx.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 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 "Image.h"
+
+#include "AffineTransform.h"
+#include "BitmapImage.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+
+#include <math.h>
+#include <stdio.h>
+
+#include <wx/defs.h>
+#include <wx/bitmap.h>
+#include <wx/dc.h>
+#include <wx/dcmemory.h>
+#include <wx/dcgraph.h>
+#include <wx/graphics.h>
+#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
+int getWxCompositingOperation(CompositeOperator op, bool hasAlpha);
+
+void FrameData::clear()
+{
+ if (m_frame) {
+ delete m_frame;
+ m_frame = 0;
+ m_duration = 0.;
+ m_hasAlpha = true;
+ }
+}
+
+// ================================================
+// Image Class
+// ================================================
+
+Image* Image::loadPlatformResource(const char *name)
+{
+ Vector<char> arr = loadResourceIntoArray(name);
+ Image* img = new BitmapImage();
+ RefPtr<SharedBuffer> buffer = new SharedBuffer(arr.data(), arr.size());
+ img->setData(buffer, true);
+ return img;
+}
+
+void BitmapImage::initPlatformData()
+{
+ // FIXME: NYI
+}
+
+// Drawing Routines
+
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
+{
+ if (!m_source.initialized())
+ return;
+
+#if USE(WXGC)
+ wxGCDC* context = (wxGCDC*)ctxt->platformContext();
+#else
+ wxWindowDC* context = ctxt->platformContext();
+#endif
+
+ wxBitmap* bitmap = frameAtIndex(m_currentFrame);
+ if (!bitmap) // If it's too early we won't have an image yet.
+ return;
+
+ IntSize selfSize = size();
+ FloatRect srcRect(src);
+ FloatRect dstRect(dst);
+
+ // If we're drawing a sub portion of the image or scaling then create
+ // a pattern transformation on the image and draw the transformed pattern.
+ // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
+ // FIXME: NYI
+
+ wxMemoryDC mydc;
+ ASSERT(bitmap->GetRefData());
+ mydc.SelectObject(*bitmap);
+ context->Blit((wxCoord)dst.x(),(wxCoord)dst.y(), (wxCoord)dst.width(), (wxCoord)dst.height(), &mydc,
+ (wxCoord)src.x(), (wxCoord)src.y(), wxCOPY, true);
+ mydc.SelectObject(wxNullBitmap);
+
+ // NB: delete is causing crashes during page load, but not during the deletion
+ // itself. It occurs later on when a valid bitmap created in frameAtIndex
+ // suddenly becomes invalid after returning. It's possible these errors deal
+ // with reentrancy and threding problems.
+ //delete bitmap;
+ startAnimation();
+}
+
+
+void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& dstRect)
+{
+ if (!m_source.initialized())
+ return;
+
+#if USE(WXGC)
+ wxGCDC* context = (wxGCDC*)ctxt->platformContext();
+#else
+ wxWindowDC* context = ctxt->platformContext();
+#endif
+
+ ctxt->save();
+ ctxt->clip(IntRect(dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height()));
+ wxBitmap* bitmap = frameAtIndex(m_currentFrame);
+ if (!bitmap) // If it's too early we won't have an image yet.
+ return;
+
+ float currentW = 0;
+ float currentH = 0;
+
+#if USE(WXGC)
+ wxGraphicsContext* gc = context->GetGraphicsContext();
+ gc->ConcatTransform(patternTransform);
+#endif
+
+ wxMemoryDC mydc;
+ mydc.SelectObject(*bitmap);
+
+ while ( currentW < dstRect.width() ) {
+ while ( currentH < dstRect.height() ) {
+ context->Blit((wxCoord)dstRect.x() + currentW, (wxCoord)dstRect.y() + currentH,
+ (wxCoord)srcRect.width(), (wxCoord)srcRect.height(), &mydc,
+ (wxCoord)srcRect.x(), (wxCoord)srcRect.y(), wxCOPY, true);
+ currentH += srcRect.height();
+ }
+ currentW += srcRect.width();
+ currentH = 0;
+ }
+ ctxt->restore();
+ mydc.SelectObject(wxNullBitmap);
+
+ // NB: delete is causing crashes during page load, but not during the deletion
+ // itself. It occurs later on when a valid bitmap created in frameAtIndex
+ // suddenly becomes invalid after returning. It's possible these errors deal
+ // with reentrancy and threding problems.
+ //delete bitmap;
+
+ startAnimation();
+
+}
+
+void BitmapImage::checkForSolidColor()
+{
+
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/IntPointWx.cpp b/WebCore/platform/graphics/wx/IntPointWx.cpp
new file mode 100644
index 0000000..389ac9f
--- /dev/null
+++ b/WebCore/platform/graphics/wx/IntPointWx.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006, 2007 Kevin Ollivier <kevino@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 "IntPoint.h"
+
+#include <wx/defs.h>
+#include <wx/gdicmn.h>
+
+namespace WebCore {
+
+IntPoint::IntPoint(const wxPoint& p)
+ : m_x(p.x)
+ , m_y(p.y)
+{
+}
+
+IntPoint::operator wxPoint() const
+{
+ return wxPoint(m_x, m_y);
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/IntRectWx.cpp b/WebCore/platform/graphics/wx/IntRectWx.cpp
new file mode 100644
index 0000000..10c1b55
--- /dev/null
+++ b/WebCore/platform/graphics/wx/IntRectWx.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006, 2007 Kevin Ollivier <kevino@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 "IntRect.h"
+
+#include <wx/defs.h>
+#include <wx/gdicmn.h>
+
+namespace WebCore {
+
+IntRect::IntRect(const wxRect& r)
+ : m_location(IntPoint(r.x, r.y))
+ , m_size(IntSize(r.width, r.height))
+{
+}
+
+IntRect::operator wxRect() const
+{
+ return wxRect(x(), y(), width(), height());
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp
new file mode 100644
index 0000000..5ff9914
--- /dev/null
+++ b/WebCore/platform/graphics/wx/PathWx.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2007 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 "Path.h"
+
+#include "AffineTransform.h"
+#include "FloatPoint.h"
+#include "FloatRect.h"
+#include "NotImplemented.h"
+
+#include <stdio.h>
+
+#include <wx/defs.h>
+#include <wx/graphics.h>
+
+namespace WebCore {
+
+int getWxWindRuleForWindRule(WindRule rule)
+{
+ if (rule == RULE_EVENODD)
+ return wxODDEVEN_RULE;
+
+ return wxWINDING_RULE;
+}
+
+Path::Path()
+{
+ m_path = 0;
+ // NB: This only supports the 'default' renderer as determined by wx on
+ // each platform. If an app uses a non-default renderer (e.g. Cairo on Win),
+ // there will be problems, but there's no way we can determine which
+ // renderer an app is using right now with wx API, so we will just handle
+ // the common case.
+#if USE(WXGC)
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ if (renderer) {
+ wxGraphicsPath path = renderer->CreatePath();
+ m_path = new wxGraphicsPath(path);
+ }
+#endif
+}
+
+Path::~Path()
+{
+}
+
+Path::Path(const Path& path)
+{
+ m_path = (PlatformPath*)&path.m_path;
+}
+
+bool Path::contains(const FloatPoint& point, const WindRule rule) const
+{
+ return false;
+}
+
+void Path::translate(const FloatSize&)
+{
+ notImplemented();
+}
+
+FloatRect Path::boundingRect() const
+{
+#if USE(WXGC)
+ if (m_path) {
+ return m_path->GetBox();
+ }
+#endif
+
+ return FloatRect();
+}
+
+Path& Path::operator=(const Path&)
+{
+ notImplemented();
+ return*this;
+}
+
+void Path::clear()
+{
+ if (m_path)
+ delete m_path;
+
+#if USE(WXGC)
+ wxGraphicsRenderer* renderer = wxGraphicsRenderer::GetDefaultRenderer();
+ if (renderer) {
+ wxGraphicsPath path = renderer->CreatePath();
+ m_path = new wxGraphicsPath(path);
+ }
+#endif
+}
+
+void Path::moveTo(const FloatPoint& point)
+{
+#if USE(WXGC)
+ if (m_path)
+ m_path->MoveToPoint(point.x(), point.y());
+#endif
+}
+
+void Path::addLineTo(const FloatPoint&)
+{
+ notImplemented();
+}
+
+void Path::addQuadCurveTo(const FloatPoint&, const FloatPoint&)
+{
+ notImplemented();
+}
+
+void Path::addBezierCurveTo(const FloatPoint&, const FloatPoint&, const FloatPoint&)
+{
+ notImplemented();
+}
+
+void Path::addArcTo(const FloatPoint&, const FloatPoint&, float)
+{
+ notImplemented();
+}
+
+void Path::closeSubpath()
+{
+ notImplemented();
+}
+
+void Path::addArc(const FloatPoint&, float, float, float, bool)
+{
+ notImplemented();
+}
+
+void Path::addRect(const FloatRect&)
+{
+ notImplemented();
+}
+
+void Path::addEllipse(const FloatRect&)
+{
+ notImplemented();
+}
+
+void Path::transform(const AffineTransform&)
+{
+ notImplemented();
+}
+
+void Path::apply(void* info, PathApplierFunction function) const
+{
+ notImplemented();
+}
+
+bool Path::isEmpty() const
+{
+ notImplemented();
+ return false;
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/PenWx.cpp b/WebCore/platform/graphics/wx/PenWx.cpp
new file mode 100644
index 0000000..5a131e3
--- /dev/null
+++ b/WebCore/platform/graphics/wx/PenWx.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007 Kevin Ollivier <kevino@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 "Pen.h"
+
+#include <wx/defs.h>
+#include <wx/pen.h>
+#include <wx/colour.h>
+
+namespace WebCore {
+
+// Pen style conversion functions
+static int penStyleToWxPenStyle(int p)
+{
+ if (p == Pen::SolidLine)
+ return wxSOLID;
+ if (p == Pen::DotLine)
+ return wxDOT;
+ if (p == Pen::DashLine)
+ return wxLONG_DASH;
+ if (p == Pen::NoPen)
+ return wxTRANSPARENT;
+
+ return wxSOLID;
+}
+
+static Pen::PenStyle wxPenStyleToPenStyle(int p)
+{
+ if (p == wxSOLID)
+ return Pen::SolidLine;
+ if (p == wxDOT)
+ return Pen::DotLine;
+ if (p == wxLONG_DASH || p == wxSHORT_DASH || p == wxDOT_DASH || p == wxUSER_DASH)
+ return Pen::DashLine;
+ if (p == wxTRANSPARENT)
+ return Pen::NoPen;
+
+ return Pen::SolidLine;
+}
+
+Pen::Pen(const wxPen& p)
+{
+ wxColour color = p.GetColour();
+ setColor(Color(color.Red(), color.Green(), color.Blue()));
+ setWidth(p.GetWidth());
+ setStyle(wxPenStyleToPenStyle(p.GetStyle()));
+}
+
+Pen::operator wxPen() const
+{
+ return wxPen(wxColour(m_color.red(), m_color.blue(), m_color.green()), width(), penStyleToWxPenStyle(style()));
+}
+
+}
diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
new file mode 100755
index 0000000..a509933
--- /dev/null
+++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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.
+ * 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 "FontCache.h"
+#include "FloatRect.h"
+#include "FontDescription.h"
+#include <wtf/MathExtras.h>
+#include <unicode/uchar.h>
+#include <unicode/unorm.h>
+
+#include <wx/defs.h>
+#include <wx/dcscreen.h>
+#include "fontprops.h"
+
+namespace WebCore
+{
+
+void SimpleFontData::platformInit()
+{
+ wxFont font = m_font.font();
+ wxFontProperties props = wxFontProperties(&font);
+ m_ascent = props.GetAscent();
+ m_descent = props.GetDescent();
+ m_lineSpacing = props.GetLineSpacing();
+ m_xHeight = props.GetXHeight();
+ m_unitsPerEm = 1; // FIXME!
+ m_lineGap = props.GetLineGap();
+}
+
+void SimpleFontData::platformDestroy()
+{
+ delete m_smallCapsFontData;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_smallCapsFontData){
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(0.70f*fontDescription.computedSize());
+ const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family());
+ m_smallCapsFontData = new SimpleFontData(*pdata);
+ }
+ 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()
+{
+ if (m_font.font().Ok())
+ m_treatAsFixedPitch = m_font.font().IsFixedWidth();
+ else
+ m_treatAsFixedPitch = false;
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ // TODO: fix this! Make GetTextExtents a method of wxFont in 2.9
+ int width = 10;
+ GetTextExtent(m_font.font(), (wxChar)glyph, &width, NULL);
+ return width;
+}
+
+}