summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/chromium
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium')
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp112
-rw-r--r--Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h65
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp126
-rw-r--r--Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h80
-rw-r--r--Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp426
-rw-r--r--Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h164
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp368
-rw-r--r--Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h99
-rw-r--r--Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h100
-rw-r--r--Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm210
-rw-r--r--Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp148
-rw-r--r--Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h77
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp607
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp159
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp541
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontLinux.cpp410
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformData.h40
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp163
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h137
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp235
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h167
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontRenderStyle.h74
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp438
-rw-r--r--Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h96
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp286
-rw-r--r--Source/WebCore/platform/graphics/chromium/GLES2Canvas.h106
-rw-r--r--Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp239
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp645
-rw-r--r--Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h146
-rw-r--r--Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp238
-rw-r--r--Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.h44
-rw-r--r--Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp54
-rw-r--r--Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp50
-rw-r--r--Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp65
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageBufferData.h50
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageChromium.cpp45
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm58
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp164
-rw-r--r--Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h66
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.cpp520
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerChromium.h307
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp803
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h221
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTexture.cpp93
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTexture.h69
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp424
-rw-r--r--Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h123
-rw-r--r--Source/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h49
-rw-r--r--Source/WebCore/platform/graphics/chromium/PlatformIcon.h42
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp133
-rw-r--r--Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h74
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp157
-rw-r--r--Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h98
-rw-r--r--Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp207
-rw-r--r--Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp236
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureManager.cpp171
-rw-r--r--Source/WebCore/platform/graphics/chromium/TextureManager.h83
-rw-r--r--Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp513
-rw-r--r--Source/WebCore/platform/graphics/chromium/TransparencyWin.h261
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp932
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.h414
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp138
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h96
-rw-r--r--Source/WebCore/platform/graphics/chromium/VDMXParser.cpp202
-rw-r--r--Source/WebCore/platform/graphics/chromium/VDMXParser.h40
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp47
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h82
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h57
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp427
-rw-r--r--Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h124
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp88
-rw-r--r--Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h60
72 files changed, 14589 insertions, 0 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
new file mode 100644
index 0000000..ad961aa
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Canvas2DLayerChromium.h"
+
+#include "DrawingBuffer.h"
+#include "GraphicsContext3D.h"
+
+namespace WebCore {
+
+PassRefPtr<Canvas2DLayerChromium> Canvas2DLayerChromium::create(DrawingBuffer* drawingBuffer, GraphicsLayerChromium* owner)
+{
+ return adoptRef(new Canvas2DLayerChromium(drawingBuffer, owner));
+}
+
+Canvas2DLayerChromium::Canvas2DLayerChromium(DrawingBuffer* drawingBuffer, GraphicsLayerChromium* owner)
+ : CanvasLayerChromium(owner)
+ , m_drawingBuffer(drawingBuffer)
+{
+}
+
+Canvas2DLayerChromium::~Canvas2DLayerChromium()
+{
+ if (m_textureId)
+ layerRendererContext()->deleteTexture(m_textureId);
+}
+
+void Canvas2DLayerChromium::updateContentsIfDirty()
+{
+ if (!m_contentsDirty || !m_drawingBuffer)
+ return;
+ if (m_textureChanged) { // We have to generate a new backing texture.
+ GraphicsContext3D* context = layerRendererContext();
+ if (m_textureId)
+ context->deleteTexture(m_textureId);
+ m_textureId = context->createTexture();
+ context->activeTexture(GraphicsContext3D::TEXTURE0);
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
+ IntSize size = m_drawingBuffer->size();
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
+ // Set the min-mag filters to linear and wrap modes to GraphicsContext3D::CLAMP_TO_EDGE
+ // to get around NPOT texture limitations of GLES.
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_textureChanged = false;
+ // FIXME: The finish() here is required because we have to make sure that the texture created in this
+ // context (the compositor context) is actually created by the service side before the child context
+ // attempts to use it (in publishToPlatformLayer). finish() is currently the only call with strong
+ // enough semantics to promise this, but is actually much stronger. Ideally we'd do something like
+ // inserting a fence here and waiting for it before trying to publish.
+ context->finish();
+ }
+ // Update the contents of the texture used by the compositor.
+ if (m_contentsDirty) {
+ m_drawingBuffer->publishToPlatformLayer();
+ m_contentsDirty = false;
+ }
+}
+
+void Canvas2DLayerChromium::setTextureChanged()
+{
+ m_textureChanged = true;
+}
+
+unsigned Canvas2DLayerChromium::textureId() const
+{
+ return m_textureId;
+}
+
+void Canvas2DLayerChromium::setDrawingBuffer(DrawingBuffer* drawingBuffer)
+{
+ if (drawingBuffer != m_drawingBuffer) {
+ m_drawingBuffer = drawingBuffer;
+ m_textureChanged = true;
+ }
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
new file mode 100644
index 0000000..44ef050
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef Canvas2DLayerChromium_h
+#define Canvas2DLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayerChromium.h"
+
+namespace WebCore {
+
+class DrawingBuffer;
+
+// A layer containing an accelerated 2d canvas
+class Canvas2DLayerChromium : public CanvasLayerChromium {
+public:
+ static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner);
+ virtual ~Canvas2DLayerChromium();
+ virtual bool drawsContent() { return true; }
+ virtual void updateContentsIfDirty();
+
+ void setTextureChanged();
+ unsigned textureId() const;
+ void setDrawingBuffer(DrawingBuffer*);
+
+private:
+ explicit Canvas2DLayerChromium(DrawingBuffer*, GraphicsLayerChromium* owner);
+ DrawingBuffer* m_drawingBuffer;
+
+ static unsigned m_shaderProgramId;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
new file mode 100644
index 0000000..4aef25b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayerChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+
+namespace WebCore {
+
+unsigned CanvasLayerChromium::m_shaderProgramId = 0;
+
+CanvasLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_canvasShaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ char vertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ // Canvas layers need to be flipped vertically and their colors shouldn't be
+ // swizzled.
+ char fragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_canvasShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString);
+ if (!m_canvasShaderProgram) {
+ LOG_ERROR("CanvasLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_shaderSamplerLocation = m_context->getUniformLocation(m_canvasShaderProgram, "s_texture");
+ m_shaderMatrixLocation = m_context->getUniformLocation(m_canvasShaderProgram, "matrix");
+ m_shaderAlphaLocation = m_context->getUniformLocation(m_canvasShaderProgram, "alpha");
+ ASSERT(m_shaderSamplerLocation != -1);
+ ASSERT(m_shaderMatrixLocation != -1);
+ ASSERT(m_shaderAlphaLocation != -1);
+
+ m_initialized = true;
+}
+
+CanvasLayerChromium::SharedValues::~SharedValues()
+{
+ if (m_canvasShaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_canvasShaderProgram));
+}
+
+CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner)
+ : LayerChromium(owner)
+ , m_textureChanged(true)
+ , m_textureId(0)
+{
+}
+
+CanvasLayerChromium::~CanvasLayerChromium()
+{
+}
+
+void CanvasLayerChromium::draw()
+{
+ ASSERT(layerRenderer());
+ const CanvasLayerChromium::SharedValues* sv = layerRenderer()->canvasLayerSharedValues();
+ ASSERT(sv && sv->initialized());
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
+ layerRenderer()->useShader(sv->canvasShaderProgram());
+ GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
new file mode 100644
index 0000000..6520b55
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef CanvasLayerChromium_h
+#define CanvasLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+namespace WebCore {
+
+// Base class for WebGL and accelerated 2d canvases.
+class CanvasLayerChromium : public LayerChromium {
+public:
+ virtual ~CanvasLayerChromium();
+
+ virtual void draw();
+
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+
+ unsigned canvasShaderProgram() const { return m_canvasShaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+ unsigned m_canvasShaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ bool m_initialized;
+ };
+
+protected:
+ explicit CanvasLayerChromium(GraphicsLayerChromium* owner);
+ bool m_textureChanged;
+ unsigned m_textureId;
+
+private:
+ static unsigned m_shaderProgramId;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // CanvasLayerChromium_h
diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
new file mode 100644
index 0000000..b5eda93
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ComplexTextControllerLinux.h"
+
+#include "Font.h"
+
+#include <unicode/normlzr.h>
+
+namespace WebCore {
+
+// Harfbuzz uses 26.6 fixed point values for pixel offsets. However, we don't
+// handle subpixel positioning so this function is used to truncate Harfbuzz
+// values to a number of pixels.
+static int truncateFixedPointToInteger(HB_Fixed value)
+{
+ return value >> 6;
+}
+
+ComplexTextController::ComplexTextController(const TextRun& run, unsigned startingX, const Font* font)
+ : m_font(font)
+ , m_startingX(startingX)
+ , m_offsetX(m_startingX)
+ , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer))
+ , m_iterateBackwards(m_run.rtl())
+ , m_wordSpacingAdjustment(0)
+ , m_padding(0)
+ , m_padPerWordBreak(0)
+ , m_padError(0)
+ , m_letterSpacing(0)
+{
+ // Do not use |run| inside this constructor. Use |m_run| instead.
+
+ memset(&m_item, 0, sizeof(m_item));
+ // We cannot know, ahead of time, how many glyphs a given script run
+ // will produce. We take a guess that script runs will not produce more
+ // than twice as many glyphs as there are code points plus a bit of
+ // padding and fallback if we find that we are wrong.
+ createGlyphArrays((m_run.length() + 2) * 2);
+
+ m_item.log_clusters = new unsigned short[m_run.length()];
+
+ m_item.face = 0;
+ m_item.font = allocHarfbuzzFont();
+
+ m_item.item.bidiLevel = m_run.rtl();
+
+ m_item.string = m_run.characters();
+ m_item.stringLength = m_run.length();
+
+ reset();
+}
+
+ComplexTextController::~ComplexTextController()
+{
+ fastFree(m_item.font);
+ deleteGlyphArrays();
+ delete[] m_item.log_clusters;
+}
+
+bool ComplexTextController::isWordBreak(unsigned index)
+{
+ return index && isCodepointSpace(m_item.string[index]) && !isCodepointSpace(m_item.string[index - 1]);
+}
+
+int ComplexTextController::determineWordBreakSpacing(unsigned logClustersIndex)
+{
+ int wordBreakSpacing = 0;
+ // The first half of the conjunction works around the case where
+ // output glyphs aren't associated with any codepoints by the
+ // clusters log.
+ if (logClustersIndex < m_item.item.length
+ && isWordBreak(m_item.item.pos + logClustersIndex)) {
+ wordBreakSpacing = m_wordSpacingAdjustment;
+
+ if (m_padding > 0) {
+ int toPad = roundf(m_padPerWordBreak + m_padError);
+ m_padError += m_padPerWordBreak - toPad;
+
+ if (m_padding < toPad)
+ toPad = m_padding;
+ m_padding -= toPad;
+ wordBreakSpacing += toPad;
+ }
+ }
+ return wordBreakSpacing;
+}
+
+// setPadding sets a number of pixels to be distributed across the TextRun.
+// WebKit uses this to justify text.
+void ComplexTextController::setPadding(int padding)
+{
+ m_padding = padding;
+ if (!m_padding)
+ return;
+
+ // If we have padding to distribute, then we try to give an equal
+ // amount to each space. The last space gets the smaller amount, if
+ // any.
+ unsigned numWordBreaks = 0;
+
+ for (unsigned i = 0; i < m_item.stringLength; i++) {
+ if (isWordBreak(i))
+ numWordBreaks++;
+ }
+
+ if (numWordBreaks)
+ m_padPerWordBreak = m_padding / numWordBreaks;
+ else
+ m_padPerWordBreak = 0;
+}
+
+void ComplexTextController::reset()
+{
+ if (m_iterateBackwards)
+ m_indexOfNextScriptRun = m_run.length() - 1;
+ else
+ m_indexOfNextScriptRun = 0;
+ m_offsetX = m_startingX;
+}
+
+void ComplexTextController::setBackwardsIteration(bool isBackwards)
+{
+ m_iterateBackwards = isBackwards;
+ reset();
+}
+
+// Advance to the next script run, returning false when the end of the
+// TextRun has been reached.
+bool ComplexTextController::nextScriptRun()
+{
+ if (m_iterateBackwards) {
+ // In right-to-left mode we need to render the shaped glyph backwards and
+ // also render the script runs themselves backwards. So given a TextRun:
+ // AAAAAAACTTTTTTT (A = Arabic, C = Common, T = Thai)
+ // we render:
+ // TTTTTTCAAAAAAA
+ // (and the glyphs in each A, C and T section are backwards too)
+ if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
+ return false;
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
+ } else {
+ if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
+ return false;
+
+ // It is actually wrong to consider script runs at all in this code.
+ // Other WebKit code (e.g. Mac) segments complex text just by finding
+ // the longest span of text covered by a single font.
+ // But we currently need to call hb_utf16_script_run_next anyway to fill
+ // in the harfbuzz data structures to e.g. pick the correct script's shaper.
+ // So we allow that to run first, then do a second pass over the range it
+ // found and take the largest subregion that stays within a single font.
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
+ unsigned endOfRun;
+ for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
+ const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false).fontData;
+ if (nextFontData != m_currentFontData)
+ break;
+ }
+ m_item.item.length = endOfRun;
+ m_indexOfNextScriptRun = m_item.item.pos + endOfRun;
+ }
+
+ setupFontForScriptRun();
+ shapeGlyphs();
+ setGlyphXPositions(rtl());
+
+ return true;
+}
+
+float ComplexTextController::widthOfFullRun()
+{
+ float widthSum = 0;
+ while (nextScriptRun())
+ widthSum += width();
+
+ return widthSum;
+}
+
+void ComplexTextController::setupFontForScriptRun()
+{
+ const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
+ const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
+ m_item.face = platformData.harfbuzzFace();
+ void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
+ m_item.font->userData = opaquePlatformData;
+}
+
+HB_FontRec* ComplexTextController::allocHarfbuzzFont()
+{
+ HB_FontRec* font = reinterpret_cast<HB_FontRec*>(fastMalloc(sizeof(HB_FontRec)));
+ memset(font, 0, sizeof(HB_FontRec));
+ font->klass = &harfbuzzSkiaClass;
+ font->userData = 0;
+ // The values which harfbuzzSkiaClass returns are already scaled to
+ // pixel units, so we just set all these to one to disable further
+ // scaling.
+ font->x_ppem = 1;
+ font->y_ppem = 1;
+ font->x_scale = 1;
+ font->y_scale = 1;
+
+ return font;
+}
+
+void ComplexTextController::deleteGlyphArrays()
+{
+ delete[] m_item.glyphs;
+ delete[] m_item.attributes;
+ delete[] m_item.advances;
+ delete[] m_item.offsets;
+ delete[] m_glyphs16;
+ delete[] m_xPositions;
+}
+
+void ComplexTextController::createGlyphArrays(int size)
+{
+ m_item.glyphs = new HB_Glyph[size];
+ m_item.attributes = new HB_GlyphAttributes[size];
+ m_item.advances = new HB_Fixed[size];
+ m_item.offsets = new HB_FixedPoint[size];
+
+ m_glyphs16 = new uint16_t[size];
+ m_xPositions = new SkScalar[size];
+
+ m_item.num_glyphs = size;
+ m_glyphsArrayCapacity = size; // Save the GlyphArrays size.
+ resetGlyphArrays();
+}
+
+void ComplexTextController::resetGlyphArrays()
+{
+ int size = m_item.num_glyphs;
+ // All the types here don't have pointers. It is safe to reset to
+ // zero unless Harfbuzz breaks the compatibility in the future.
+ memset(m_item.glyphs, 0, size * sizeof(HB_Glyph));
+ memset(m_item.attributes, 0, size * sizeof(HB_GlyphAttributes));
+ memset(m_item.advances, 0, size * sizeof(HB_Fixed));
+ memset(m_item.offsets, 0, size * sizeof(HB_FixedPoint));
+ memset(m_glyphs16, 0, size * sizeof(uint16_t));
+ memset(m_xPositions, 0, size * sizeof(SkScalar));
+}
+
+void ComplexTextController::shapeGlyphs()
+{
+ // HB_ShapeItem() resets m_item.num_glyphs. If the previous call to
+ // HB_ShapeItem() used less space than was available, the capacity of
+ // the array may be larger than the current value of m_item.num_glyphs.
+ // So, we need to reset the num_glyphs to the capacity of the array.
+ m_item.num_glyphs = m_glyphsArrayCapacity;
+ resetGlyphArrays();
+ while (!HB_ShapeItem(&m_item)) {
+ // We overflowed our arrays. Resize and retry.
+ // HB_ShapeItem fills in m_item.num_glyphs with the needed size.
+ deleteGlyphArrays();
+ // The |+ 1| here is a workaround for a bug in Harfbuzz: the Khmer
+ // shaper (at least) can fail because of insufficient glyph buffers
+ // and request 0 additional glyphs: throwing us into an infinite
+ // loop.
+ createGlyphArrays(m_item.num_glyphs + 1);
+ }
+}
+
+void ComplexTextController::setGlyphXPositions(bool isRTL)
+{
+ double position = 0;
+ // logClustersIndex indexes logClusters for the first (or last when
+ // RTL) codepoint of the current glyph. Each time we advance a glyph,
+ // we skip over all the codepoints that contributed to the current
+ // glyph.
+ int logClustersIndex = 0;
+
+ if (isRTL) {
+ logClustersIndex = m_item.num_glyphs - 1;
+
+ // Glyphs are stored in logical order, but for layout purposes we
+ // always go left to right.
+ for (int i = m_item.num_glyphs - 1; i >= 0; --i) {
+ if (!m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i])) {
+ // Whitespace must be laid out in logical order, so when inserting
+ // spaces in RTL (but iterating in LTR order) we must insert spaces
+ // _before_ the next glyph.
+ if (static_cast<unsigned>(i + 1) >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
+ position += m_letterSpacing;
+
+ position += determineWordBreakSpacing(logClustersIndex);
+ }
+
+ m_glyphs16[i] = m_item.glyphs[i];
+ double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
+ m_xPositions[i] = m_offsetX + position + offsetX;
+
+ while (logClustersIndex > 0 && logClusters()[logClustersIndex] == i)
+ logClustersIndex--;
+
+ if (!m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i]))
+ position += truncateFixedPointToInteger(m_item.advances[i]);
+ }
+ } else {
+ for (size_t i = 0; i < m_item.num_glyphs; ++i) {
+ m_glyphs16[i] = m_item.glyphs[i];
+ double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
+ m_xPositions[i] = m_offsetX + position + offsetX;
+
+ if (m_currentFontData->isZeroWidthSpaceGlyph(m_glyphs16[i]))
+ continue;
+
+ double advance = truncateFixedPointToInteger(m_item.advances[i]);
+
+ advance += determineWordBreakSpacing(logClustersIndex);
+
+ if (m_item.attributes[i].clusterStart)
+ advance += m_letterSpacing;
+
+ while (static_cast<unsigned>(logClustersIndex) < m_item.item.length && logClusters()[logClustersIndex] == i)
+ logClustersIndex++;
+
+ position += advance;
+ }
+ }
+ m_pixelWidth = std::max(position, 0.0);
+ m_offsetX += m_pixelWidth;
+}
+
+void ComplexTextController::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length)
+{
+ int position = 0;
+ bool error = false;
+ // Iterate characters in source and mirror character if needed.
+ while (position < length) {
+ UChar32 character;
+ int nextPosition = position;
+ U16_NEXT(source, nextPosition, length, character);
+ if (Font::treatAsSpace(character))
+ character = ' ';
+ else if (Font::treatAsZeroWidthSpace(character))
+ character = zeroWidthSpace;
+ else if (rtl)
+ character = u_charMirror(character);
+ U16_APPEND(destination, position, length, character, error);
+ ASSERT(!error);
+ position = nextPosition;
+ }
+}
+
+const TextRun& ComplexTextController::getNormalizedTextRun(const TextRun& originalRun, OwnPtr<TextRun>& normalizedRun, OwnArrayPtr<UChar>& normalizedBuffer)
+{
+ // Normalize the text run in three ways:
+ // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks
+ // (U+0300..) are used in the run. This conversion is necessary since most OpenType
+ // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in
+ // their GSUB tables.
+ //
+ // Note that we don't use the icu::Normalizer::isNormalized(UNORM_NFC) API here since
+ // the API returns FALSE (= not normalized) for complex runs that don't require NFC
+ // normalization (e.g., Arabic text). Unless the run contains the diacritical marks,
+ // Harfbuzz will do the same thing for us using the GSUB table.
+ // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs
+ // for characters like '\n' otherwise.
+ // 3) Convert mirrored characters such as parenthesis for rtl text.
+
+ // Convert to NFC form if the text has diacritical marks.
+ icu::UnicodeString normalizedString;
+ UErrorCode error = U_ZERO_ERROR;
+
+ for (int16_t i = 0; i < originalRun.length(); ++i) {
+ UChar ch = originalRun[i];
+ if (::ublock_getCode(ch) == UBLOCK_COMBINING_DIACRITICAL_MARKS) {
+ icu::Normalizer::normalize(icu::UnicodeString(originalRun.characters(),
+ originalRun.length()), UNORM_NFC, 0 /* no options */,
+ normalizedString, error);
+ if (U_FAILURE(error))
+ return originalRun;
+ break;
+ }
+ }
+
+ // Normalize space and mirror parenthesis for rtl text.
+ int normalizedBufferLength;
+ const UChar* sourceText;
+ if (normalizedString.isEmpty()) {
+ normalizedBufferLength = originalRun.length();
+ sourceText = originalRun.characters();
+ } else {
+ normalizedBufferLength = normalizedString.length();
+ sourceText = normalizedString.getBuffer();
+ }
+
+ normalizedBuffer.set(new UChar[normalizedBufferLength + 1]);
+
+ normalizeSpacesAndMirrorChars(sourceText, originalRun.rtl(), normalizedBuffer.get(), normalizedBufferLength);
+
+ normalizedRun.set(new TextRun(originalRun));
+ normalizedRun->setText(normalizedBuffer.get(), normalizedBufferLength);
+ return *normalizedRun;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h
new file mode 100644
index 0000000..4ebbd89
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ComplexTextControllerLinux.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ComplexTextControllerLinux_h
+#define ComplexTextControllerLinux_h
+
+#include "HarfbuzzSkia.h"
+#include "SkScalar.h"
+#include "TextRun.h"
+
+#include <unicode/uchar.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class Font;
+class FontPlatformData;
+class SimpleFontData;
+
+// ComplexTextController walks a TextRun and presents each script run in sequence. A
+// TextRun is a sequence of code-points with the same embedding level (i.e. they
+// are all left-to-right or right-to-left). A script run is a subsequence where
+// all the characters have the same script (e.g. Arabic, Thai etc). Shaping is
+// only ever done with script runs since the shapers only know how to deal with
+// a single script.
+//
+// After creating it, the script runs are either iterated backwards or forwards.
+// It defaults to backwards for RTL and forwards otherwise (which matches the
+// presentation order), however you can set it with |setBackwardsIteration|.
+//
+// Once you have setup the object, call |nextScriptRun| to get the first script
+// run. This will return false when the iteration is complete. At any time you
+// can call |reset| to start over again.
+class ComplexTextController {
+public:
+ ComplexTextController(const TextRun&, unsigned, const Font*);
+ ~ComplexTextController();
+
+ bool isWordBreak(unsigned);
+ int determineWordBreakSpacing(unsigned);
+ // setPadding sets a number of pixels to be distributed across the TextRun.
+ // WebKit uses this to justify text.
+ void setPadding(int);
+ void reset();
+ void setBackwardsIteration(bool);
+ // Advance to the next script run, returning false when the end of the
+ // TextRun has been reached.
+ bool nextScriptRun();
+ float widthOfFullRun();
+
+ // setWordSpacingAdjustment sets a delta (in pixels) which is applied at
+ // each word break in the TextRun.
+ void setWordSpacingAdjustment(int wordSpacingAdjustment) { m_wordSpacingAdjustment = wordSpacingAdjustment; }
+
+ // setLetterSpacingAdjustment sets an additional number of pixels that is
+ // added to the advance after each output cluster. This matches the behaviour
+ // of WidthIterator::advance.
+ void setLetterSpacingAdjustment(int letterSpacingAdjustment) { m_letterSpacing = letterSpacingAdjustment; }
+ int letterSpacing() const { return m_letterSpacing; }
+
+ // Set the x offset for the next script run. This affects the values in
+ // |xPositions|
+ void setXOffsetToZero() { m_offsetX = 0; }
+ bool rtl() const { return m_run.rtl(); }
+ const uint16_t* glyphs() const { return m_glyphs16; }
+
+ // Return the length of the array returned by |glyphs|
+ const unsigned length() const { return m_item.num_glyphs; }
+
+ // Return the x offset for each of the glyphs. Note that this is translated
+ // by the current x offset and that the x offset is updated for each script
+ // run.
+ const SkScalar* xPositions() const { return m_xPositions; }
+
+ // Get the advances (widths) for each glyph.
+ const HB_Fixed* advances() const { return m_item.advances; }
+
+ // Return the width (in px) of the current script run.
+ const unsigned width() const { return m_pixelWidth; }
+
+ // Return the cluster log for the current script run. For example:
+ // script run: f i a n c é (fi gets ligatured)
+ // log clutrs: 0 0 1 2 3 4
+ // So, for each input code point, the log tells you which output glyph was
+ // generated for it.
+ const unsigned short* logClusters() const { return m_item.log_clusters; }
+
+ // return the number of code points in the current script run
+ const unsigned numCodePoints() const { return m_numCodePoints; }
+
+ const FontPlatformData* fontPlatformDataForScriptRun() { return reinterpret_cast<FontPlatformData*>(m_item.font->userData); }
+
+private:
+ void setupFontForScriptRun();
+ HB_FontRec* allocHarfbuzzFont();
+ void deleteGlyphArrays();
+ void createGlyphArrays(int);
+ void resetGlyphArrays();
+ void shapeGlyphs();
+ void setGlyphXPositions(bool);
+
+ static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length);
+ static const TextRun& getNormalizedTextRun(const TextRun& originalRun, OwnPtr<TextRun>& normalizedRun, OwnArrayPtr<UChar>& normalizedBuffer);
+
+ // This matches the logic in RenderBlock::findNextLineBreak
+ static bool isCodepointSpace(HB_UChar16 c) { return c == ' ' || c == '\t'; }
+
+ const Font* const m_font;
+ const SimpleFontData* m_currentFontData;
+ HB_ShaperItem m_item;
+ uint16_t* m_glyphs16; // A vector of 16-bit glyph ids.
+ SkScalar* m_xPositions; // A vector of x positions for each glyph.
+ ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|.
+ const unsigned m_startingX; // Offset in pixels of the first script run.
+ unsigned m_offsetX; // Offset in pixels to the start of the next script run.
+ unsigned m_pixelWidth; // Width (in px) of the current script run.
+ unsigned m_numCodePoints; // Code points in current script run.
+ unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays.
+
+ OwnPtr<TextRun> m_normalizedRun;
+ OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run.
+ const TextRun& m_run;
+ bool m_iterateBackwards;
+ int m_wordSpacingAdjustment; // delta adjustment (pixels) for each word break.
+ float m_padding; // pixels to be distributed over the line at word breaks.
+ float m_padPerWordBreak; // pixels to be added to each word break.
+ float m_padError; // |m_padPerWordBreak| might have a fractional component.
+ // Since we only add a whole number of padding pixels at
+ // each word break we accumulate error. This is the
+ // number of pixels that we are behind so far.
+ int m_letterSpacing; // pixels to be added after each glyph.
+};
+
+} // namespace WebCore
+
+#endif // ComplexTextControllerLinux_h
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
new file mode 100644
index 0000000..d00faf8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ContentLayerChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
+#include "RenderLayerBacking.h"
+
+#if PLATFORM(SKIA)
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#include "SkColorPriv.h"
+#include "skia/ext/platform_canvas.h"
+#elif PLATFORM(CG)
+#include <CoreGraphics/CGBitmapContext.h>
+#endif
+
+namespace WebCore {
+
+ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_contentShaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ // Shaders for drawing the layer contents.
+ char vertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+#if PLATFORM(SKIA)
+ // Color is in RGBA order.
+ char rgbaFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = texColor * alpha; \n"
+ "} \n";
+#endif
+
+ // Color is in BGRA order.
+ char bgraFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n"
+ "} \n";
+
+#if PLATFORM(SKIA)
+ // Assuming the packing is either Skia default RGBA or Chromium default BGRA.
+ char* fragmentShaderString = SK_B32_SHIFT ? rgbaFragmentShaderString : bgraFragmentShaderString;
+#else
+ char* fragmentShaderString = bgraFragmentShaderString;
+#endif
+ m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString);
+ if (!m_contentShaderProgram) {
+ LOG_ERROR("ContentLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_shaderSamplerLocation = m_context->getUniformLocation(m_contentShaderProgram, "s_texture");
+ m_shaderMatrixLocation = m_context->getUniformLocation(m_contentShaderProgram, "matrix");
+ m_shaderAlphaLocation = m_context->getUniformLocation(m_contentShaderProgram, "alpha");
+ ASSERT(m_shaderSamplerLocation != -1);
+ ASSERT(m_shaderMatrixLocation != -1);
+ ASSERT(m_shaderAlphaLocation != -1);
+
+ m_initialized = true;
+}
+
+ContentLayerChromium::SharedValues::~SharedValues()
+{
+ if (m_contentShaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_contentShaderProgram));
+}
+
+
+PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new ContentLayerChromium(owner));
+}
+
+ContentLayerChromium::ContentLayerChromium(GraphicsLayerChromium* owner)
+ : LayerChromium(owner)
+ , m_contentsTexture(0)
+ , m_skipsDraw(false)
+{
+}
+
+ContentLayerChromium::~ContentLayerChromium()
+{
+ cleanupResources();
+}
+
+void ContentLayerChromium::cleanupResources()
+{
+ LayerChromium::cleanupResources();
+ m_contentsTexture.clear();
+}
+
+bool ContentLayerChromium::requiresClippedUpdateRect() const
+{
+ // To avoid allocating excessively large textures, switch into "large layer mode" if
+ // one of the layer's dimensions is larger than 2000 pixels or the size of
+ // surface it's rendering into. This is a temporary measure until layer tiling is implemented.
+ static const int maxLayerSize = 2000;
+ return (m_bounds.width() > max(maxLayerSize, m_targetRenderSurface->contentRect().width())
+ || m_bounds.height() > max(maxLayerSize, m_targetRenderSurface->contentRect().height())
+ || !layerRenderer()->checkTextureSize(m_bounds));
+}
+
+void ContentLayerChromium::updateContentsIfDirty()
+{
+ RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
+ if (!backing || backing->paintingGoesToWindow())
+ return;
+
+ ASSERT(drawsContent());
+
+ ASSERT(layerRenderer());
+
+ void* pixels = 0;
+ IntRect dirtyRect;
+ IntRect updateRect;
+ IntSize requiredTextureSize;
+ IntSize bitmapSize;
+ IntRect boundsRect(IntPoint(0, 0), m_bounds);
+
+ // FIXME: Remove this test when tiled layers are implemented.
+ if (requiresClippedUpdateRect()) {
+ // A layer with 3D transforms could require an arbitrarily large number
+ // of texels to be repainted, so ignore these layers until tiling is
+ // implemented.
+ if (!drawTransform().isIdentityOrTranslation()) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ // Calculate the region of this layer that is currently visible.
+ const IntRect clipRect = m_targetRenderSurface->contentRect();
+
+ TransformationMatrix layerOriginTransform = drawTransform();
+ layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0);
+
+ // For now we apply the large layer treatment only for layers that are either untransformed
+ // or are purely translated. Their matrix is expected to be invertible.
+ ASSERT(layerOriginTransform.isInvertible());
+
+ TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
+ IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect);
+ visibleRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height()));
+
+ // For normal layers, the center of the texture corresponds with the center of the layer.
+ // In large layers the center of the texture is the center of the visible region so we have
+ // to keep track of the offset in order to render correctly.
+ IntRect visibleRectInSurfaceCoords = layerOriginTransform.mapRect(visibleRectInLayerCoords);
+ m_layerCenterInSurfaceCoords = FloatRect(visibleRectInSurfaceCoords).center();
+
+ // If this is still too large to render, then skip the layer completely.
+ if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ // If the visible portion of the layer is different from the last upload, or if our backing
+ // texture has been evicted, then the whole layer is considered dirty.
+ if (visibleRectInLayerCoords != m_visibleRectInLayerCoords || !m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA))
+ m_dirtyRect = boundsRect;
+ m_visibleRectInLayerCoords = visibleRectInLayerCoords;
+
+ // Calculate the portion of the dirty rectangle that is visible. m_dirtyRect is in layer space.
+ IntRect visibleDirtyRectInLayerSpace = enclosingIntRect(m_dirtyRect);
+ visibleDirtyRectInLayerSpace.intersect(visibleRectInLayerCoords);
+
+ // What the rectangles mean:
+ // dirtyRect: The region of this layer that will be updated.
+ // updateRect: The region of the layer's texture that will be uploaded into.
+ // requiredTextureSize: is the required size of this layer's texture.
+ dirtyRect = visibleDirtyRectInLayerSpace;
+ updateRect = dirtyRect;
+ IntSize visibleRectOffsetInLayerCoords(visibleRectInLayerCoords.x(), visibleRectInLayerCoords.y());
+ updateRect.move(-visibleRectOffsetInLayerCoords);
+ requiredTextureSize = visibleRectInLayerCoords.size();
+ } else {
+ dirtyRect = IntRect(m_dirtyRect);
+ requiredTextureSize = m_bounds;
+ // If the texture needs to be reallocated then we must redraw the entire
+ // contents of the layer.
+ if (!m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA))
+ dirtyRect = boundsRect;
+ else {
+ // Clip the dirtyRect to the size of the layer to avoid drawing
+ // outside the bounds of the backing texture.
+ dirtyRect.intersect(boundsRect);
+ }
+ updateRect = dirtyRect;
+ }
+
+ if (dirtyRect.isEmpty())
+ return;
+
+#if PLATFORM(SKIA)
+ const SkBitmap* skiaBitmap = 0;
+ OwnPtr<skia::PlatformCanvas> canvas;
+ OwnPtr<PlatformContextSkia> skiaContext;
+ OwnPtr<GraphicsContext> graphicsContext;
+
+ canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false));
+ skiaContext.set(new PlatformContextSkia(canvas.get()));
+
+ // This is needed to get text to show up correctly.
+ // FIXME: Does this take us down a very slow text rendering path?
+ skiaContext->setDrawingToImageBuffer(true);
+
+ graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));
+
+ // Bring the canvas into the coordinate system of the paint rect.
+ canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y()));
+
+ m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect);
+ const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
+ skiaBitmap = &bitmap;
+ ASSERT(skiaBitmap);
+
+ SkAutoLockPixels lock(*skiaBitmap);
+ SkBitmap::Config skiaConfig = skiaBitmap->config();
+ // FIXME: do we need to support more image configurations?
+ if (skiaConfig == SkBitmap::kARGB_8888_Config) {
+ pixels = skiaBitmap->getPixels();
+ bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
+ }
+#elif PLATFORM(CG)
+ Vector<uint8_t> tempVector;
+ int rowBytes = 4 * dirtyRect.width();
+ tempVector.resize(rowBytes * dirtyRect.height());
+ memset(tempVector.data(), 0, tempVector.size());
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(),
+ dirtyRect.width(), dirtyRect.height(), 8, rowBytes,
+ colorSpace.get(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height());
+ CGContextScaleCTM(contextCG.get(), 1, -1);
+
+ GraphicsContext graphicsContext(contextCG.get());
+
+ // Translate the graphics context into the coordinate system of the dirty rect.
+ graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y());
+
+ m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect);
+
+ pixels = tempVector.data();
+ bitmapSize = dirtyRect.size();
+#else
+#error "Need to implement for your platform."
+#endif
+
+ if (pixels)
+ updateTextureRect(pixels, requiredTextureSize, updateRect);
+}
+
+void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect)
+{
+ if (!pixels)
+ return;
+
+ GraphicsContext3D* context = layerRendererContext();
+ if (!m_contentsTexture)
+ m_contentsTexture = LayerTexture::create(context, layerRenderer()->textureManager());
+
+ if (!m_contentsTexture->reserve(requiredTextureSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ return;
+ }
+
+ m_contentsTexture->bindTexture();
+
+ GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+
+ m_dirtyRect.setSize(FloatSize());
+ // Large layers always stay dirty, because they need to update when the content rect changes.
+ m_contentsDirty = requiresClippedUpdateRect();
+}
+
+void ContentLayerChromium::draw()
+{
+ if (m_skipsDraw)
+ return;
+
+ ASSERT(layerRenderer());
+
+ const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues();
+ ASSERT(sv && sv->initialized());
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ m_contentsTexture->bindTexture();
+ layerRenderer()->useShader(sv->contentShaderProgram());
+ GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
+
+ if (requiresClippedUpdateRect()) {
+ float m43 = drawTransform().m43();
+ TransformationMatrix transform;
+ transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43);
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
+ transform, m_visibleRectInLayerCoords.width(),
+ m_visibleRectInLayerCoords.height(), drawOpacity(),
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+ } else {
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
+ drawTransform(), m_bounds.width(), m_bounds.height(),
+ drawOpacity(), sv->shaderMatrixLocation(),
+ sv->shaderAlphaLocation());
+ }
+ m_contentsTexture->unreserve();
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
new file mode 100644
index 0000000..dc1630b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef ContentLayerChromium_h
+#define ContentLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+#include "TextureManager.h"
+
+namespace WebCore {
+
+class LayerTexture;
+
+// A Layer that requires a GraphicsContext to render its contents.
+class ContentLayerChromium : public LayerChromium {
+ friend class LayerRendererChromium;
+public:
+ static PassRefPtr<ContentLayerChromium> create(GraphicsLayerChromium* owner = 0);
+
+ virtual ~ContentLayerChromium();
+
+ virtual void updateContentsIfDirty();
+ virtual void draw();
+ virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
+
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+
+ unsigned contentShaderProgram() const { return m_contentShaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ int initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+ unsigned m_contentShaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ int m_initialized;
+ };
+
+protected:
+ explicit ContentLayerChromium(GraphicsLayerChromium* owner);
+
+ void updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect);
+
+ virtual void cleanupResources();
+ bool requiresClippedUpdateRect() const;
+
+ OwnPtr<LayerTexture> m_contentsTexture;
+ bool m_skipsDraw;
+
+private:
+
+ IntRect m_visibleRectInLayerCoords;
+ FloatPoint m_layerCenterInSurfaceCoords;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h
new file mode 100644
index 0000000..e1fb740
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CrossProcessFontLoading_h
+#define CrossProcessFontLoading_h
+
+#import <wtf/RefCounted.h>
+#import <wtf/RetainPtr.h>
+
+typedef struct CGFont* CGFontRef;
+typedef UInt32 ATSFontContainerRef;
+typedef UInt32 ATSFontRef;
+
+namespace WebCore {
+
+// MemoryActivatedFont encapsulates a font loaded from another process and
+// activated from memory.
+//
+// Responsibilities:
+// * Holder for the CGFontRef & ATSFontRef belonging to the activated font.
+// * Responsible for unloading the font container when done.
+//
+// Memory Management:
+// The class is reference counted, with each instance of FontPlatformData that
+// uses this class holding a reference to it.
+// Entries are kept track of internally in a hash to allow quick lookup
+// of existing instances for reuse:
+// - fontCacheBySrcFontContainerRef() - key is the ATSFontContainerRef
+// corresponding to the *original in-process NSFont* whose loading was blocked
+// by the sandbox.
+// This is needed to allow lookup of a pre-existing MemoryActivatedFont when
+// creating a new FontPlatformData object.
+//
+// Assumptions:
+// This code assumes that an ATSFontRef is a unique identifier tied to an
+// activated font. i.e. After we activate a font, its ATSFontRef doesn't
+// change.
+// It also assumes that the ATSFoncontainerRef for two in-memory NSFonts that
+// correspond to the same on-disk font file are always the same and don't change
+// with time.
+//
+// Flushing caches:
+// When the system notifies us of a system font cache flush, all FontDataCache
+// objects are destroyed. This should in turn dereference all
+// MemoryActivatedFonts and thus unload all in-memory fonts.
+class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> {
+public:
+ // Use to create a new object, see docs on constructor below.
+ static PassRefPtr<MemoryActivatedFont> create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
+ ~MemoryActivatedFont();
+
+ // Get cached CGFontRef corresponding to the in-memory font.
+ CGFontRef cgFont() { return m_cgFont.get(); }
+
+ // Get cached ATSFontRef corresponding to the in-memory font.
+ ATSFontRef atsFontRef() { return m_atsFontRef; }
+
+private:
+ // srcFontRef - ATSFontRef belonging to the NSFont object that failed to
+ // load in-process.
+ // container - a font container corresponding to an identical font that
+ // we loaded cross-process.
+ MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
+
+ ATSFontContainerRef m_fontContainer;
+ WTF::RetainPtr<CGFontRef> m_cgFont;
+ ATSFontRef m_atsFontRef;
+ ATSFontContainerRef m_srcFontContainerRef;
+};
+
+} // namespace WebCore
+
+#endif // CrossProcessFontLoading_h
diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
new file mode 100644
index 0000000..72e3369
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
@@ -0,0 +1,210 @@
+/*
+ * This file is part of the internal font implementation.
+ *
+ * Copyright (c) 2010 Google Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+// This file provides additional functionality to the Mac FontPlatformData class
+// defined in WebCore/platform/cocoa/FontPlatformDataCocoa.mm .
+// Because we want to support loading fonts between processes in the face of
+// font loading being blocked by the sandbox, we need a mechnasim to both
+// do the loading of in-memory fonts and keep track of them.
+
+#import "config.h"
+#import "CrossProcessFontLoading.h"
+
+#import "../graphics/cocoa/FontPlatformData.h"
+#import "ChromiumBridge.h"
+#import <AppKit/NSFont.h>
+#import <wtf/HashMap.h>
+
+namespace WebCore {
+
+namespace {
+
+typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
+
+// On 10.5, font loading is not blocked by the sandbox and thus there is no
+// need for the cross-process font loading mechanim.
+// On system versions >=10.6 cross-process font loading is required.
+bool OutOfProcessFontLoadingEnabled()
+{
+ static SInt32 systemVersion = 0;
+ if (!systemVersion) {
+ if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr)
+ return false;
+ }
+
+ return systemVersion >= 0x1060;
+}
+
+FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef()
+{
+ DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ());
+ return srcFontRefCache;
+}
+
+ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont)
+{
+ ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0);
+ if (!fontRef)
+ return kATSFontContainerRefUnspecified;
+ ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified;
+ if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr)
+ return kATSFontContainerRefUnspecified;
+ return fontContainer;
+}
+
+// The only way we can tell that an in-process font has failed to load
+// is if CTFontCopyGraphicsFont() returns the LastResort font.
+bool isLastResortFont(CGFontRef cgFont)
+{
+ NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont);
+ return [fontName isEqualToString:@"LastResort"];
+}
+
+// Given an in-process font which has failed to load, return a
+// MemoryActivatedFont* corresponding to an in-memory representation of the
+// same font loaded from the browser process.
+// On failure this function returns a PassRefPtr pointing to 0.
+PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont)
+{
+ ATSFontContainerRef container;
+ // Send cross-process request to load font.
+ if (!ChromiumBridge::loadFont(nsFont, &container))
+ return 0;
+
+ ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont);
+ if (!srcFontContainerRef) {
+ ATSFontDeactivate(container, 0, kATSOptionFlagsDefault);
+ return 0;
+ }
+
+ PassRefPtr<MemoryActivatedFont> font = adoptRef(fontCacheBySrcFontContainerRef().get(srcFontContainerRef));
+ if (font.get())
+ return font;
+
+ return MemoryActivatedFont::create(srcFontContainerRef, container);
+}
+
+} // namespace
+
+PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
+{
+ MemoryActivatedFont* font = new MemoryActivatedFont(srcFontContainerRef, container);
+ if (!font->cgFont()) // Object construction failed.
+ {
+ delete font;
+ return 0;
+ }
+ return adoptRef(font);
+}
+
+MemoryActivatedFont::MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
+ : m_fontContainer(container)
+ , m_atsFontRef(kATSFontRefUnspecified)
+ , m_srcFontContainerRef(srcFontContainerRef)
+{
+ if (!container)
+ return;
+
+ // Count the number of fonts in the container.
+ ItemCount fontCount = 0;
+ OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0, 0, &fontCount);
+ if (err != noErr || fontCount < 1)
+ return;
+
+ // For now always assume that we want the first font in the container.
+ ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef, 0);
+
+ if (!m_atsFontRef)
+ return;
+
+ // Cache CGFont representation of the font.
+ m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef));
+
+ if (!m_cgFont.get())
+ return;
+
+ // Add ourselves to cache.
+ fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this);
+}
+
+// Destructor - Unload font container from memory and remove ourselves
+// from cache.
+MemoryActivatedFont::~MemoryActivatedFont()
+{
+ if (m_cgFont.get()) {
+ // First remove ourselves from the caches.
+ ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef));
+
+ fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef);
+
+ // Make sure the CGFont is destroyed before its font container.
+ m_cgFont.releaseRef();
+ }
+
+ if (m_fontContainer != kATSFontContainerRefUnspecified)
+ ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault);
+}
+
+// Given an NSFont, try to load a representation of that font into the cgFont
+// parameter. If loading is blocked by the sandbox, the font may be loaded
+// cross-process.
+// If sandbox loading also fails, a fallback font is loaded.
+//
+// Considerations:
+// * cgFont must be CFRelease()ed by the caller when done.
+//
+// Parameters:
+// * nsFont - The font we wish to load.
+// * fontSize - point size of the font we wish to load.
+// * outNSFont - The font that was actually loaded, may be different from nsFont
+// if a fallback font was used.
+// * cgFont - on output this contains the CGFontRef corresponding to the NSFont
+// that was picked in the end. The caller is responsible for calling
+// CFRelease() on this parameter when done with it.
+// * fontID - on output, the ID corresponding to nsFont.
+void FontPlatformData::loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont)
+{
+ outNSFont = nsFont;
+ cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0);
+ if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortFont(cgFont)) {
+ // Release old CGFontRef since it points at the LastResort font which we don't want.
+ CFRelease(cgFont);
+ cgFont = 0;
+
+ // Font loading was blocked by the Sandbox.
+ m_inMemoryFont = loadFontFromBrowserProcess(outNSFont);
+ if (m_inMemoryFont.get()) {
+ cgFont = m_inMemoryFont->cgFont();
+
+ // Need to add an extra retain so output semantics of this function
+ // are consistent.
+ CFRetain(cgFont);
+ } else {
+ // If we still can't load the font, then return Times,
+ // rather than the LastResort font.
+ outNSFont = [NSFont fontWithName:@"Times" size:fontSize];
+ cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0);
+ }
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
new file mode 100644
index 0000000..507c227
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "DrawingBuffer.h"
+
+#include "Extensions3DChromium.h"
+#include "GraphicsContext3D.h"
+#include "SharedGraphicsContext3D.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "Canvas2DLayerChromium.h"
+#endif
+
+namespace WebCore {
+
+struct DrawingBufferInternal {
+ unsigned offscreenColorTexture;
+#if USE(ACCELERATED_COMPOSITING)
+ RefPtr<Canvas2DLayerChromium> platformLayer;
+#endif
+};
+
+static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize& size)
+{
+ unsigned offscreenColorTexture = context->createTexture();
+ if (!offscreenColorTexture)
+ return 0;
+
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, offscreenColorTexture);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
+ context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, offscreenColorTexture, 0);
+
+ return offscreenColorTexture;
+}
+
+
+DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size)
+ : m_context(context)
+ , m_size(size)
+ , m_fbo(0)
+ , m_colorBuffer(0)
+ , m_depthStencilBuffer(0)
+ , m_multisampleFBO(0)
+ , m_multisampleColorBuffer(0)
+ , m_multisampleDepthStencilBuffer(0)
+ , m_internal(new DrawingBufferInternal)
+{
+ if (!m_context->getExtensions()->supports("GL_CHROMIUM_copy_texture_to_parent_texture")) {
+ m_context.clear();
+ return;
+ }
+ m_fbo = context->createFramebuffer();
+ context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ m_colorBuffer = generateColorTexture(context, size);
+}
+
+DrawingBuffer::~DrawingBuffer()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_internal->platformLayer)
+ m_internal->platformLayer->setDrawingBuffer(0);
+#endif
+
+ if (!m_context)
+ return;
+
+ m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
+ m_context->deleteTexture(m_colorBuffer);
+
+ clear();
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+void DrawingBuffer::publishToPlatformLayer()
+{
+ if (!m_context)
+ return;
+
+ if (m_callback)
+ m_callback->willPublish();
+ unsigned parentTexture = m_internal->platformLayer->textureId();
+ // FIXME: We do the copy in the canvas' (child) context so that it executes in the correct order relative to
+ // other commands in the child context. This ensures that the parent texture always contains a complete
+ // frame and not some intermediate result. However, there is no synchronization to ensure that this copy
+ // happens before the compositor draws. This means we might draw stale frames sometimes. Ideally this
+ // would insert a fence into the child command stream that the compositor could wait for.
+ m_context->makeContextCurrent();
+ static_cast<Extensions3DChromium*>(m_context->getExtensions())->copyTextureToParentTextureCHROMIUM(m_colorBuffer, parentTexture);
+ m_context->flush();
+}
+#endif
+
+void DrawingBuffer::didReset()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_internal->platformLayer)
+ m_internal->platformLayer->setTextureChanged();
+#endif
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+PlatformLayer* DrawingBuffer::platformLayer()
+{
+ if (!m_internal->platformLayer)
+ m_internal->platformLayer = Canvas2DLayerChromium::create(this, 0);
+ return m_internal->platformLayer.get();
+}
+#endif
+
+Platform3DObject DrawingBuffer::platformColorBuffer() const
+{
+ return m_colorBuffer;
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
new file mode 100644
index 0000000..d120424
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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 Extensions3DChromium_h
+#define Extensions3DChromium_h
+
+#include "Extensions3D.h"
+
+namespace WebCore {
+
+class GraphicsContext3DInternal;
+
+class Extensions3DChromium : public Extensions3D {
+public:
+ virtual ~Extensions3DChromium();
+
+ // Supported extensions:
+ // GL_CHROMIUM_resource_safe : indicating that textures/renderbuffers are always initialized before read/write.
+ // GL_CHROMIUM_strict_attribs : indicating a GL error is generated for out-of-bounds buffer accesses.
+
+ // Extensions3D methods.
+ virtual bool supports(const String&);
+ virtual void ensureEnabled(const String&);
+ virtual int getGraphicsResetStatusARB();
+ virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) { }
+ virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) { }
+
+ enum {
+ // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object)
+ READ_ONLY = 0x88B8,
+ WRITE_ONLY = 0x88B9
+ };
+
+ // GL_CHROMIUM_map_sub
+ void* mapBufferSubDataCHROMIUM(unsigned target, int offset, int size, unsigned access);
+ void unmapBufferSubDataCHROMIUM(const void*);
+ void* mapTexSubImage2DCHROMIUM(unsigned target, int level, int xoffset, int yoffset, int width, int height, unsigned format, unsigned type, unsigned access);
+ void unmapTexSubImage2DCHROMIUM(const void*);
+
+ // GL_CHROMIUM_copy_texture_to_parent_texture
+ void copyTextureToParentTextureCHROMIUM(unsigned texture, unsigned parentTexture);
+
+private:
+ // Instances of this class are strictly owned by the GraphicsContext3D implementation and do not
+ // need to be instantiated by any other code.
+ friend class GraphicsContext3DInternal;
+ explicit Extensions3DChromium(GraphicsContext3DInternal*);
+
+ // Weak pointer back to GraphicsContext3DInternal
+ GraphicsContext3DInternal* m_internal;
+};
+
+} // namespace WebCore
+
+#endif // Extensions3DChromium_h
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
new file mode 100644
index 0000000..2c79815
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontCache.h"
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "FontUtilsChromiumWin.h"
+#include "HashMap.h"
+#include "HashSet.h"
+#include "SimpleFontData.h"
+#include <unicode/uniset.h>
+#include <wtf/text/StringHash.h>
+
+#include <windows.h>
+#include <objidl.h>
+#include <mlang.h>
+
+using std::min;
+
+namespace WebCore
+{
+
+// FIXME: consider adding to WebKit String class
+static bool charactersAreAllASCII(const String& s)
+{
+ return WTF::charactersAreAllASCII(s.characters(), s.length());
+}
+
+// When asked for a CJK font with a native name under a non-CJK locale or
+// asked for a CJK font with a Romanized name under a CJK locale,
+// |GetTextFace| (after |CreateFont*|) returns a 'bogus' value (e.g. Arial).
+// This is not consistent with what MSDN says !!
+// Therefore, before we call |CreateFont*|, we have to map a Romanized name to
+// the corresponding native name under a CJK locale and vice versa
+// under a non-CJK locale.
+// See the corresponding gecko bugs at
+// https://bugzilla.mozilla.org/show_bug.cgi?id=373952
+// https://bugzilla.mozilla.org/show_bug.cgi?id=231426
+static bool LookupAltName(const String& name, String& altName)
+{
+ struct FontCodepage {
+ WCHAR* name;
+ int codePage;
+ };
+
+ struct NamePair {
+ WCHAR* name;
+ FontCodepage altNameCodepage;
+ };
+
+ const int japaneseCodepage = 932;
+ const int simplifiedChineseCodepage = 936;
+ const int koreanCodepage = 949;
+ const int traditionalChineseCodepage = 950;
+
+ // FIXME(jungshik) : This list probably covers 99% of cases.
+ // To cover the remaining 1% and cut down the file size,
+ // consider accessing 'NAME' table of a truetype font
+ // using |GetFontData| and caching the mapping.
+ // In the table below, the ASCII keys are all lower-cased for
+ // case-insensitive matching.
+ static const NamePair namePairs[] = {
+ // MS Pゴシック, MS PGothic
+ {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", {L"MS PGothic", japaneseCodepage}},
+ {L"ms pgothic", {L"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
+ // MS P明朝, MS PMincho
+ {L"\xFF2D\xFF33 \xFF30\x660E\x671D", {L"MS PMincho", japaneseCodepage}},
+ {L"ms pmincho", {L"\xFF2D\xFF33 \xFF30\x660E\x671D", japaneseCodepage}},
+ // MSゴシック, MS Gothic
+ {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", {L"MS Gothic", japaneseCodepage}},
+ {L"ms gothic", {L"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF", japaneseCodepage}},
+ // MS 明朝, MS Mincho
+ {L"\xFF2D\xFF33 \x660E\x671D", {L"MS Mincho", japaneseCodepage}},
+ {L"ms mincho", {L"\xFF2D\xFF33 \x660E\x671D", japaneseCodepage}},
+ // メイリオ, Meiryo
+ {L"\x30E1\x30A4\x30EA\x30AA", {L"Meiryo", japaneseCodepage}},
+ {L"meiryo", {L"\x30E1\x30A4\x30EA\x30AA", japaneseCodepage}},
+ // 바탕, Batang
+ {L"\xBC14\xD0D5", {L"Batang", koreanCodepage}},
+ {L"batang", {L"\xBC14\xD0D5", koreanCodepage}},
+ // 바탕체, Batangche
+ {L"\xBC14\xD0D5\xCCB4", {L"Batangche", koreanCodepage}},
+ {L"batangche", {L"\xBC14\xD0D5\xCCB4", koreanCodepage}},
+ // 굴림, Gulim
+ {L"\xAD74\xB9BC", {L"Gulim", koreanCodepage}},
+ {L"gulim", {L"\xAD74\xB9BC", koreanCodepage}},
+ // 굴림체, Gulimche
+ {L"\xAD74\xB9BC\xCCB4", {L"Gulimche", koreanCodepage}},
+ {L"gulimche", {L"\xAD74\xB9BC\xCCB4", koreanCodepage}},
+ // 돋움, Dotum
+ {L"\xB3CB\xC6C0", {L"Dotum", koreanCodepage}},
+ {L"dotum", {L"\xB3CB\xC6C0", koreanCodepage}},
+ // 돋움체, Dotumche
+ {L"\xB3CB\xC6C0\xCCB4", {L"Dotumche", koreanCodepage}},
+ {L"dotumche", {L"\xB3CB\xC6C0\xCCB4", koreanCodepage}},
+ // 궁서, Gungsuh
+ {L"\xAD81\xC11C", {L"Gungsuh", koreanCodepage}},
+ {L"gungsuh", {L"\xAD81\xC11C", koreanCodepage}},
+ // 궁서체, Gungsuhche
+ {L"\xAD81\xC11C\xCCB4", {L"Gungsuhche", koreanCodepage}},
+ {L"gungsuhche", {L"\xAD81\xC11C\xCCB4", koreanCodepage}},
+ // 맑은 고딕, Malgun Gothic
+ {L"\xB9D1\xC740 \xACE0\xB515", {L"Malgun Gothic", koreanCodepage}},
+ {L"malgun gothic", {L"\xB9D1\xC740 \xACE0\xB515", koreanCodepage}},
+ // 宋体, SimSun
+ {L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}},
+ {L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}},
+ // 宋体-ExtB, SimSun-ExtB
+ {L"\x5B8B\x4F53-ExtB", {L"SimSun-ExtB", simplifiedChineseCodepage}},
+ {L"simsun-extb", {L"\x5B8B\x4F53-extb", simplifiedChineseCodepage}},
+ // 黑体, SimHei
+ {L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}},
+ {L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}},
+ // 新宋体, NSimSun
+ {L"\x65B0\x5B8B\x4F53", {L"NSimSun", simplifiedChineseCodepage}},
+ {L"nsimsun", {L"\x65B0\x5B8B\x4F53", simplifiedChineseCodepage}},
+ // 微软雅黑, Microsoft Yahei
+ {L"\x5FAE\x8F6F\x96C5\x9ED1", {L"Microsoft Yahei", simplifiedChineseCodepage}},
+ {L"microsoft yahei", {L"\x5FAE\x8F6F\x96C5\x9ED1", simplifiedChineseCodepage}},
+ // 仿宋, FangSong
+ {L"\x4EFF\x5B8B", {L"FangSong", simplifiedChineseCodepage}},
+ {L"fangsong", {L"\x4EFF\x5B8B", simplifiedChineseCodepage}},
+ // 楷体, KaiTi
+ {L"\x6977\x4F53", {L"KaiTi", simplifiedChineseCodepage}},
+ {L"kaiti", {L"\x6977\x4F53", simplifiedChineseCodepage}},
+ // 仿宋_GB2312, FangSong_GB2312
+ {L"\x4EFF\x5B8B_GB2312", {L"FangSong_GB2312", simplifiedChineseCodepage}},
+ {L"fangsong_gb2312", {L"\x4EFF\x5B8B_gb2312", simplifiedChineseCodepage}},
+ // 楷体_GB2312, KaiTi_GB2312
+ {L"\x6977\x4F53", {L"KaiTi_GB2312", simplifiedChineseCodepage}},
+ {L"kaiti_gb2312", {L"\x6977\x4F53_gb2312", simplifiedChineseCodepage}},
+ // 新細明體, PMingLiu
+ {L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}},
+ {L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
+ // 新細明體-ExtB, PMingLiu-ExtB
+ {L"\x65B0\x7D30\x660E\x9AD4-ExtB", {L"PMingLiu-ExtB", traditionalChineseCodepage}},
+ {L"pmingliu-extb", {L"\x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
+ // 細明體, MingLiu
+ {L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}},
+ {L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}},
+ // 細明體-ExtB, MingLiu-ExtB
+ {L"\x7D30\x660E\x9AD4-ExtB", {L"MingLiu-ExtB", traditionalChineseCodepage}},
+ {L"mingliu-extb", {L"x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}},
+ // 微軟正黑體, Microsoft JhengHei
+ {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}},
+ {L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}},
+ // 標楷體, DFKai-SB
+ {L"\x6A19\x6977\x9AD4", {L"DFKai-SB", traditionalChineseCodepage}},
+ {L"dfkai-sb", {L"\x6A19\x6977\x9AD4", traditionalChineseCodepage}},
+ // WenQuanYi Zen Hei
+ {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", {L"WenQuanYi Zen Hei", traditionalChineseCodepage}},
+ {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a5b\x6b63\x9ed1", traditionalChineseCodepage}},
+ // WenQuanYi Zen Hei
+ {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", {L"WenQuanYi Zen Hei", simplifiedChineseCodepage}},
+ {L"wenquanyi zen hei", {L"\x6587\x6cc9\x9a7f\x6b63\x9ed1", simplifiedChineseCodepage}},
+ // AR PL ShanHeiSun Uni,
+ {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
+ {L"AR PL ShanHeiSun Uni", traditionalChineseCodepage}},
+ {L"ar pl shanheisun uni",
+ {L"\x6587\x9f0e\x0050\x004c\x7d30\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", traditionalChineseCodepage}},
+ // AR PL ShanHeiSun Uni,
+ {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069",
+ {L"AR PL ShanHeiSun Uni", simplifiedChineseCodepage}},
+ {L"ar pl shanheisun uni",
+ {L"\x6587\x9f0e\x0050\x004c\x7ec6\x4e0a\x6d77\x5b8b\x0055\x006e\x0069", simplifiedChineseCodepage}},
+ // AR PL ZenKai Uni
+ // Traditional Chinese and Simplified Chinese names are
+ // identical.
+ {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", traditionalChineseCodepage}},
+ {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", traditionalChineseCodepage}},
+ {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", {L"AR PL ZenKai Uni", simplifiedChineseCodepage}},
+ {L"ar pl zenkai uni", {L"\x6587\x0050\x004C\x4E2D\x6977\x0055\x006E\x0069", simplifiedChineseCodepage}},
+ };
+
+ typedef HashMap<String, const FontCodepage*> NameMap;
+ static NameMap* fontNameMap = 0;
+
+ if (!fontNameMap) {
+ fontNameMap = new NameMap;
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(namePairs); ++i)
+ fontNameMap->set(String(namePairs[i].name), &(namePairs[i].altNameCodepage));
+ }
+
+ bool isAscii = false;
+ String n;
+ // use |lower| only for ASCII names
+ // For non-ASCII names, we don't want to invoke an expensive
+ // and unnecessary |lower|.
+ if (charactersAreAllASCII(name)) {
+ isAscii = true;
+ n = name.lower();
+ } else
+ n = name;
+
+ NameMap::iterator iter = fontNameMap->find(n);
+ if (iter == fontNameMap->end())
+ return false;
+
+ static int systemCp = ::GetACP();
+ int fontCp = iter->second->codePage;
+
+ if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) {
+ altName = String(iter->second->name);
+ return true;
+ }
+
+ return false;
+}
+
+static HFONT createFontIndirectAndGetWinName(const String& family, LOGFONT* winfont, String* winName)
+{
+ int len = min(static_cast<int>(family.length()), LF_FACESIZE - 1);
+ memcpy(winfont->lfFaceName, family.characters(), len * sizeof(WORD));
+ winfont->lfFaceName[len] = '\0';
+
+ HFONT hfont = CreateFontIndirect(winfont);
+ if (!hfont)
+ return 0;
+
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
+ WCHAR name[LF_FACESIZE];
+ unsigned resultLength = GetTextFace(dc, LF_FACESIZE, name);
+ if (resultLength > 0)
+ resultLength--; // ignore the null terminator
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ *winName = String(name, resultLength);
+ return hfont;
+}
+
+// This maps font family names to their repertoires of supported Unicode
+// characters. Because it's family names rather than font faces we use
+// as keys, there might be edge cases where one face of a font family
+// has a different repertoire from another face of the same family.
+typedef HashMap<const wchar_t*, icu::UnicodeSet*> FontCmapCache;
+
+static bool fontContainsCharacter(const FontPlatformData* fontData,
+ const wchar_t* family, UChar32 character)
+{
+ // FIXME: For non-BMP characters, GetFontUnicodeRanges is of
+ // no use. We have to read directly from the cmap table of a font.
+ // Return true for now.
+ if (character > 0xFFFF)
+ return true;
+
+ // This cache is just leaked on shutdown.
+ static FontCmapCache* fontCmapCache = 0;
+ if (!fontCmapCache)
+ fontCmapCache = new FontCmapCache;
+
+ HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family);
+ if (it != fontCmapCache->end())
+ return it->second->contains(character);
+
+ HFONT hfont = fontData->hfont();
+ HDC hdc = GetDC(0);
+ HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(hdc, hfont));
+ int count = GetFontUnicodeRanges(hdc, 0);
+ if (count == 0 && ChromiumBridge::ensureFontLoaded(hfont))
+ count = GetFontUnicodeRanges(hdc, 0);
+ if (count == 0) {
+ LOG_ERROR("Unable to get the font unicode range after second attempt");
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+ return true;
+ }
+
+ static Vector<char, 512> glyphsetBuffer;
+ glyphsetBuffer.resize(GetFontUnicodeRanges(hdc, 0));
+ GLYPHSET* glyphset = reinterpret_cast<GLYPHSET*>(glyphsetBuffer.data());
+ // In addition, refering to the OS/2 table and converting the codepage list
+ // to the coverage map might be faster.
+ count = GetFontUnicodeRanges(hdc, glyphset);
+ ASSERT(count > 0);
+ SelectObject(hdc, oldFont);
+ ReleaseDC(0, hdc);
+
+ // FIXME: consider doing either of the following two:
+ // 1) port back ICU 4.0's faster look-up code for UnicodeSet
+ // 2) port Mozilla's CompressedCharMap or gfxSparseBitset
+ unsigned i = 0;
+ icu::UnicodeSet* cmap = new icu::UnicodeSet;
+ while (i < glyphset->cRanges) {
+ WCHAR start = glyphset->ranges[i].wcLow;
+ cmap->add(start, start + glyphset->ranges[i].cGlyphs - 1);
+ i++;
+ }
+ cmap->freeze();
+ // We don't lowercase |family| because all of them are under our control
+ // and they're already lowercased.
+ fontCmapCache->set(family, cmap);
+ return cmap->contains(character);
+}
+
+// Tries the given font and save it |outFontFamilyName| if it succeeds.
+static SimpleFontData* fontDataFromDescriptionAndLogFont(FontCache* fontCache, const FontDescription& fontDescription, const LOGFONT& font, wchar_t* outFontFamilyName)
+{
+ SimpleFontData* fontData = fontCache->getCachedFontData(fontDescription, font.lfFaceName);
+ if (fontData)
+ memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName));
+ return fontData;
+}
+
+static LONG toGDIFontWeight(FontWeight fontWeight)
+{
+ static LONG gdiFontWeights[] = {
+ FW_THIN, // FontWeight100
+ FW_EXTRALIGHT, // FontWeight200
+ FW_LIGHT, // FontWeight300
+ FW_NORMAL, // FontWeight400
+ FW_MEDIUM, // FontWeight500
+ FW_SEMIBOLD, // FontWeight600
+ FW_BOLD, // FontWeight700
+ FW_EXTRABOLD, // FontWeight800
+ FW_HEAVY // FontWeight900
+ };
+ return gdiFontWeights[fontWeight];
+}
+
+static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
+{
+ // The size here looks unusual. The negative number is intentional.
+ // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be
+ // some kind of artifact of their CG backend, or something.
+ winfont->lfHeight = -fontDescription.computedPixelSize();
+ 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 = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
+ winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ winfont->lfItalic = fontDescription.italic();
+ winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
+}
+
+struct TraitsInFamilyProcData {
+ TraitsInFamilyProcData(const AtomicString& familyName)
+ : m_familyName(familyName)
+ {
+ }
+
+ const AtomicString& m_familyName;
+ HashSet<unsigned> m_traitsMasks;
+};
+
+static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
+{
+ TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
+
+ unsigned traitsMask = 0;
+ traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
+ traitsMask |= FontVariantNormalMask;
+ LONG weight = logFont->lfWeight;
+ traitsMask |= weight == FW_THIN ? FontWeight100Mask :
+ weight == FW_EXTRALIGHT ? FontWeight200Mask :
+ weight == FW_LIGHT ? FontWeight300Mask :
+ weight == FW_NORMAL ? FontWeight400Mask :
+ weight == FW_MEDIUM ? FontWeight500Mask :
+ weight == FW_SEMIBOLD ? FontWeight600Mask :
+ weight == FW_BOLD ? FontWeight700Mask :
+ weight == FW_EXTRABOLD ? FontWeight800Mask :
+ FontWeight900Mask;
+ procData->m_traitsMasks.add(traitsMask);
+ return 1;
+}
+
+void FontCache::platformInit()
+{
+ // Not needed on Windows.
+}
+
+// Given the desired base font, this will create a SimpleFontData for a specific
+// font that can be used to render the given range of characters.
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
+{
+ // FIXME: Consider passing fontDescription.dominantScript()
+ // to GetFallbackFamily here.
+ FontDescription fontDescription = font.fontDescription();
+ UChar32 c;
+ UScriptCode script;
+ const wchar_t* family = getFallbackFamily(characters, length,
+ fontDescription.genericFamily(), &c, &script);
+ FontPlatformData* data = 0;
+ if (family)
+ data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)), false);
+
+ // Last resort font list : PanUnicode. CJK fonts have a pretty
+ // large repertoire. Eventually, we need to scan all the fonts
+ // on the system to have a Firefox-like coverage.
+ // Make sure that all of them are lowercased.
+ const static wchar_t* const cjkFonts[] = {
+ L"arial unicode ms",
+ L"ms pgothic",
+ L"simsun",
+ L"gulim",
+ L"pmingliu",
+ L"wenquanyi zen hei", // partial CJK Ext. A coverage but more
+ // widely known to Chinese users.
+ L"ar pl shanheisun uni",
+ L"ar pl zenkai uni",
+ L"han nom a", // Complete CJK Ext. A coverage
+ L"code2000", // Complete CJK Ext. A coverage
+ // CJK Ext. B fonts are not listed here because it's of no use
+ // with our current non-BMP character handling because we use
+ // Uniscribe for it and that code path does not go through here.
+ };
+
+ const static wchar_t* const commonFonts[] = {
+ L"tahoma",
+ L"arial unicode ms",
+ L"lucida sans unicode",
+ L"microsoft sans serif",
+ L"palatino linotype",
+ // Six fonts below (and code2000 at the end) are not from MS, but
+ // once installed, cover a very wide range of characters.
+ L"dejavu serif",
+ L"dejavu sasns",
+ L"freeserif",
+ L"freesans",
+ L"gentium",
+ L"gentiumalt",
+ L"ms pgothic",
+ L"simsun",
+ L"gulim",
+ L"pmingliu",
+ L"code2000",
+ };
+
+ const wchar_t* const* panUniFonts = 0;
+ int numFonts = 0;
+ if (script == USCRIPT_HAN) {
+ panUniFonts = cjkFonts;
+ numFonts = WTF_ARRAY_LENGTH(cjkFonts);
+ } else {
+ panUniFonts = commonFonts;
+ numFonts = WTF_ARRAY_LENGTH(commonFonts);
+ }
+ // Font returned from GetFallbackFamily may not cover |characters|
+ // because it's based on script to font mapping. This problem is
+ // critical enough for non-Latin scripts (especially Han) to
+ // warrant an additional (real coverage) check with fontCotainsCharacter.
+ int i;
+ for (i = 0; (!data || !fontContainsCharacter(data, family, c)) && i < numFonts; ++i) {
+ family = panUniFonts[i];
+ data = getCachedFontPlatformData(font.fontDescription(), AtomicString(family, wcslen(family)));
+ }
+ // When i-th font (0-base) in |panUniFonts| contains a character and
+ // we get out of the loop, |i| will be |i + 1|. That is, if only the
+ // last font in the array covers the character, |i| will be numFonts.
+ // So, we have to use '<=" rather than '<' to see if we found a font
+ // covering the character.
+ if (i <= numFonts)
+ return getCachedFontData(data);
+
+ return 0;
+
+}
+
+SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ return 0;
+}
+
+SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description)
+{
+ FontDescription::GenericFamilyType generic = description.genericFamily();
+
+ // 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");
+ static AtomicString courierStr("Courier New");
+ static AtomicString arialStr("Arial");
+
+ AtomicString& fontStr = timesStr;
+ if (generic == FontDescription::SansSerifFamily)
+ fontStr = arialStr;
+ else if (generic == FontDescription::MonospaceFamily)
+ fontStr = courierStr;
+
+ SimpleFontData* simpleFont = getCachedFontData(description, fontStr);
+ if (simpleFont)
+ return simpleFont;
+
+ // Fall back to system fonts as Win Safari does because this function must
+ // return a valid font. Once we find a valid system font, we save its name
+ // to a static variable and use it to prevent trying system fonts again.
+ static wchar_t fallbackFontName[LF_FACESIZE] = {0};
+ if (fallbackFontName[0])
+ return getCachedFontData(description, fallbackFontName);
+
+ // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
+ if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
+ LOGFONT defaultGUILogFont;
+ GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, defaultGUILogFont, fallbackFontName))
+ return simpleFont;
+ }
+
+ // Fall back to Non-client metrics fonts.
+ NONCLIENTMETRICS nonClientMetrics = {0};
+ nonClientMetrics.cbSize = sizeof(nonClientMetrics);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMessageFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMenuFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfStatusFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfCaptionFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
+ return simpleFont;
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
+{
+ HDC hdc = GetDC(0);
+
+ LOGFONT logFont;
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ unsigned familyLength = min(familyName.length(), static_cast<unsigned>(LF_FACESIZE - 1));
+ memcpy(logFont.lfFaceName, familyName.characters(), familyLength * sizeof(UChar));
+ logFont.lfFaceName[familyLength] = 0;
+ logFont.lfPitchAndFamily = 0;
+
+ TraitsInFamilyProcData procData(familyName);
+ EnumFontFamiliesEx(hdc, &logFont, traitsInFamilyEnumProc, reinterpret_cast<LPARAM>(&procData), 0);
+ copyToVector(procData.m_traitsMasks, traitsMasks);
+
+ ReleaseDC(0, hdc);
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ LOGFONT winfont = {0};
+ FillLogFont(fontDescription, &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.
+ String winName;
+ HFONT hfont = createFontIndirectAndGetWinName(family, &winfont, &winName);
+ if (!hfont)
+ return 0;
+
+ // FIXME: Do we need to use predefined fonts "guaranteed" to exist
+ // when we're running in layout-test mode?
+ if (!equalIgnoringCase(family, winName)) {
+ // For CJK fonts with both English and native names,
+ // GetTextFace returns a native name under the font's "locale"
+ // and an English name under other locales regardless of
+ // lfFaceName field of LOGFONT. As a result, we need to check
+ // if a font has an alternate name. If there is, we need to
+ // compare it with what's requested in the first place.
+ String altName;
+ if (!LookupAltName(family, altName) ||
+ !equalIgnoringCase(altName, winName)) {
+ DeleteObject(hfont);
+ return 0;
+ }
+ }
+
+ return new FontPlatformData(hfont,
+ fontDescription.computedPixelSize());
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
new file mode 100644
index 0000000..bd33927
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontCache.h"
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "FontDescription.h"
+#include "FontPlatformData.h"
+#include "Logging.h"
+#include "NotImplemented.h"
+#include "SimpleFontData.h"
+
+#include "SkPaint.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
+#include <wtf/Assertions.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+void FontCache::platformInit()
+{
+}
+
+const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
+ const UChar* characters,
+ int length)
+{
+ String family = ChromiumBridge::getFontFamilyForCharacters(characters, length);
+ if (family.isEmpty())
+ return 0;
+
+ AtomicString atomicFamily(family);
+ return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), atomicFamily, false));
+}
+
+SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
+{
+ return 0;
+}
+
+SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description)
+{
+ static const AtomicString sansStr("Sans");
+ static const AtomicString serifStr("Serif");
+ static const AtomicString monospaceStr("Monospace");
+
+ FontPlatformData* fontPlatformData = 0;
+ switch (description.genericFamily()) {
+ case FontDescription::SerifFamily:
+ fontPlatformData = getCachedFontPlatformData(description, serifStr);
+ break;
+ case FontDescription::MonospaceFamily:
+ fontPlatformData = getCachedFontPlatformData(description, monospaceStr);
+ break;
+ case FontDescription::SansSerifFamily:
+ default:
+ fontPlatformData = getCachedFontPlatformData(description, sansStr);
+ break;
+ }
+
+ ASSERT(fontPlatformData);
+ return getCachedFontData(fontPlatformData);
+}
+
+void FontCache::getTraitsInFamily(const AtomicString& familyName,
+ Vector<unsigned>& traitsMasks)
+{
+ notImplemented();
+}
+
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription,
+ const AtomicString& family)
+{
+ const char* name = 0;
+ CString s;
+
+ // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
+ // the fallback name (like "monospace") that fontconfig understands.
+ if (!family.length() || family.startsWith("-webkit-")) {
+ static const struct {
+ FontDescription::GenericFamilyType mType;
+ const char* mName;
+ } fontDescriptions[] = {
+ { FontDescription::SerifFamily, "serif" },
+ { FontDescription::SansSerifFamily, "sans-serif" },
+ { FontDescription::MonospaceFamily, "monospace" },
+ { FontDescription::CursiveFamily, "cursive" },
+ { FontDescription::FantasyFamily, "fantasy" }
+ };
+
+ FontDescription::GenericFamilyType type = fontDescription.genericFamily();
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(fontDescriptions); i++) {
+ if (type == fontDescriptions[i].mType) {
+ name = fontDescriptions[i].mName;
+ break;
+ }
+ }
+ if (!name)
+ name = "";
+ } else {
+ // convert the name to utf8
+ s = family.string().utf8();
+ name = s.data();
+ }
+
+ int style = SkTypeface::kNormal;
+ if (fontDescription.weight() >= FontWeightBold)
+ style |= SkTypeface::kBold;
+ if (fontDescription.italic())
+ style |= SkTypeface::kItalic;
+
+ SkTypeface* tf = SkTypeface::CreateFromName(name, static_cast<SkTypeface::Style>(style));
+ if (!tf)
+ return 0;
+
+ FontPlatformData* result =
+ new FontPlatformData(tf,
+ name,
+ fontDescription.computedSize(),
+ (style & SkTypeface::kBold) && !tf->isBold(),
+ (style & SkTypeface::kItalic) && !tf->isItalic(),
+ fontDescription.orientation());
+ tf->unref();
+ return result;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
new file mode 100644
index 0000000..1a00833
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -0,0 +1,541 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "ChromiumBridge.h"
+#include "FontFallbackList.h"
+#include "GlyphBuffer.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "SimpleFontData.h"
+#include "SkiaFontWin.h"
+#include "SkiaUtils.h"
+#include "TransparencyWin.h"
+#include "UniscribeHelperTextRun.h"
+
+#include "skia/ext/platform_canvas_win.h"
+#include "skia/ext/skia_utils_win.h" // FIXME: remove this dependency.
+
+#include <windows.h>
+
+namespace WebCore {
+
+namespace {
+
+bool canvasHasMultipleLayers(const SkCanvas* canvas)
+{
+ SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
+ iter.next(); // There is always at least one layer.
+ return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
+}
+
+class TransparencyAwareFontPainter {
+public:
+ TransparencyAwareFontPainter(GraphicsContext*, const FloatPoint&);
+ ~TransparencyAwareFontPainter();
+
+protected:
+ // Called by our subclass' constructor to initialize GDI if necessary. This
+ // is a separate function so it can be called after the subclass finishes
+ // construction (it calls virtual functions).
+ void init();
+
+ virtual IntRect estimateTextBounds() = 0;
+
+ // Use the context from the transparency helper when drawing with GDI. It
+ // may point to a temporary one.
+ GraphicsContext* m_graphicsContext;
+ PlatformGraphicsContext* m_platformContext;
+
+ FloatPoint m_point;
+
+ // Set when Windows can handle the type of drawing we're doing.
+ bool m_useGDI;
+
+ // These members are valid only when m_useGDI is set.
+ HDC m_hdc;
+ TransparencyWin m_transparency;
+
+private:
+ // Call when we're using GDI mode to initialize the TransparencyWin to help
+ // us draw GDI text.
+ void initializeForGDI();
+
+ bool m_createdTransparencyLayer; // We created a layer to give the font some alpha.
+};
+
+TransparencyAwareFontPainter::TransparencyAwareFontPainter(GraphicsContext* context,
+ const FloatPoint& point)
+ : m_graphicsContext(context)
+ , m_platformContext(context->platformContext())
+ , m_point(point)
+ , m_useGDI(windowsCanHandleTextDrawing(context))
+ , m_hdc(0)
+ , m_createdTransparencyLayer(false)
+{
+}
+
+void TransparencyAwareFontPainter::init()
+{
+ if (m_useGDI)
+ initializeForGDI();
+}
+
+void TransparencyAwareFontPainter::initializeForGDI()
+{
+ m_graphicsContext->save();
+ SkColor color = m_platformContext->effectiveFillColor();
+ // Used only when m_createdTransparencyLayer is true.
+ float layerAlpha = 0.0f;
+ if (SkColorGetA(color) != 0xFF) {
+ // When the font has some transparency, apply it by creating a new
+ // transparency layer with that opacity applied. We'll actually create
+ // a new transparency layer after we calculate the bounding box.
+ m_createdTransparencyLayer = true;
+ layerAlpha = SkColorGetA(color) / 255.0f;
+ // The color should be opaque now.
+ color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+ }
+
+ TransparencyWin::LayerMode layerMode;
+ IntRect layerRect;
+ if (m_platformContext->isDrawingToImageBuffer()) {
+ // Assume if we're drawing to an image buffer that the background
+ // is not opaque and we have to undo ClearType. We may want to
+ // enhance this to actually check, since it will often be opaque
+ // and we could do ClearType in that case.
+ layerMode = TransparencyWin::TextComposite;
+ layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
+
+ // The transparency helper requires that we draw text in black in
+ // this mode and it will apply the color.
+ m_transparency.setTextCompositeColor(color);
+ color = SkColorSetRGB(0, 0, 0);
+ } else if (m_createdTransparencyLayer || canvasHasMultipleLayers(m_platformContext->canvas())) {
+ // When we're drawing a web page, we know the background is opaque,
+ // but if we're drawing to a layer, we still need extra work.
+ layerMode = TransparencyWin::OpaqueCompositeLayer;
+ layerRect = estimateTextBounds();
+ m_graphicsContext->clip(layerRect);
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->beginTransparencyLayer(layerAlpha);
+ } else {
+ // Common case of drawing onto the bottom layer of a web page: we
+ // know everything is opaque so don't need to do anything special.
+ layerMode = TransparencyWin::NoLayer;
+ }
+
+ // Bug 26088 - init() might fail if layerRect is invalid. Given this, we
+ // need to be careful to check for null pointers everywhere after this call
+ m_transparency.init(m_graphicsContext, layerMode,
+ TransparencyWin::KeepTransform, layerRect);
+
+ // Set up the DC, using the one from the transparency helper.
+ if (m_transparency.platformContext()) {
+ m_hdc = m_transparency.platformContext()->canvas()->beginPlatformPaint();
+ SetTextColor(m_hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(m_hdc, TRANSPARENT);
+ }
+}
+
+TransparencyAwareFontPainter::~TransparencyAwareFontPainter()
+{
+ if (!m_useGDI || !m_graphicsContext || !m_platformContext)
+ return; // Nothing to do.
+ m_transparency.composite();
+ if (m_createdTransparencyLayer)
+ m_graphicsContext->endTransparencyLayer();
+ m_graphicsContext->restore();
+ m_platformContext->canvas()->endPlatformPaint();
+}
+
+// Specialization for simple GlyphBuffer painting.
+class TransparencyAwareGlyphPainter : public TransparencyAwareFontPainter {
+ public:
+ TransparencyAwareGlyphPainter(GraphicsContext*,
+ const SimpleFontData*,
+ const GlyphBuffer&,
+ int from, int numGlyphs,
+ const FloatPoint&);
+ ~TransparencyAwareGlyphPainter();
+
+ // Draws the partial string of glyphs, starting at |startAdvance| to the
+ // left of m_point. We express it this way so that if we're using the Skia
+ // drawing path we can use floating-point positioning, even though we have
+ // to use integer positioning in the GDI path.
+ bool drawGlyphs(int numGlyphs, const WORD* glyphs, const int* advances, int startAdvance) const;
+
+ private:
+ virtual IntRect estimateTextBounds();
+
+ const SimpleFontData* m_font;
+ const GlyphBuffer& m_glyphBuffer;
+ int m_from;
+ int m_numGlyphs;
+
+ // When m_useGdi is set, this stores the previous HFONT selected into the
+ // m_hdc so we can restore it.
+ HGDIOBJ m_oldFont; // For restoring the DC to its original state.
+};
+
+TransparencyAwareGlyphPainter::TransparencyAwareGlyphPainter(
+ GraphicsContext* context,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from, int numGlyphs,
+ const FloatPoint& point)
+ : TransparencyAwareFontPainter(context, point)
+ , m_font(font)
+ , m_glyphBuffer(glyphBuffer)
+ , m_from(from)
+ , m_numGlyphs(numGlyphs)
+ , m_oldFont(0)
+{
+ init();
+
+ if (m_hdc)
+ m_oldFont = ::SelectObject(m_hdc, m_font->platformData().hfont());
+}
+
+TransparencyAwareGlyphPainter::~TransparencyAwareGlyphPainter()
+{
+ if (m_useGDI && m_hdc)
+ ::SelectObject(m_hdc, m_oldFont);
+}
+
+
+// Estimates the bounding box of the given text. This is copied from
+// FontCGWin.cpp, it is possible, but a lot more work, to get the precide
+// bounds.
+IntRect TransparencyAwareGlyphPainter::estimateTextBounds()
+{
+ int totalWidth = 0;
+ for (int i = 0; i < m_numGlyphs; i++)
+ totalWidth += lroundf(m_glyphBuffer.advanceAt(m_from + i));
+
+ return IntRect(m_point.x() - (m_font->ascent() + m_font->descent()) / 2,
+ m_point.y() - m_font->ascent() - m_font->lineGap(),
+ totalWidth + m_font->ascent() + m_font->descent(),
+ m_font->lineSpacing());
+}
+
+bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
+ const WORD* glyphs,
+ const int* advances,
+ int startAdvance) const
+{
+ if (!m_useGDI) {
+ SkPoint origin = m_point;
+ origin.fX += startAdvance;
+ return paintSkiaText(m_graphicsContext, m_font->platformData().hfont(),
+ numGlyphs, glyphs, advances, 0, &origin);
+ }
+
+ if (!m_graphicsContext || !m_hdc)
+ return true;
+
+ // Windows' origin is the top-left of the bounding box, so we have
+ // to subtract off the font ascent to get it.
+ int x = lroundf(m_point.x() + startAdvance);
+ int y = lroundf(m_point.y() - m_font->ascent());
+
+ // If there is a non-blur shadow and both the fill color and shadow color
+ // are opaque, handle without skia.
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)) {
+ // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
+ // will have already returned true during the ctor initiatization of m_useGDI
+ ASSERT(shadowColor.alpha() == 255);
+ ASSERT(m_graphicsContext->fillColor().alpha() == 255);
+ ASSERT(shadowBlur == 0);
+ COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
+ COLORREF savedTextColor = GetTextColor(m_hdc);
+ SetTextColor(m_hdc, textColor);
+ ExtTextOut(m_hdc, x + shadowOffset.width(), y + shadowOffset.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
+ SetTextColor(m_hdc, savedTextColor);
+ }
+
+ return !!ExtTextOut(m_hdc, x, y, ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]);
+}
+
+class TransparencyAwareUniscribePainter : public TransparencyAwareFontPainter {
+ public:
+ TransparencyAwareUniscribePainter(GraphicsContext*,
+ const Font*,
+ const TextRun&,
+ int from, int to,
+ const FloatPoint&);
+ ~TransparencyAwareUniscribePainter();
+
+ // Uniscibe will draw directly into our buffer, so we need to expose our DC.
+ HDC hdc() const { return m_hdc; }
+
+ private:
+ virtual IntRect estimateTextBounds();
+
+ const Font* m_font;
+ const TextRun& m_run;
+ int m_from;
+ int m_to;
+};
+
+TransparencyAwareUniscribePainter::TransparencyAwareUniscribePainter(
+ GraphicsContext* context,
+ const Font* font,
+ const TextRun& run,
+ int from, int to,
+ const FloatPoint& point)
+ : TransparencyAwareFontPainter(context, point)
+ , m_font(font)
+ , m_run(run)
+ , m_from(from)
+ , m_to(to)
+{
+ init();
+}
+
+TransparencyAwareUniscribePainter::~TransparencyAwareUniscribePainter()
+{
+}
+
+IntRect TransparencyAwareUniscribePainter::estimateTextBounds()
+{
+ // This case really really sucks. There is no convenient way to estimate
+ // the bounding box. So we run Uniscribe twice. If we find this happens a
+ // lot, the way to fix it is to make the extra layer after the
+ // UniscribeHelper has measured the text.
+ IntPoint intPoint(lroundf(m_point.x()),
+ lroundf(m_point.y()));
+
+ UniscribeHelperTextRun state(m_run, *m_font);
+ int left = lroundf(m_point.x()) + state.characterToX(m_from);
+ int right = lroundf(m_point.x()) + state.characterToX(m_to);
+
+ // Adjust for RTL script since we just want to know the text bounds.
+ if (left > right)
+ std::swap(left, right);
+
+ // This algorithm for estimating how much extra space we need (the text may
+ // go outside the selection rect) is based roughly on
+ // TransparencyAwareGlyphPainter::estimateTextBounds above.
+ return IntRect(left - (m_font->ascent() + m_font->descent()) / 2,
+ m_point.y() - m_font->ascent() - m_font->lineGap(),
+ (right - left) + m_font->ascent() + m_font->descent(),
+ m_font->lineSpacing());
+}
+
+} // namespace
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+void Font::drawGlyphs(GraphicsContext* graphicsContext,
+ const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer,
+ int from,
+ int numGlyphs,
+ const FloatPoint& point) const
+{
+ graphicsContext->platformContext()->prepareForSoftwareDraw();
+
+ SkColor color = graphicsContext->platformContext()->effectiveFillColor();
+ unsigned char alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
+ return;
+
+ TransparencyAwareGlyphPainter painter(graphicsContext, font, glyphBuffer, from, numGlyphs, point);
+
+ // We draw the glyphs in chunks to avoid having to do a heap allocation for
+ // the arrays of characters and advances. Since ExtTextOut is the
+ // lowest-level text output function on Windows, there should be little
+ // penalty for splitting up the text. On the other hand, the buffer cannot
+ // be bigger than 4094 or the function will fail.
+ const int kMaxBufferLength = 256;
+ Vector<WORD, kMaxBufferLength> glyphs;
+ Vector<int, kMaxBufferLength> advances;
+ int glyphIndex = 0; // The starting glyph of the current chunk.
+ int curAdvance = 0; // How far from the left the current chunk is.
+ while (glyphIndex < numGlyphs) {
+ // How many chars will be in this chunk?
+ int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
+ glyphs.resize(curLen);
+ advances.resize(curLen);
+
+ int curWidth = 0;
+ for (int i = 0; i < curLen; ++i, ++glyphIndex) {
+ glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
+ advances[i] = static_cast<int>(glyphBuffer.advanceAt(from + glyphIndex));
+
+ // Bug 26088 - very large positive or negative runs can fail to
+ // render so we clamp the size here. In the specs, negative
+ // letter-spacing is implementation-defined, so this should be
+ // fine, and it matches Safari's implementation. The call actually
+ // seems to crash if kMaxNegativeRun is set to somewhere around
+ // -32830, so we give ourselves a little breathing room.
+ const int maxNegativeRun = -32768;
+ const int maxPositiveRun = 32768;
+ if ((curWidth + advances[i] < maxNegativeRun) || (curWidth + advances[i] > maxPositiveRun))
+ advances[i] = 0;
+ curWidth += advances[i];
+ }
+
+ // Actually draw the glyphs (with retry on failure).
+ bool success = false;
+ for (int executions = 0; executions < 2; ++executions) {
+ success = painter.drawGlyphs(curLen, &glyphs[0], &advances[0], curAdvance);
+ if (!success && executions == 0) {
+ // Ask the browser to load the font for us and retry.
+ ChromiumBridge::ensureFontLoaded(font->platformData().hfont());
+ continue;
+ }
+ break;
+ }
+
+ if (!success)
+ LOG_ERROR("Unable to draw the glyphs after second attempt");
+
+ curAdvance += curWidth;
+ }
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run,
+ const FloatPoint& point,
+ int h,
+ int from,
+ int to) const
+{
+ UniscribeHelperTextRun state(run, *this);
+ float left = static_cast<float>(point.x() + state.characterToX(from));
+ float right = static_cast<float>(point.x() + state.characterToX(to));
+
+ // If the text is RTL, left will actually be after right.
+ if (left < right)
+ return FloatRect(left, point.y(),
+ right - left, static_cast<float>(h));
+
+ return FloatRect(right, point.y(),
+ left - right, static_cast<float>(h));
+}
+
+void Font::drawComplexText(GraphicsContext* graphicsContext,
+ const TextRun& run,
+ const FloatPoint& point,
+ int from,
+ int to) const
+{
+ PlatformGraphicsContext* context = graphicsContext->platformContext();
+ UniscribeHelperTextRun state(run, *this);
+
+ SkColor color = graphicsContext->platformContext()->effectiveFillColor();
+ unsigned char alpha = SkColorGetA(color);
+ // Skip 100% transparent text; no need to draw anything.
+ if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke)
+ return;
+
+ TransparencyAwareUniscribePainter painter(graphicsContext, this, run, from, to, point);
+
+ HDC hdc = painter.hdc();
+ if (windowsCanHandleTextDrawing(graphicsContext) && !hdc)
+ return;
+
+ // TODO(maruel): http://b/700464 SetTextColor doesn't support transparency.
+ // Enforce non-transparent color.
+ color = SkColorSetRGB(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color));
+ if (hdc) {
+ SetTextColor(hdc, skia::SkColorToCOLORREF(color));
+ SetBkMode(hdc, TRANSPARENT);
+ }
+
+ // If there is a non-blur shadow and both the fill color and shadow color
+ // are opaque, handle without skia.
+ FloatSize shadowOffset;
+ float shadowBlur;
+ Color shadowColor;
+ ColorSpace shadowColorSpace;
+ if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace) && windowsCanHandleDrawTextShadow(graphicsContext)) {
+ COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
+ COLORREF savedTextColor = GetTextColor(hdc);
+ SetTextColor(hdc, textColor);
+ state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(),
+ static_cast<int>(point.y() - ascent()) + shadowOffset.height(), from, to);
+ SetTextColor(hdc, savedTextColor);
+ }
+
+ // Uniscribe counts the coordinates from the upper left, while WebKit uses
+ // the baseline, so we have to subtract off the ascent.
+ state.draw(graphicsContext, hdc, static_cast<int>(point.x()),
+ static_cast<int>(point.y() - ascent()), from, to);
+
+ context->canvas()->endPlatformPaint();
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
+{
+ UniscribeHelperTextRun state(run, *this);
+ return static_cast<float>(state.width());
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
+ bool includePartialGlyphs) const
+{
+ // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
+ // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
+ int x = static_cast<int>(xFloat);
+
+ // Mac code ignores includePartialGlyphs, and they don't know what it's
+ // supposed to do, so we just ignore it as well.
+ UniscribeHelperTextRun state(run, *this);
+ int charIndex = state.xToCharacter(x);
+
+ // XToCharacter will return -1 if the position is before the first
+ // character (we get called like this sometimes).
+ if (charIndex < 0)
+ charIndex = 0;
+ return charIndex;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/FontLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
new file mode 100644
index 0000000..b256e70
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Font.h"
+
+#include "ComplexTextControllerLinux.h"
+#include "FloatRect.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "HarfbuzzSkia.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "SimpleFontData.h"
+
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkTemplates.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+static bool isCanvasMultiLayered(SkCanvas* canvas)
+{
+ SkCanvas::LayerIter layerIterator(canvas, false);
+ layerIterator.next();
+ return !layerIterator.done();
+}
+
+static void adjustTextRenderMode(SkPaint* paint, PlatformContextSkia* skiaContext)
+{
+ // Our layers only have a single alpha channel. This means that subpixel
+ // rendered text cannot be compositied correctly when the layer is
+ // collapsed. Therefore, subpixel text is disabled when we are drawing
+ // onto a layer or when the compositor is being used.
+ if (isCanvasMultiLayered(skiaContext->canvas()) || skiaContext->isDrawingToImageBuffer())
+ paint->setLCDRenderText(false);
+}
+
+void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
+ const FloatPoint& point) const {
+ SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); // compile-time assert
+
+ const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
+ SkScalar x = SkFloatToScalar(point.x());
+ SkScalar y = SkFloatToScalar(point.y());
+
+ // FIXME: text rendering speed:
+ // Android has code in their WebCore fork to special case when the
+ // GlyphBuffer has no advances other than the defaults. In that case the
+ // text drawing can proceed faster. However, it's unclear when those
+ // patches may be upstreamed to WebKit so we always use the slower path
+ // here.
+ const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
+ SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs);
+ SkPoint* pos = storage.get();
+ SkPoint* vPosBegin = storage2.get();
+ SkPoint* vPosEnd = storage3.get();
+
+ bool isVertical = font->orientation() == Vertical;
+ for (int i = 0; i < numGlyphs; i++) {
+ SkScalar myWidth = SkFloatToScalar(adv[i].width());
+ pos[i].set(x, y);
+ if (isVertical) {
+ vPosBegin[i].set(x + myWidth, y);
+ vPosEnd[i].set(x + myWidth, y - myWidth);
+ }
+ x += myWidth;
+ y += SkFloatToScalar(adv[i].height());
+ }
+
+ gc->platformContext()->prepareForSoftwareDraw();
+
+ SkCanvas* canvas = gc->platformContext()->canvas();
+ TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
+
+ // We draw text up to two times (once for fill, once for stroke).
+ if (textMode & TextModeFill) {
+ SkPaint paint;
+ gc->platformContext()->setupPaintForFilling(&paint);
+ font->platformData().setupPaint(&paint);
+ adjustTextRenderMode(&paint, gc->platformContext());
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setColor(gc->fillColor().rgb());
+
+ if (isVertical) {
+ SkPath path;
+ for (int i = 0; i < numGlyphs; ++i) {
+ path.reset();
+ path.moveTo(vPosBegin[i]);
+ path.lineTo(vPosEnd[i]);
+ canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+ }
+ } else
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+ }
+
+ if ((textMode & TextModeStroke)
+ && gc->platformContext()->getStrokeStyle() != NoStroke
+ && gc->platformContext()->getStrokeThickness() > 0) {
+
+ SkPaint paint;
+ gc->platformContext()->setupPaintForStroking(&paint, 0, 0);
+ font->platformData().setupPaint(&paint);
+ adjustTextRenderMode(&paint, gc->platformContext());
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setColor(gc->strokeColor().rgb());
+
+ if (textMode & TextModeFill) {
+ // If we also filled, we don't want to draw shadows twice.
+ // See comment in FontChromiumWin.cpp::paintSkiaText() for more details.
+ SkSafeUnref(paint.setLooper(0));
+ }
+
+ if (isVertical) {
+ SkPath path;
+ for (int i = 0; i < numGlyphs; ++i) {
+ path.reset();
+ path.moveTo(vPosBegin[i]);
+ path.lineTo(vPosEnd[i]);
+ canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+ }
+ } else
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+ }
+}
+
+// Harfbuzz uses 26.6 fixed point values for pixel offsets. However, we don't
+// handle subpixel positioning so this function is used to truncate Harfbuzz
+// values to a number of pixels.
+static int truncateFixedPointToInteger(HB_Fixed value)
+{
+ return value >> 6;
+}
+
+static void setupForTextPainting(SkPaint* paint, SkColor color)
+{
+ paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint->setColor(color);
+}
+
+void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
+ const FloatPoint& point, int from, int to) const
+{
+ if (!run.length())
+ return;
+
+ SkCanvas* canvas = gc->platformContext()->canvas();
+ TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
+ bool fill = textMode & TextModeFill;
+ bool stroke = (textMode & TextModeStroke)
+ && gc->platformContext()->getStrokeStyle() != NoStroke
+ && gc->platformContext()->getStrokeThickness() > 0;
+
+ if (!fill && !stroke)
+ return;
+
+ SkPaint strokePaint, fillPaint;
+ if (fill) {
+ gc->platformContext()->setupPaintForFilling(&fillPaint);
+ setupForTextPainting(&fillPaint, gc->fillColor().rgb());
+ }
+ if (stroke) {
+ gc->platformContext()->setupPaintForStroking(&strokePaint, 0, 0);
+ setupForTextPainting(&strokePaint, gc->strokeColor().rgb());
+ }
+
+ ComplexTextController controller(run, point.x(), this);
+ controller.setWordSpacingAdjustment(wordSpacing());
+ controller.setLetterSpacingAdjustment(letterSpacing());
+ controller.setPadding(run.padding());
+
+ while (controller.nextScriptRun()) {
+ if (fill) {
+ controller.fontPlatformDataForScriptRun()->setupPaint(&fillPaint);
+ adjustTextRenderMode(&fillPaint, gc->platformContext());
+ canvas->drawPosTextH(controller.glyphs(), controller.length() << 1, controller.xPositions(), point.y(), fillPaint);
+ }
+
+ if (stroke) {
+ controller.fontPlatformDataForScriptRun()->setupPaint(&strokePaint);
+ adjustTextRenderMode(&strokePaint, gc->platformContext());
+ canvas->drawPosTextH(controller.glyphs(), controller.length() << 1, controller.xPositions(), point.y(), strokePaint);
+ }
+ }
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
+{
+ ComplexTextController controller(run, 0, this);
+ controller.setWordSpacingAdjustment(wordSpacing());
+ controller.setLetterSpacingAdjustment(letterSpacing());
+ return controller.widthOfFullRun();
+}
+
+static int glyphIndexForXPositionInScriptRun(const ComplexTextController& controller, int x)
+{
+ const HB_Fixed* advances = controller.advances();
+ int letterSpacing = controller.letterSpacing();
+ int glyphIndex;
+ if (controller.rtl()) {
+ for (glyphIndex = controller.length() - 1; glyphIndex >= 0; --glyphIndex) {
+ // When iterating LTR over RTL text, we must include the whitespace
+ // _before_ the glyph, so no + 1 here.
+ if (x < (static_cast<int>(controller.length()) - glyphIndex) * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex]))
+ break;
+ x -= truncateFixedPointToInteger(advances[glyphIndex]);
+ }
+ } else {
+ for (glyphIndex = 0; static_cast<unsigned>(glyphIndex) < controller.length(); ++glyphIndex) {
+ if (x < (glyphIndex * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex])))
+ break;
+ x -= truncateFixedPointToInteger(advances[glyphIndex]);
+ }
+ }
+
+ return glyphIndex;
+}
+
+// Return the code point index for the given |x| offset into the text run.
+int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
+ bool includePartialGlyphs) const
+{
+ // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
+ // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
+ int x = static_cast<int>(xFloat);
+
+ // (Mac code ignores includePartialGlyphs, and they don't know what it's
+ // supposed to do, so we just ignore it as well.)
+ ComplexTextController controller(run, 0, this);
+ controller.setWordSpacingAdjustment(wordSpacing());
+ controller.setLetterSpacingAdjustment(letterSpacing());
+
+ // If this is RTL text, the first glyph from the left is actually the last
+ // code point. So we need to know how many code points there are total in
+ // order to subtract. This is different from the length of the TextRun
+ // because UTF-16 surrogate pairs are a single code point, but 32-bits long.
+ // In LTR we leave this as 0 so that we get the correct value for
+ // |basePosition|, below.
+ unsigned totalCodePoints = 0;
+ if (controller.rtl()) {
+ ssize_t offset = 0;
+ while (offset < run.length()) {
+ utf16_to_code_point(run.characters(), run.length(), &offset);
+ totalCodePoints++;
+ }
+ }
+
+ unsigned basePosition = totalCodePoints;
+
+ // For RTL:
+ // code-point order: abcd efg hijkl
+ // on screen: lkjih gfe dcba
+ // ^ ^
+ // | |
+ // basePosition--| |
+ // totalCodePoints----|
+ // Since basePosition is currently the total number of code-points, the
+ // first thing we do is decrement it so that it's pointing to the start of
+ // the current script-run.
+ //
+ // For LTR, basePosition is zero so it already points to the start of the
+ // first script run.
+ while (controller.nextScriptRun()) {
+ if (controller.rtl())
+ basePosition -= controller.numCodePoints();
+
+ if (x >= 0 && static_cast<unsigned>(x) < controller.width()) {
+ // The x value in question is within this script run. We consider
+ // each glyph in presentation order and stop when we find the one
+ // covering this position.
+ const int glyphIndex = glyphIndexForXPositionInScriptRun(controller, x);
+
+ // Now that we have a glyph index, we have to turn that into a
+ // code-point index. Because of ligatures, several code-points may
+ // have gone into a single glyph. We iterate over the clusters log
+ // and find the first code-point which contributed to the glyph.
+
+ // Some shapers (i.e. Khmer) will produce cluster logs which report
+ // that /no/ code points contributed to certain glyphs. Because of
+ // this, we take any code point which contributed to the glyph in
+ // question, or any subsequent glyph. If we run off the end, then
+ // we take the last code point.
+ const unsigned short* log = controller.logClusters();
+ for (unsigned j = 0; j < controller.numCodePoints(); ++j) {
+ if (log[j] >= glyphIndex)
+ return basePosition + j;
+ }
+
+ return basePosition + controller.numCodePoints() - 1;
+ }
+
+ x -= controller.width();
+
+ if (!controller.rtl())
+ basePosition += controller.numCodePoints();
+ }
+
+ return basePosition;
+}
+
+// Return the rectangle for selecting the given range of code-points in the TextRun.
+FloatRect Font::selectionRectForComplexText(const TextRun& run,
+ const FloatPoint& point, int height,
+ int from, int to) const
+{
+ int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1;
+ ComplexTextController controller(run, 0, this);
+ controller.setWordSpacingAdjustment(wordSpacing());
+ controller.setLetterSpacingAdjustment(letterSpacing());
+
+ // Base will point to the x offset for the current script run. Note that, in
+ // the LTR case, width will be 0.
+ int base = controller.rtl() ? controller.widthOfFullRun() : 0;
+ const int leftEdge = base;
+
+ // We want to enumerate the script runs in code point order in the following
+ // code. This call also resets |controller|.
+ controller.setBackwardsIteration(false);
+
+ while (controller.nextScriptRun() && (fromX == -1 || toX == -1)) {
+ // ComplexTextController will helpfully accululate the x offsets for different
+ // script runs for us. For this code, however, we always want the x offsets
+ // to start from zero so we call this before each script run.
+ controller.setXOffsetToZero();
+
+ if (controller.rtl())
+ base -= controller.width();
+
+ if (fromX == -1 && from >= 0 && static_cast<unsigned>(from) < controller.numCodePoints()) {
+ // |from| is within this script run. So we index the clusters log to
+ // find which glyph this code-point contributed to and find its x
+ // position.
+ int glyph = controller.logClusters()[from];
+ fromX = base + controller.xPositions()[glyph];
+ fromAdvance = controller.advances()[glyph];
+ } else
+ from -= controller.numCodePoints();
+
+ if (toX == -1 && to >= 0 && static_cast<unsigned>(to) < controller.numCodePoints()) {
+ int glyph = controller.logClusters()[to];
+ toX = base + controller.xPositions()[glyph];
+ toAdvance = controller.advances()[glyph];
+ } else
+ to -= controller.numCodePoints();
+
+ if (!controller.rtl())
+ base += controller.width();
+ }
+
+ // The position in question might be just after the text.
+ const int rightEdge = base;
+ if (fromX == -1 && !from)
+ fromX = leftEdge;
+ else if (controller.rtl())
+ fromX += truncateFixedPointToInteger(fromAdvance);
+
+ if (toX == -1 && !to)
+ toX = rightEdge;
+
+ ASSERT(fromX != -1 && toX != -1);
+
+ if (fromX < toX)
+ return FloatRect(point.x() + fromX, point.y(), toX - fromX, height);
+
+ return FloatRect(point.x() + toX, point.y(), fromX - toX, height);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformData.h b/Source/WebCore/platform/graphics/chromium/FontPlatformData.h
new file mode 100644
index 0000000..d8ce3e2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformData.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontPlatformData_h
+#define FontPlatformData_h
+
+#if OS(WINDOWS)
+#include "FontPlatformDataChromiumWin.h"
+#elif OS(LINUX) || OS(FREEBSD)
+#include "FontPlatformDataLinux.h"
+#endif
+
+#endif // FontPlatformData_h
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
new file mode 100644
index 0000000..d6c83ec
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontPlatformData.h"
+
+#include <windows.h>
+#include <objidl.h>
+#include <mlang.h>
+
+#include "ChromiumBridge.h"
+#include "SkiaFontWin.h"
+
+namespace WebCore {
+
+FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_font(hashTableDeletedFontValue())
+ , m_size(-1)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData::FontPlatformData()
+ : m_font(0)
+ , m_size(0)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData::FontPlatformData(HFONT font, float size)
+ : m_font(RefCountedHFONT::create(font))
+ , m_size(size)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+// FIXME: this constructor is needed for SVG fonts but doesn't seem to do much
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+ : m_font(0)
+ , m_size(size)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData& data)
+ : m_font(data.m_font)
+ , m_size(data.m_size)
+ , m_scriptCache(0)
+ , m_scriptFontProperties(0)
+{
+}
+
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& data)
+{
+ if (this != &data) {
+ m_font = data.m_font;
+ m_size = data.m_size;
+
+ // The following fields will get re-computed if necessary.
+ ScriptFreeCache(&m_scriptCache);
+ m_scriptCache = 0;
+
+ delete m_scriptFontProperties;
+ m_scriptFontProperties = 0;
+ }
+ return *this;
+}
+
+FontPlatformData::~FontPlatformData()
+{
+ ScriptFreeCache(&m_scriptCache);
+ m_scriptCache = 0;
+
+ delete m_scriptFontProperties;
+ m_scriptFontProperties = 0;
+}
+
+FontPlatformData::RefCountedHFONT::~RefCountedHFONT()
+{
+ if (m_hfont != reinterpret_cast<HFONT>(-1)) {
+ SkiaWinOutlineCache::removePathsForFont(m_hfont);
+ DeleteObject(m_hfont);
+ }
+}
+
+FontPlatformData::RefCountedHFONT* FontPlatformData::hashTableDeletedFontValue()
+{
+ static RefPtr<RefCountedHFONT> deletedValue =
+ RefCountedHFONT::create(reinterpret_cast<HFONT>(-1));
+ return deletedValue.get();
+}
+
+SCRIPT_FONTPROPERTIES* FontPlatformData::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);
+ HGDIOBJ oldFont = SelectObject(dc, hfont());
+ HRESULT hr = ScriptGetFontProperties(dc, scriptCache(),
+ m_scriptFontProperties);
+ if (S_OK != hr) {
+ if (ChromiumBridge::ensureFontLoaded(hfont())) {
+ // FIXME: Handle gracefully the error if this call also fails.
+ hr = ScriptGetFontProperties(dc, scriptCache(),
+ m_scriptFontProperties);
+ if (S_OK != hr) {
+ LOG_ERROR("Unable to get the font properties after second attempt");
+ }
+ }
+ }
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ }
+ }
+ return m_scriptFontProperties;
+}
+
+#ifndef NDEBUG
+String FontPlatformData::description() const
+{
+ return String();
+}
+#endif
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
new file mode 100644
index 0000000..b6ebb2e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontPlatformDataChromiumWin_h
+#define FontPlatformDataChromiumWin_h
+
+#include "config.h"
+
+#include "FontOrientation.h"
+#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/StringImpl.h>
+
+#include <usp10.h>
+
+typedef struct HFONT__ *HFONT;
+
+namespace WebCore {
+
+class FontDescription;
+
+class FontPlatformData {
+public:
+ // Used for deleted values in the font cache's hash tables. The hash table
+ // will create us with this structure, and it will compare other values
+ // to this "Deleted" one. It expects the Deleted one to be differentiable
+ // from the NULL one (created with the empty constructor), so we can't just
+ // set everything to NULL.
+ FontPlatformData(WTF::HashTableDeletedValueType);
+ FontPlatformData();
+ FontPlatformData(HFONT, float size);
+ FontPlatformData(float size, bool bold, bool oblique);
+ FontPlatformData(const FontPlatformData&);
+
+ FontPlatformData& operator=(const FontPlatformData&);
+
+ bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
+
+ ~FontPlatformData();
+
+ HFONT hfont() const { return m_font ? m_font->hfont() : 0; }
+ float size() const { return m_size; }
+
+ FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+
+ unsigned hash() const
+ {
+ return m_font ? m_font->hash() : NULL;
+ }
+
+ bool operator==(const FontPlatformData& other) const
+ {
+ return m_font == other.m_font && m_size == other.m_size;
+ }
+
+#ifndef NDEBUG
+ String description() const;
+#endif
+
+ SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
+ SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
+
+private:
+ // We refcount the internal HFONT so that FontPlatformData can be
+ // efficiently copied. WebKit depends on being able to copy it, and we
+ // don't really want to re-create the HFONT.
+ class RefCountedHFONT : public RefCounted<RefCountedHFONT> {
+ public:
+ static PassRefPtr<RefCountedHFONT> create(HFONT hfont)
+ {
+ return adoptRef(new RefCountedHFONT(hfont));
+ }
+
+ ~RefCountedHFONT();
+
+ HFONT hfont() const { return m_hfont; }
+ unsigned hash() const
+ {
+ return WTF::StringHasher::createBlobHash<sizeof(HFONT)>(&m_hfont);
+ }
+
+ bool operator==(const RefCountedHFONT& other) const
+ {
+ return m_hfont == other.m_hfont;
+ }
+
+ private:
+ // The create() function assumes there is already a refcount of one
+ // so it can do adoptRef.
+ RefCountedHFONT(HFONT hfont) : m_hfont(hfont)
+ {
+ }
+
+ HFONT m_hfont;
+ };
+
+ static RefCountedHFONT* hashTableDeletedFontValue();
+
+ RefPtr<RefCountedHFONT> m_font;
+ float m_size; // Point size of the font in pixels.
+
+ mutable SCRIPT_CACHE m_scriptCache;
+ mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
+};
+
+} // WebCore
+
+#endif // FontPlatformDataChromiumWin_h
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
new file mode 100644
index 0000000..42942cc
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontPlatformData.h"
+
+#include "ChromiumBridge.h"
+#include "HarfbuzzSkia.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+#include "SkPaint.h"
+#include "SkTypeface.h"
+
+#include <wtf/text/StringImpl.h>
+
+namespace WebCore {
+
+static SkPaint::Hinting skiaHinting = SkPaint::kNormal_Hinting;
+static bool isSkiaAntiAlias = true;
+static bool isSkiaSubpixelGlyphs = false;
+
+void FontPlatformData::setHinting(SkPaint::Hinting hinting)
+{
+ skiaHinting = hinting;
+}
+
+void FontPlatformData::setAntiAlias(bool isAntiAlias)
+{
+ isSkiaAntiAlias = isAntiAlias;
+}
+
+void FontPlatformData::setSubpixelGlyphs(bool isSubpixelGlyphs)
+{
+ isSkiaSubpixelGlyphs = isSubpixelGlyphs;
+}
+
+FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace()
+{
+ HB_FreeFace(m_harfbuzzFace);
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData& src)
+ : m_typeface(src.m_typeface)
+ , m_family(src.m_family)
+ , m_textSize(src.m_textSize)
+ , m_fakeBold(src.m_fakeBold)
+ , m_fakeItalic(src.m_fakeItalic)
+ , m_orientation(src.m_orientation)
+ , m_style(src.m_style)
+ , m_harfbuzzFace(src.m_harfbuzzFace)
+{
+ SkSafeRef(m_typeface);
+}
+
+FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation)
+ : m_typeface(tf)
+ , m_family(family)
+ , m_textSize(textSize)
+ , m_fakeBold(fakeBold)
+ , m_fakeItalic(fakeItalic)
+ , m_orientation(orientation)
+{
+ SkSafeRef(m_typeface);
+ querySystemForRenderStyle();
+}
+
+FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
+ : m_typeface(src.m_typeface)
+ , m_family(src.m_family)
+ , m_textSize(textSize)
+ , m_fakeBold(src.m_fakeBold)
+ , m_fakeItalic(src.m_fakeItalic)
+ , m_harfbuzzFace(src.m_harfbuzzFace)
+{
+ SkSafeRef(m_typeface);
+ querySystemForRenderStyle();
+}
+
+FontPlatformData::~FontPlatformData()
+{
+ SkSafeUnref(m_typeface);
+}
+
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
+{
+ SkRefCnt_SafeAssign(m_typeface, src.m_typeface);
+
+ m_family = src.m_family;
+ m_textSize = src.m_textSize;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
+ m_harfbuzzFace = src.m_harfbuzzFace;
+ m_orientation = src.m_orientation;
+ m_style = src.m_style;
+
+ return *this;
+}
+
+#ifndef NDEBUG
+String FontPlatformData::description() const
+{
+ return String();
+}
+#endif
+
+void FontPlatformData::setupPaint(SkPaint* paint) const
+{
+ const float ts = m_textSize >= 0 ? m_textSize : 12;
+
+ paint->setAntiAlias(m_style.useAntiAlias == FontRenderStyle::NoPreference ? isSkiaAntiAlias : m_style.useAntiAlias);
+ switch (m_style.useHinting) {
+ case FontRenderStyle::NoPreference:
+ paint->setHinting(skiaHinting);
+ break;
+ case 0:
+ paint->setHinting(SkPaint::kNo_Hinting);
+ break;
+ default:
+ paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle));
+ break;
+ }
+
+ paint->setEmbeddedBitmapText(m_style.useBitmaps);
+ paint->setTextSize(SkFloatToScalar(ts));
+ paint->setTypeface(m_typeface);
+ paint->setFakeBoldText(m_fakeBold);
+ paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0);
+ paint->setAutohinted(m_style.useAutoHint);
+
+ if (m_style.useAntiAlias == 1 || (m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias))
+ paint->setLCDRenderText(m_style.useSubpixel == FontRenderStyle::NoPreference ? isSkiaSubpixelGlyphs : m_style.useSubpixel);
+}
+
+SkFontID FontPlatformData::uniqueID() const
+{
+ return m_typeface->uniqueID();
+}
+
+bool FontPlatformData::operator==(const FontPlatformData& a) const
+{
+ // If either of the typeface pointers are invalid (either NULL or the
+ // special deleted value) then we test for pointer equality. Otherwise, we
+ // call SkTypeface::Equal on the valid pointers.
+ bool typefacesEqual;
+ if (m_typeface == hashTableDeletedFontValue()
+ || a.m_typeface == hashTableDeletedFontValue()
+ || !m_typeface
+ || !a.m_typeface)
+ typefacesEqual = m_typeface == a.m_typeface;
+ else
+ typefacesEqual = SkTypeface::Equal(m_typeface, a.m_typeface);
+
+ return typefacesEqual
+ && m_textSize == a.m_textSize
+ && m_fakeBold == a.m_fakeBold
+ && m_fakeItalic == a.m_fakeItalic
+ && m_orientation == a.m_orientation
+ && m_style == a.m_style;
+}
+
+unsigned FontPlatformData::hash() const
+{
+ unsigned h = SkTypeface::UniqueID(m_typeface);
+ h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
+
+ // This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing
+ // rules. Memcpy is generally optimized enough so that performance doesn't
+ // matter here.
+ uint32_t textSizeBytes;
+ memcpy(&textSizeBytes, &m_textSize, sizeof(uint32_t));
+ h ^= textSizeBytes;
+
+ return h;
+}
+
+bool FontPlatformData::isFixedPitch() const
+{
+ notImplemented();
+ return false;
+}
+
+HB_FaceRec_* FontPlatformData::harfbuzzFace() const
+{
+ if (!m_harfbuzzFace)
+ m_harfbuzzFace = RefCountedHarfbuzzFace::create(HB_NewFace(const_cast<FontPlatformData*>(this), harfbuzzSkiaGetTable));
+
+ return m_harfbuzzFace->face();
+}
+
+void FontPlatformData::querySystemForRenderStyle()
+{
+ if (!m_family.length()) {
+ // We don't have a family for this. Probably because it's a webfont. We
+ // set all the values to 'no preference' and take the defaults passed
+ // in from XSETTINGS.
+ m_style.useBitmaps = FontRenderStyle::NoPreference;
+ m_style.useAutoHint = FontRenderStyle::NoPreference;
+ m_style.useHinting = FontRenderStyle::NoPreference;
+ m_style.useAntiAlias = FontRenderStyle::NoPreference;
+ m_style.useSubpixel = FontRenderStyle::NoPreference;
+ return;
+ }
+
+ ChromiumBridge::getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3), &m_style);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
new file mode 100644
index 0000000..43771d7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontPlatformDataLinux_h
+#define FontPlatformDataLinux_h
+
+#include "FontOrientation.h"
+#include "FontRenderStyle.h"
+#include <wtf/Forward.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringImpl.h>
+#include <SkPaint.h>
+
+class SkTypeface;
+typedef uint32_t SkFontID;
+
+struct HB_FaceRec_;
+
+namespace WebCore {
+
+class FontDescription;
+
+// -----------------------------------------------------------------------------
+// FontPlatformData is the handle which WebKit has on a specific face. A face
+// is the tuple of (font, size, ...etc). Here we are just wrapping a Skia
+// SkTypeface pointer and dealing with the reference counting etc.
+// -----------------------------------------------------------------------------
+class FontPlatformData {
+public:
+ // Used for deleted values in the font cache's hash tables. The hash table
+ // will create us with this structure, and it will compare other values
+ // to this "Deleted" one. It expects the Deleted one to be differentiable
+ // from the NULL one (created with the empty constructor), so we can't just
+ // set everything to NULL.
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_typeface(hashTableDeletedFontValue())
+ , m_textSize(0)
+ , m_fakeBold(false)
+ , m_fakeItalic(false)
+ { }
+
+ FontPlatformData()
+ : m_typeface(0)
+ , m_textSize(0)
+ , m_fakeBold(false)
+ , m_fakeItalic(false)
+ , m_orientation(Horizontal)
+ { }
+
+ FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
+ : m_typeface(0)
+ , m_textSize(textSize)
+ , m_fakeBold(fakeBold)
+ , m_fakeItalic(fakeItalic)
+ , m_orientation(Horizontal)
+ { }
+
+ FontPlatformData(const FontPlatformData&);
+ FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation = Horizontal);
+ FontPlatformData(const FontPlatformData& src, float textSize);
+ ~FontPlatformData();
+
+ // -------------------------------------------------------------------------
+ // Return true iff this font is monospaced (i.e. every glyph has an equal x
+ // advance)
+ // -------------------------------------------------------------------------
+ bool isFixedPitch() const;
+
+ // -------------------------------------------------------------------------
+ // Setup a Skia painting context to use this font.
+ // -------------------------------------------------------------------------
+ void setupPaint(SkPaint*) const;
+
+ // -------------------------------------------------------------------------
+ // Return Skia's unique id for this font. This encodes both the style and
+ // the font's file name so refers to a single face.
+ // -------------------------------------------------------------------------
+ SkFontID uniqueID() const;
+
+ unsigned hash() const;
+ float size() const { return m_textSize; }
+
+ FontOrientation orientation() const { return m_orientation; }
+
+ bool operator==(const FontPlatformData&) const;
+ FontPlatformData& operator=(const FontPlatformData&);
+ bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); }
+
+#ifndef NDEBUG
+ String description() const;
+#endif
+
+ HB_FaceRec_* harfbuzzFace() const;
+
+ // -------------------------------------------------------------------------
+ // Global font preferences...
+
+ static void setHinting(SkPaint::Hinting);
+ static void setAntiAlias(bool on);
+ static void setSubpixelGlyphs(bool on);
+
+private:
+ class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> {
+ public:
+ static PassRefPtr<RefCountedHarfbuzzFace> create(HB_FaceRec_* harfbuzzFace)
+ {
+ return adoptRef(new RefCountedHarfbuzzFace(harfbuzzFace));
+ }
+
+ ~RefCountedHarfbuzzFace();
+
+ HB_FaceRec_* face() const { return m_harfbuzzFace; }
+
+ private:
+ RefCountedHarfbuzzFace(HB_FaceRec_* harfbuzzFace) : m_harfbuzzFace(harfbuzzFace)
+ {
+ }
+
+ HB_FaceRec_* m_harfbuzzFace;
+ };
+
+ void querySystemForRenderStyle();
+
+ // FIXME: Could SkAutoUnref be used here?
+ SkTypeface* m_typeface;
+ CString m_family;
+ float m_textSize;
+ bool m_fakeBold;
+ bool m_fakeItalic;
+ FontOrientation m_orientation;
+ FontRenderStyle m_style;
+ mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
+
+ SkTypeface* hashTableDeletedFontValue() const { return reinterpret_cast<SkTypeface*>(-1); }
+};
+
+} // namespace WebCore
+
+#endif // ifdef FontPlatformData_h
diff --git a/Source/WebCore/platform/graphics/chromium/FontRenderStyle.h b/Source/WebCore/platform/graphics/chromium/FontRenderStyle.h
new file mode 100644
index 0000000..6e2ae54
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontRenderStyle.h
@@ -0,0 +1,74 @@
+/* Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FontRenderStyle_h
+#define FontRenderStyle_h
+
+namespace WebCore {
+
+// FontRenderStyle describes the user's preferences for rendering a font at a
+// given size.
+struct FontRenderStyle {
+ enum {
+ NoPreference = 2,
+ };
+
+ FontRenderStyle()
+ : useBitmaps(0),
+ useAutoHint(0),
+ useHinting(0),
+ hintStyle(0),
+ useAntiAlias(0),
+ useSubpixel(0) { }
+
+ bool operator==(const FontRenderStyle& a) const
+ {
+ return useBitmaps == a.useBitmaps
+ && useAutoHint == a.useAutoHint
+ && useHinting == a.useHinting
+ && hintStyle == a.hintStyle
+ && useAntiAlias == a.useAntiAlias
+ && useSubpixel == a.useSubpixel;
+ }
+
+ // Each of the use* members below can take one of three values:
+ // 0: off
+ // 1: on
+ // NoPreference: no preference expressed
+ char useBitmaps; // use embedded bitmap strike if possible
+ char useAutoHint; // use 'auto' hinting (FreeType specific)
+ char useHinting; // hint glyphs to the pixel grid
+ char hintStyle; // level of hinting, 0..3
+ char useAntiAlias; // antialias glyph shapes
+ char useSubpixel; // use subpixel antialias
+};
+
+}
+
+#endif // FontRenderStyle_h
diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
new file mode 100644
index 0000000..bea0572
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009, 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FontUtilsChromiumWin.h"
+
+#include <limits>
+
+#include "PlatformString.h"
+#include "UniscribeHelper.h"
+#include <unicode/locid.h>
+#include <unicode/uchar.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+namespace {
+
+bool isFontPresent(const UChar* fontName)
+{
+ HFONT hfont = CreateFont(12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ fontName);
+ if (!hfont)
+ return false;
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont));
+ WCHAR actualFontName[LF_FACESIZE];
+ GetTextFace(dc, LF_FACESIZE, actualFontName);
+ actualFontName[LF_FACESIZE - 1] = 0;
+ SelectObject(dc, oldFont);
+ DeleteObject(hfont);
+ ReleaseDC(0, dc);
+ // We don't have to worry about East Asian fonts with locale-dependent
+ // names here for now.
+ return !wcscmp(fontName, actualFontName);
+}
+
+// A simple mapping from UScriptCode to family name. This is a sparse array,
+// which works well since the range of UScriptCode values is small.
+typedef const UChar* ScriptToFontMap[USCRIPT_CODE_LIMIT];
+
+void initializeScriptFontMap(ScriptToFontMap& scriptFontMap)
+{
+ struct FontMap {
+ UScriptCode script;
+ const UChar* family;
+ };
+
+ static const FontMap fontMap[] = {
+ {USCRIPT_LATIN, L"times new roman"},
+ {USCRIPT_GREEK, L"times new roman"},
+ {USCRIPT_CYRILLIC, L"times new roman"},
+ // FIXME: Consider trying new Vista fonts before XP fonts for CJK.
+ // Some Vista users do want to use Vista cleartype CJK fonts. If we
+ // did, the results of tests with CJK characters would have to be
+ // regenerated for Vista.
+ {USCRIPT_SIMPLIFIED_HAN, L"simsun"},
+ {USCRIPT_TRADITIONAL_HAN, L"pmingliu"},
+ {USCRIPT_HIRAGANA, L"ms pgothic"},
+ {USCRIPT_KATAKANA, L"ms pgothic"},
+ {USCRIPT_KATAKANA_OR_HIRAGANA, L"ms pgothic"},
+ {USCRIPT_HANGUL, L"gulim"},
+ {USCRIPT_THAI, L"tahoma"},
+ {USCRIPT_HEBREW, L"david"},
+ {USCRIPT_ARABIC, L"tahoma"},
+ {USCRIPT_DEVANAGARI, L"mangal"},
+ {USCRIPT_BENGALI, L"vrinda"},
+ {USCRIPT_GURMUKHI, L"raavi"},
+ {USCRIPT_GUJARATI, L"shruti"},
+ {USCRIPT_TAMIL, L"latha"},
+ {USCRIPT_TELUGU, L"gautami"},
+ {USCRIPT_KANNADA, L"tunga"},
+ {USCRIPT_GEORGIAN, L"sylfaen"},
+ {USCRIPT_ARMENIAN, L"sylfaen"},
+ {USCRIPT_THAANA, L"mv boli"},
+ {USCRIPT_CANADIAN_ABORIGINAL, L"euphemia"},
+ {USCRIPT_CHEROKEE, L"plantagenet cherokee"},
+ {USCRIPT_MONGOLIAN, L"mongolian balti"},
+ // For USCRIPT_COMMON, we map blocks to scripts when
+ // that makes sense.
+ };
+
+ struct ScriptToFontFamilies {
+ UScriptCode script;
+ const UChar** families;
+ };
+
+ // Kartika on Vista or earlier lacks the support for Chillu
+ // letters added to Unicode 5.1.
+ // Try AnjaliOldLipi (a very widely used Malaylalam font with the full
+ // Unicode 5.x support) before falling back to Kartika.
+ static const UChar* malayalamFonts[] = {L"AnjaliOldLipi", L"Lohit Malayalam", L"Kartika", L"Rachana", 0};
+ // Try Khmer OS before Vista fonts because 'Khmer OS' goes along better
+ // with Latin and looks better/larger for the same size.
+ static const UChar* khmerFonts[] = {L"Khmer OS", L"MoolBoran", L"DaunPenh", L"Code2000", 0};
+ // For the following 6 scripts, two or fonts are listed. The fonts in
+ // the 1st slot are not available on Windows XP. To support these
+ // scripts on XP, listed in the rest of slots are widely used
+ // fonts.
+ static const UChar* ethiopicFonts[] = {L"Nyala", L"Abyssinica SIL", L"Ethiopia Jiret", L"Visual Geez Unicode", L"GF Zemen Unicode", 0};
+ static const UChar* oriyaFonts[] = {L"Kalinga", L"ori1Uni", L"Lohit Oriya", 0};
+ static const UChar* laoFonts[] = {L"DokChampa", L"Saysettha OT", L"Phetsarath OT", L"Code2000", 0};
+ static const UChar* tibetanFonts[] = {L"Microsoft Himalaya", L"Jomolhari", L"Tibetan Machine Uni", 0};
+ static const UChar* sinhalaFonts[] = {L"Iskoola Pota", L"AksharUnicode", 0};
+ static const UChar* yiFonts[] = {L"Microsoft Yi Balti", L"Nuosu SIL", L"Code2000", 0};
+ // http://www.bethmardutho.org/support/meltho/download/index.php
+ static const UChar* syriacFonts[] = {L"Estrangelo Edessa", L"Estrangelo Nisibin", L"Code2000", 0};
+ // No Myanmar/Burmese font is shipped with Windows, yet. Try a few
+ // widely available/used ones that supports Unicode 5.1 or later.
+ static const UChar* myanmarFonts[] = {L"Padauk", L"Parabaik", L"Myanmar3", L"Code2000", 0};
+
+ static const ScriptToFontFamilies scriptToFontFamilies[] = {
+ {USCRIPT_MALAYALAM, malayalamFonts},
+ {USCRIPT_KHMER, khmerFonts},
+ {USCRIPT_ETHIOPIC, ethiopicFonts},
+ {USCRIPT_ORIYA, oriyaFonts},
+ {USCRIPT_LAO, laoFonts},
+ {USCRIPT_TIBETAN, tibetanFonts},
+ {USCRIPT_SINHALA, sinhalaFonts},
+ {USCRIPT_YI, yiFonts},
+ {USCRIPT_SYRIAC, syriacFonts},
+ {USCRIPT_MYANMAR, myanmarFonts},
+ };
+
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(fontMap); ++i)
+ scriptFontMap[fontMap[i].script] = fontMap[i].family;
+
+ // FIXME: Instead of scanning the hard-coded list, we have to
+ // use EnumFont* to 'inspect' fonts to pick up fonts covering scripts
+ // when it's possible (e.g. using OS/2 table). If we do that, this
+ // had better be pulled out of here.
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(scriptToFontFamilies); ++i) {
+ UScriptCode script = scriptToFontFamilies[i].script;
+ scriptFontMap[script] = 0;
+ const UChar** familyPtr = scriptToFontFamilies[i].families;
+ while (*familyPtr) {
+ if (isFontPresent(*familyPtr)) {
+ scriptFontMap[script] = *familyPtr;
+ break;
+ }
+ ++familyPtr;
+ }
+ }
+
+ // Initialize the locale-dependent mapping.
+ // Since Chrome synchronizes the ICU default locale with its UI locale,
+ // this ICU locale tells the current UI locale of Chrome.
+ icu::Locale locale = icu::Locale::getDefault();
+ const UChar* localeFamily = 0;
+ if (locale == icu::Locale::getJapanese())
+ localeFamily = scriptFontMap[USCRIPT_HIRAGANA];
+ else if (locale == icu::Locale::getKorean())
+ localeFamily = scriptFontMap[USCRIPT_HANGUL];
+ else if (locale == icu::Locale::getTraditionalChinese())
+ localeFamily = scriptFontMap[USCRIPT_TRADITIONAL_HAN];
+ else {
+ // For other locales, use the simplified Chinese font for Han.
+ localeFamily = scriptFontMap[USCRIPT_SIMPLIFIED_HAN];
+ }
+ if (localeFamily)
+ scriptFontMap[USCRIPT_HAN] = localeFamily;
+}
+
+// There are a lot of characters in USCRIPT_COMMON that can be covered
+// by fonts for scripts closely related to them. See
+// http://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:Script=Common:]
+// FIXME: make this more efficient with a wider coverage
+UScriptCode getScriptBasedOnUnicodeBlock(int ucs4)
+{
+ UBlockCode block = ublock_getCode(ucs4);
+ switch (block) {
+ case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
+ return USCRIPT_HAN;
+ case UBLOCK_HIRAGANA:
+ case UBLOCK_KATAKANA:
+ return USCRIPT_HIRAGANA;
+ case UBLOCK_ARABIC:
+ return USCRIPT_ARABIC;
+ case UBLOCK_THAI:
+ return USCRIPT_THAI;
+ case UBLOCK_GREEK:
+ return USCRIPT_GREEK;
+ case UBLOCK_DEVANAGARI:
+ // For Danda and Double Danda (U+0964, U+0965), use a Devanagari
+ // font for now although they're used by other scripts as well.
+ // Without a context, we can't do any better.
+ return USCRIPT_DEVANAGARI;
+ case UBLOCK_ARMENIAN:
+ return USCRIPT_ARMENIAN;
+ case UBLOCK_GEORGIAN:
+ return USCRIPT_GEORGIAN;
+ case UBLOCK_KANNADA:
+ return USCRIPT_KANNADA;
+ default:
+ return USCRIPT_COMMON;
+ }
+}
+
+UScriptCode getScript(int ucs4)
+{
+ UErrorCode err = U_ZERO_ERROR;
+ UScriptCode script = uscript_getScript(ucs4, &err);
+ // If script is invalid, common or inherited or there's an error,
+ // infer a script based on the unicode block of a character.
+ if (script <= USCRIPT_INHERITED || U_FAILURE(err))
+ script = getScriptBasedOnUnicodeBlock(ucs4);
+ return script;
+}
+
+const int kUndefinedAscent = std::numeric_limits<int>::min();
+
+// Given an HFONT, return the ascent. If GetTextMetrics fails,
+// kUndefinedAscent is returned, instead.
+int getAscent(HFONT hfont)
+{
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, hfont);
+ TEXTMETRIC tm;
+ BOOL gotMetrics = GetTextMetrics(dc, &tm);
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ return gotMetrics ? tm.tmAscent : kUndefinedAscent;
+}
+
+struct FontData {
+ FontData()
+ : hfont(0)
+ , ascent(kUndefinedAscent)
+ , scriptCache(0)
+ {
+ }
+
+ HFONT hfont;
+ int ascent;
+ mutable SCRIPT_CACHE scriptCache;
+};
+
+// Again, using hash_map does not earn us much here. page_cycler_test intl2
+// gave us a 'better' result with map than with hash_map even though they're
+// well-within 1-sigma of each other so that the difference is not significant.
+// On the other hand, some pages in intl2 seem to take longer to load with map
+// in the 1st pass. Need to experiment further.
+typedef HashMap<String, FontData> FontDataCache;
+
+} // namespace
+
+// FIXME: this is font fallback code version 0.1
+// - Cover all the scripts
+// - Get the default font for each script/generic family from the
+// preference instead of hardcoding in the source.
+// (at least, read values from the registry for IE font settings).
+// - Support generic families (from FontDescription)
+// - If the default font for a script is not available,
+// try some more fonts known to support it. Finally, we can
+// use EnumFontFamilies or similar APIs to come up with a list of
+// fonts supporting the script and cache the result.
+// - Consider using UnicodeSet (or UnicodeMap) converted from
+// GLYPHSET (BMP) or directly read from truetype cmap tables to
+// keep track of which character is supported by which font
+// - Update script_font_cache in response to WM_FONTCHANGE
+
+const UChar* getFontFamilyForScript(UScriptCode script,
+ FontDescription::GenericFamilyType generic)
+{
+ static ScriptToFontMap scriptFontMap;
+ static bool initialized = false;
+ if (!initialized) {
+ initializeScriptFontMap(scriptFontMap);
+ initialized = true;
+ }
+ if (script == USCRIPT_INVALID_CODE)
+ return 0;
+ ASSERT(script < USCRIPT_CODE_LIMIT);
+ return scriptFontMap[script];
+}
+
+// FIXME:
+// - Handle 'Inherited', 'Common' and 'Unknown'
+// (see http://www.unicode.org/reports/tr24/#Usage_Model )
+// For 'Inherited' and 'Common', perhaps we need to
+// accept another parameter indicating the previous family
+// and just return it.
+// - All the characters (or characters up to the point a single
+// font can cover) need to be taken into account
+const UChar* getFallbackFamily(const UChar* characters,
+ int length,
+ FontDescription::GenericFamilyType generic,
+ UChar32* charChecked,
+ UScriptCode* scriptChecked)
+{
+ ASSERT(characters && characters[0] && length > 0);
+ UScriptCode script = USCRIPT_COMMON;
+
+ // Sometimes characters common to script (e.g. space) is at
+ // the beginning of a string so that we need to skip them
+ // to get a font required to render the string.
+ int i = 0;
+ UChar32 ucs4 = 0;
+ while (i < length && script == USCRIPT_COMMON) {
+ U16_NEXT(characters, i, length, ucs4);
+ script = getScript(ucs4);
+ }
+
+ // For the full-width ASCII characters (U+FF00 - U+FF5E), use the font for
+ // Han (determined in a locale-dependent way above). Full-width ASCII
+ // characters are rather widely used in Japanese and Chinese documents and
+ // they're fully covered by Chinese, Japanese and Korean fonts.
+ if (0xFF00 < ucs4 && ucs4 < 0xFF5F)
+ script = USCRIPT_HAN;
+
+ if (script == USCRIPT_COMMON)
+ script = getScriptBasedOnUnicodeBlock(ucs4);
+
+ const UChar* family = getFontFamilyForScript(script, generic);
+ // Another lame work-around to cover non-BMP characters.
+ // If the font family for script is not found or the character is
+ // not in BMP (> U+FFFF), we resort to the hard-coded list of
+ // fallback fonts for now.
+ if (!family || ucs4 > 0xFFFF) {
+ int plane = ucs4 >> 16;
+ switch (plane) {
+ case 1:
+ family = L"code2001";
+ break;
+ case 2:
+ // Use a Traditional Chinese ExtB font if in Traditional Chinese locale.
+ // Otherwise, use a Simplified Chinese ExtB font. Windows Japanese
+ // fonts do support a small subset of ExtB (that are included in JIS X 0213),
+ // but its coverage is rather sparse.
+ // Eventually, this should be controlled by lang/xml:lang.
+ if (icu::Locale::getDefault() == icu::Locale::getTraditionalChinese())
+ family = L"pmingliu-extb";
+ else
+ family = L"simsun-extb";
+ break;
+ default:
+ family = L"lucida sans unicode";
+ }
+ }
+
+ if (charChecked)
+ *charChecked = ucs4;
+ if (scriptChecked)
+ *scriptChecked = script;
+ return family;
+}
+
+// Be aware that this is not thread-safe.
+bool getDerivedFontData(const UChar* family,
+ int style,
+ LOGFONT* logfont,
+ int* ascent,
+ HFONT* hfont,
+ SCRIPT_CACHE** scriptCache)
+{
+ ASSERT(logfont);
+ ASSERT(family);
+ ASSERT(*family);
+
+ // It does not matter that we leak font data when we exit.
+ static FontDataCache fontDataCache;
+
+ // FIXME: This comes up pretty high in the profile so that
+ // we need to measure whether using SHA256 (after coercing all the
+ // fields to char*) is faster than String::format.
+ String fontKey = String::format("%1d:%d:%ls", style, logfont->lfHeight, family);
+ FontDataCache::iterator iter = fontDataCache.find(fontKey);
+ FontData* derived;
+ if (iter == fontDataCache.end()) {
+ ASSERT(wcslen(family) < LF_FACESIZE);
+ wcscpy_s(logfont->lfFaceName, LF_FACESIZE, family);
+ // FIXME: CreateFontIndirect always comes up with
+ // a font even if there's no font matching the name. Need to
+ // check it against what we actually want (as is done in
+ // FontCacheWin.cpp)
+ pair<FontDataCache::iterator, bool> entry = fontDataCache.add(fontKey, FontData());
+ derived = &entry.first->second;
+ derived->hfont = CreateFontIndirect(logfont);
+ // GetAscent may return kUndefinedAscent, but we still want to
+ // cache it so that we won't have to call CreateFontIndirect once
+ // more for HFONT next time.
+ derived->ascent = getAscent(derived->hfont);
+ } else {
+ derived = &iter->second;
+ // Last time, GetAscent failed so that only HFONT was
+ // cached. Try once more assuming that TryPreloadFont
+ // was called by a caller between calls.
+ if (kUndefinedAscent == derived->ascent)
+ derived->ascent = getAscent(derived->hfont);
+ }
+ *hfont = derived->hfont;
+ *ascent = derived->ascent;
+ *scriptCache = &(derived->scriptCache);
+ return *ascent != kUndefinedAscent;
+}
+
+int getStyleFromLogfont(const LOGFONT* logfont)
+{
+ // FIXME: consider defining UNDEFINED or INVALID for style and
+ // returning it when logfont is 0
+ if (!logfont) {
+ ASSERT_NOT_REACHED();
+ return FontStyleNormal;
+ }
+ return (logfont->lfItalic ? FontStyleItalic : FontStyleNormal) |
+ (logfont->lfUnderline ? FontStyleUnderlined : FontStyleNormal) |
+ (logfont->lfWeight >= 700 ? FontStyleBold : FontStyleNormal);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
new file mode 100644
index 0000000..b637ede
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// A collection of utilities for font handling.
+
+// FIXME: Move all methods to the files that have their callsites and remove this file.
+// *Utils files are not very WebKit-ty.
+
+#ifndef FontUtilsChromiumWin_h
+#define FontUtilsChromiumWin_h
+
+#include <usp10.h>
+#include <wchar.h>
+#include <windows.h>
+
+#include "FontDescription.h"
+#include <unicode/uscript.h>
+
+namespace WebCore {
+
+// Return a font family that supports a script and belongs to |generic| font
+// family. It can return NULL and a caller has to implement its own fallback.
+const UChar* getFontFamilyForScript(UScriptCode, FontDescription::GenericFamilyType);
+
+// Return a font family that can render |characters| based on
+// what script characters belong to. When char_checked is non-NULL,
+// it's filled with the character used to determine the script.
+// When script_checked is non-NULL, the script used to determine
+// the family is returned.
+// FIXME: This function needs a total overhaul.
+const UChar* getFallbackFamily(const UChar* characters, int length,
+ FontDescription::GenericFamilyType,
+ UChar32* charChecked,
+ UScriptCode* scriptChecked);
+
+// Derive a new HFONT by replacing lfFaceName of LOGFONT with |family|,
+// calculate the ascent for the derived HFONT, and initialize SCRIPT_CACHE
+// in FontData.
+// |style| is only used for cache key generation. |style| is
+// bit-wise OR of BOLD(1), UNDERLINED(2) and ITALIC(4) and
+// should match what's contained in LOGFONT. It should be calculated
+// by calling GetStyleFromLogFont.
+// Returns false if the font is not accessible, in which case |ascent| field
+// of |fontdata| is set to kUndefinedAscent.
+// Be aware that this is not thread-safe.
+// FIXME: Instead of having three out params, we'd better have one
+// (|*FontData|), but somehow it mysteriously messes up the layout for
+// certain complex script pages (e.g. hi.wikipedia.org) and also crashes
+// at the start-up if recently visited page list includes pages with complex
+// scripts in their title. Moreover, somehow the very first-pass of
+// intl2 page-cycler test is noticeably slower with one out param than
+// the current version although the subsequent 9 passes take about the
+// same time.
+bool getDerivedFontData(const UChar* family, int style, LOGFONT*, int* ascent, HFONT*, SCRIPT_CACHE**);
+
+enum {
+ FontStyleNormal = 0,
+ FontStyleBold = 1,
+ FontStyleItalic = 2,
+ FontStyleUnderlined = 4
+};
+
+// Derive style (bit-wise OR of FONT_STYLE_BOLD, FONT_STYLE_UNDERLINED, and
+// FONT_STYLE_ITALIC) from LOGFONT. Returns 0 if |*logfont| is NULL.
+int getStyleFromLogfont(const LOGFONT*);
+
+} // namespace WebCore
+
+#endif // FontUtilsChromiumWin_h
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
new file mode 100644
index 0000000..697cf5e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "GLES2Canvas.h"
+
+#include "DrawingBuffer.h"
+#include "FloatRect.h"
+#include "GraphicsContext3D.h"
+#include "IntRect.h"
+#include "PlatformString.h"
+#include "SharedGraphicsContext3D.h"
+#include "SolidFillShader.h"
+#include "TexShader.h"
+#include "Texture.h"
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+struct GLES2Canvas::State {
+ State()
+ : m_fillColor(0, 0, 0, 255)
+ , m_alpha(1.0f)
+ , m_compositeOp(CompositeSourceOver)
+ {
+ }
+ Color m_fillColor;
+ float m_alpha;
+ CompositeOperator m_compositeOp;
+ AffineTransform m_ctm;
+};
+
+GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawingBuffer, const IntSize& size)
+ : m_size(size)
+ , m_context(context)
+ , m_drawingBuffer(drawingBuffer)
+ , m_state(0)
+{
+ m_flipMatrix.translate(-1.0f, 1.0f);
+ m_flipMatrix.scale(2.0f / size.width(), -2.0f / size.height());
+
+ m_stateStack.append(State());
+ m_state = &m_stateStack.last();
+}
+
+GLES2Canvas::~GLES2Canvas()
+{
+}
+
+void GLES2Canvas::bindFramebuffer()
+{
+ m_drawingBuffer->bind();
+}
+
+void GLES2Canvas::clearRect(const FloatRect& rect)
+{
+ bindFramebuffer();
+ if (m_state->m_ctm.isIdentity()) {
+ m_context->scissor(rect);
+ m_context->enable(GraphicsContext3D::SCISSOR_TEST);
+ m_context->clearColor(Color(RGBA32(0)));
+ m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ } else {
+ save();
+ setCompositeOperation(CompositeClear);
+ fillRect(rect, Color(RGBA32(0)), ColorSpaceDeviceRGB);
+ restore();
+ }
+}
+
+void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
+{
+ m_context->applyCompositeOperator(m_state->m_compositeOp);
+ m_context->useQuadVertices();
+
+ AffineTransform matrix(m_flipMatrix);
+ matrix.multLeft(m_state->m_ctm);
+ matrix.translate(rect.x(), rect.y());
+ matrix.scale(rect.width(), rect.height());
+
+ m_context->useFillSolidProgram(matrix, color);
+
+ bindFramebuffer();
+ m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
+}
+
+void GLES2Canvas::fillRect(const FloatRect& rect)
+{
+ fillRect(rect, m_state->m_fillColor, ColorSpaceDeviceRGB);
+}
+
+void GLES2Canvas::setFillColor(const Color& color, ColorSpace colorSpace)
+{
+ m_state->m_fillColor = color;
+}
+
+void GLES2Canvas::setAlpha(float alpha)
+{
+ m_state->m_alpha = alpha;
+}
+
+void GLES2Canvas::translate(float x, float y)
+{
+ m_state->m_ctm.translate(x, y);
+}
+
+void GLES2Canvas::rotate(float angleInRadians)
+{
+ m_state->m_ctm.rotate(angleInRadians * (180.0f / M_PI));
+}
+
+void GLES2Canvas::scale(const FloatSize& size)
+{
+ m_state->m_ctm.scale(size.width(), size.height());
+}
+
+void GLES2Canvas::concatCTM(const AffineTransform& affine)
+{
+ m_state->m_ctm.multLeft(affine);
+}
+
+void GLES2Canvas::save()
+{
+ m_stateStack.append(State(m_stateStack.last()));
+ m_state = &m_stateStack.last();
+}
+
+void GLES2Canvas::restore()
+{
+ ASSERT(!m_stateStack.isEmpty());
+ m_stateStack.removeLast();
+ m_state = &m_stateStack.last();
+}
+
+void GLES2Canvas::drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
+{
+ m_context->applyCompositeOperator(compositeOp);
+
+ m_context->useQuadVertices();
+ m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
+
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture);
+
+ drawQuad(textureSize, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha);
+}
+
+void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp)
+{
+ drawTexturedRect(texture, srcRect, dstRect, m_state->m_ctm, m_state->m_alpha, colorSpace, compositeOp);
+}
+
+
+void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp)
+{
+ m_context->applyCompositeOperator(compositeOp);
+ const TilingData& tiles = texture->tiles();
+ IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect);
+
+ m_context->useQuadVertices();
+ m_context->setActiveTexture(GraphicsContext3D::TEXTURE0);
+
+ for (int y = tileIdxRect.y(); y <= tileIdxRect.bottom(); y++) {
+ for (int x = tileIdxRect.x(); x <= tileIdxRect.right(); x++)
+ drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform, alpha);
+ }
+}
+
+void GLES2Canvas::drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha)
+{
+ if (dstRect.isEmpty())
+ return;
+
+ const TilingData& tiles = texture->tiles();
+
+ texture->bindTile(tile);
+
+ FloatRect srcRectClippedInTileSpace;
+ FloatRect dstRectIntersected;
+ tiles.intersectDrawQuad(srcRect, dstRect, tile, &srcRectClippedInTileSpace, &dstRectIntersected);
+
+ IntRect tileBoundsWithBorder = tiles.tileBoundsWithBorder(tile);
+
+ drawQuad(tileBoundsWithBorder.size(), srcRectClippedInTileSpace, dstRectIntersected, transform, alpha);
+}
+
+void GLES2Canvas::drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha)
+{
+ AffineTransform matrix(m_flipMatrix);
+ matrix.multLeft(transform);
+ matrix.translate(dstRect.x(), dstRect.y());
+ matrix.scale(dstRect.width(), dstRect.height());
+
+ AffineTransform texMatrix;
+ texMatrix.scale(1.0f / textureSize.width(), 1.0f / textureSize.height());
+ texMatrix.translate(srcRect.x(), srcRect.y());
+ texMatrix.scale(srcRect.width(), srcRect.height());
+
+ bindFramebuffer();
+
+ m_context->useTextureProgram(matrix, texMatrix, alpha);
+ m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4);
+ checkGLError("glDrawArrays");
+}
+
+void GLES2Canvas::setCompositeOperation(CompositeOperator op)
+{
+ m_state->m_compositeOp = op;
+}
+
+Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height)
+{
+ return m_context->createTexture(ptr, format, width, height);
+}
+
+Texture* GLES2Canvas::getTexture(NativeImagePtr ptr)
+{
+ return m_context->getTexture(ptr);
+}
+
+void GLES2Canvas::checkGLError(const char* header)
+{
+#ifndef NDEBUG
+ unsigned err;
+ while ((err = m_context->getError()) != GraphicsContext3D::NO_ERROR) {
+ const char* errorStr = "*** UNKNOWN ERROR ***";
+ switch (err) {
+ case GraphicsContext3D::INVALID_ENUM:
+ errorStr = "GraphicsContext3D::INVALID_ENUM";
+ break;
+ case GraphicsContext3D::INVALID_VALUE:
+ errorStr = "GraphicsContext3D::INVALID_VALUE";
+ break;
+ case GraphicsContext3D::INVALID_OPERATION:
+ errorStr = "GraphicsContext3D::INVALID_OPERATION";
+ break;
+ case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
+ errorStr = "GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION";
+ break;
+ case GraphicsContext3D::OUT_OF_MEMORY:
+ errorStr = "GraphicsContext3D::OUT_OF_MEMORY";
+ break;
+ }
+ if (header)
+ LOG_ERROR("%s: %s", header, errorStr);
+ else
+ LOG_ERROR("%s", errorStr);
+ }
+#endif
+}
+
+}
+
diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
new file mode 100644
index 0000000..6fc1a0e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GLES2Canvas_h
+#define GLES2Canvas_h
+
+#include "AffineTransform.h"
+#include "Color.h"
+#include "ColorSpace.h"
+#include "GraphicsTypes.h"
+#include "ImageSource.h"
+#include "Texture.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Color;
+class DrawingBuffer;
+class FloatRect;
+class GraphicsContext3D;
+class SharedGraphicsContext3D;
+
+class GLES2Canvas : public Noncopyable {
+public:
+ GLES2Canvas(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&);
+ ~GLES2Canvas();
+
+ void fillRect(const FloatRect&, const Color&, ColorSpace);
+ void fillRect(const FloatRect&);
+ void clearRect(const FloatRect&);
+ void setFillColor(const Color&, ColorSpace);
+ void setAlpha(float alpha);
+ void setCompositeOperation(CompositeOperator);
+ void translate(float x, float y);
+ void rotate(float angleInRadians);
+ void scale(const FloatSize&);
+ void concatCTM(const AffineTransform&);
+
+ void save();
+ void restore();
+
+ // non-standard functions
+ // These are not standard GraphicsContext functions, and should be pushed
+ // down into a PlatformContextGLES2 at some point.
+ void drawTexturedRect(unsigned texture, const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
+ void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator);
+ void drawTexturedRect(Texture*, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace, CompositeOperator);
+ Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height);
+ Texture* getTexture(NativeImagePtr);
+
+ SharedGraphicsContext3D* context() const { return m_context; }
+
+ void bindFramebuffer();
+
+ DrawingBuffer* drawingBuffer() const { return m_drawingBuffer; }
+
+private:
+ void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
+ void drawQuad(const IntSize& textureSize, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha);
+ void applyCompositeOperator(CompositeOperator);
+ void checkGLError(const char* header);
+
+ IntSize m_size;
+
+ SharedGraphicsContext3D* m_context;
+ DrawingBuffer* m_drawingBuffer;
+
+ struct State;
+ WTF::Vector<State> m_stateStack;
+ State* m_state;
+ AffineTransform m_flipMatrix;
+};
+
+}
+
+#endif // GLES2Canvas_h
diff --git a/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
new file mode 100644
index 0000000..e71f66a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/GlyphPageTreeNodeChromiumWin.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2008, 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <windows.h>
+#include <vector>
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "GlyphPageTreeNode.h"
+#include "SimpleFontData.h"
+#include "UniscribeHelperTextRun.h"
+#include "WindowsVersion.h"
+
+namespace WebCore {
+
+// Fills one page of font data pointers with 0 to indicate that there
+// are no glyphs for the characters.
+static void fillEmptyGlyphs(GlyphPage* page)
+{
+ for (int i = 0; i < GlyphPage::size; ++i)
+ page->setGlyphDataForIndex(i, 0, 0);
+}
+
+// Lazily initializes space glyph
+static Glyph initSpaceGlyph(HDC dc, Glyph* spaceGlyph)
+{
+ if (*spaceGlyph)
+ return *spaceGlyph;
+
+ static wchar_t space = ' ';
+ GetGlyphIndices(dc, &space, 1, spaceGlyph, 0);
+ return *spaceGlyph;
+}
+
+// Fills |length| glyphs starting at |offset| in a |page| in the Basic
+// Multilingual Plane (<= U+FFFF). The input buffer size should be the
+// same as |length|. We can use the standard Windows GDI functions here.
+// Returns true if any glyphs were found.
+static bool fillBMPGlyphs(unsigned offset,
+ unsigned length,
+ UChar* buffer,
+ GlyphPage* page,
+ const SimpleFontData* fontData,
+ bool recurse)
+{
+ HDC dc = GetDC((HWND)0);
+ HGDIOBJ oldFont = SelectObject(dc, fontData->platformData().hfont());
+
+ TEXTMETRIC tm = {0};
+ if (!GetTextMetrics(dc, &tm)) {
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+
+ if (recurse) {
+ if (ChromiumBridge::ensureFontLoaded(fontData->platformData().hfont()))
+ return fillBMPGlyphs(offset, length, buffer, page, fontData, false);
+ else {
+ fillEmptyGlyphs(page);
+ return false;
+ }
+ } else {
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401
+ LOG_ERROR("Unable to get the text metrics after second attempt");
+ fillEmptyGlyphs(page);
+ return false;
+ }
+ }
+
+ // FIXME: GetGlyphIndices() sets each item of localGlyphBuffer[]
+ // with the one of the values listed below.
+ // * With the GGI_MARK_NONEXISTING_GLYPHS flag
+ // + If the font has a glyph available for the character,
+ // localGlyphBuffer[i] > 0x0.
+ // + If the font does not have glyphs available for the character,
+ // localGlyphBuffer[i] = 0x1F (TrueType Collection?) or
+ // 0xFFFF (OpenType?).
+ // * Without the GGI_MARK_NONEXISTING_GLYPHS flag
+ // + If the font has a glyph available for the character,
+ // localGlyphBuffer[i] > 0x0.
+ // + If the font does not have glyphs available for the character,
+ // localGlyphBuffer[i] = 0x80.
+ // (Windows automatically assigns the glyph for a box character to
+ // prevent ExtTextOut() from returning errors.)
+ // To avoid from hurting the rendering performance, this code just
+ // tells WebKit whether or not the all glyph indices for the given
+ // characters are 0x80 (i.e. a possibly-invalid glyph) and let it
+ // use alternative fonts for the characters.
+ // Although this may cause a problem, it seems to work fine as far as I
+ // have tested. (Obviously, I need more tests.)
+ WORD localGlyphBuffer[GlyphPage::size];
+
+ // FIXME: I find some Chinese characters can not be correctly displayed
+ // when call GetGlyphIndices without flag GGI_MARK_NONEXISTING_GLYPHS,
+ // because the corresponding glyph index is set as 0x20 when current font
+ // does not have glyphs available for the character. According a blog post
+ // http://blogs.msdn.com/michkap/archive/2006/06/28/649791.aspx
+ // I think we should switch to the way about calling GetGlyphIndices with
+ // flag GGI_MARK_NONEXISTING_GLYPHS, it should be OK according the
+ // description of MSDN.
+ // Also according to Jungshik and Hironori's suggestion and modification
+ // we treat turetype and raster Font as different way when windows version
+ // is less than Vista.
+ GetGlyphIndices(dc, buffer, length, localGlyphBuffer, GGI_MARK_NONEXISTING_GLYPHS);
+
+ // Copy the output to the GlyphPage
+ bool haveGlyphs = false;
+ int invalidGlyph = 0xFFFF;
+ const DWORD cffTableTag = 0x20464643; // 4-byte identifier for OpenType CFF table ('CFF ').
+ if (!isVistaOrNewer() && !(tm.tmPitchAndFamily & TMPF_TRUETYPE) && (GetFontData(dc, cffTableTag, 0, 0, 0) == GDI_ERROR))
+ invalidGlyph = 0x1F;
+
+ Glyph spaceGlyph = 0; // Glyph for a space. Lazily filled.
+
+ for (unsigned i = 0; i < length; i++) {
+ UChar c = buffer[i];
+ Glyph glyph = localGlyphBuffer[i];
+ const SimpleFontData* glyphFontData = fontData;
+ // When this character should be a space, we ignore whatever the font
+ // says and use a space. Otherwise, if fonts don't map one of these
+ // space or zero width glyphs, we will get a box.
+ if (Font::treatAsSpace(c)) {
+ // Hard code the glyph indices for characters that should be
+ // treated like spaces.
+ glyph = initSpaceGlyph(dc, &spaceGlyph);
+ } else if (glyph == invalidGlyph) {
+ // WebKit expects both the glyph index and FontData
+ // pointer to be 0 if the glyph is not present
+ glyph = 0;
+ glyphFontData = 0;
+ } else
+ haveGlyphs = true;
+ page->setGlyphDataForCharacter(offset + i, glyph, glyphFontData);
+ }
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+ return haveGlyphs;
+}
+
+// For non-BMP characters, each is two words (UTF-16) and the input buffer
+// size is 2 * |length|. Since GDI doesn't know how to handle non-BMP
+// characters, we must use Uniscribe to tell us the glyph indices.
+//
+// We don't want to call this in the case of "regular" characters since some
+// fonts may not have the correct combining rules for accents. See the notes
+// at the bottom of ScriptGetCMap. We can't use ScriptGetCMap, though, since
+// it doesn't seem to support UTF-16, despite what this blog post says:
+// http://blogs.msdn.com/michkap/archive/2006/06/29/650680.aspx
+//
+// So we fire up the full Uniscribe doohicky, give it our string, and it will
+// correctly handle the UTF-16 for us. The hard part is taking this and getting
+// the glyph indices back out that correspond to the correct input characters,
+// since they may be missing.
+//
+// Returns true if any glyphs were found.
+static bool fillNonBMPGlyphs(unsigned offset,
+ unsigned length,
+ UChar* buffer,
+ GlyphPage* page,
+ const SimpleFontData* fontData)
+{
+ bool haveGlyphs = false;
+
+ UniscribeHelperTextRun state(buffer, length * 2, false,
+ fontData->platformData().hfont(),
+ fontData->platformData().scriptCache(),
+ fontData->platformData().scriptFontProperties());
+ state.setInhibitLigate(true);
+ state.setDisableFontFallback(true);
+ state.init();
+
+ for (unsigned i = 0; i < length; i++) {
+ // Each character in this input buffer is a surrogate pair, which
+ // consists of two UChars. So, the offset for its i-th character is
+ // (i * 2).
+ WORD glyph = state.firstGlyphForCharacter(i * 2);
+ if (glyph) {
+ haveGlyphs = true;
+ page->setGlyphDataForIndex(offset + i, glyph, fontData);
+ } else
+ // Clear both glyph and fontData fields.
+ page->setGlyphDataForIndex(offset + i, 0, 0);
+ }
+ return haveGlyphs;
+}
+
+// We're supposed to return true if there are any glyphs in the range
+// specified by |offset| and |length| in our font,
+// false if there are none.
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* characterBuffer,
+ unsigned bufferLength, const SimpleFontData* fontData)
+{
+ // We have to handle BMP and non-BMP characters differently.
+ // FIXME: Add assertions to make sure that buffer is entirely in BMP
+ // or entirely in non-BMP.
+ if (bufferLength == length)
+ return fillBMPGlyphs(offset, length, characterBuffer, this, fontData, true);
+
+ if (bufferLength == 2 * length) {
+ // A non-BMP input buffer will be twice as long as output glyph buffer
+ // because each character in the non-BMP input buffer will be
+ // represented by a surrogate pair (two UChar's).
+ return fillNonBMPGlyphs(offset, length, characterBuffer, this, fontData);
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
new file mode 100644
index 0000000..5e8d148
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/** FIXME
+ * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp
+ * (and hence it includes both copyrights)
+ * Ideally the common code (mostly the code that keeps track of the layer hierarchy)
+ * should be kept separate and shared between platforms. It would be a well worthwhile
+ * effort once the Windows implementation (binaries and headers) of CoreAnimation is
+ * checked in to the WebKit repository. Until then only Apple can make this happen.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayerChromium.h"
+
+#include "Canvas2DLayerChromium.h"
+#include "ContentLayerChromium.h"
+#include "DrawingBuffer.h"
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "Image.h"
+#include "ImageLayerChromium.h"
+#include "LayerChromium.h"
+#include "PlatformString.h"
+#include "SystemTime.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/StringExtras.h>
+#include <wtf/text/CString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static void setLayerBorderColor(LayerChromium& layer, const Color& color)
+{
+ layer.setBorderColor(color);
+}
+
+static void clearBorderColor(LayerChromium& layer)
+{
+ layer.setBorderColor(static_cast<RGBA32>(0));
+}
+
+static void setLayerBackgroundColor(LayerChromium& layer, const Color& color)
+{
+ layer.setBackgroundColor(color);
+}
+
+static void clearLayerBackgroundColor(LayerChromium& layer)
+{
+ layer.setBackgroundColor(static_cast<RGBA32>(0));
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerChromium(client);
+}
+
+GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+{
+ m_layer = ContentLayerChromium::create(this);
+
+ updateDebugIndicators();
+}
+
+GraphicsLayerChromium::~GraphicsLayerChromium()
+{
+ if (m_layer)
+ m_layer->setOwner(0);
+ if (m_contentsLayer)
+ m_contentsLayer->setOwner(0);
+ if (m_transformLayer)
+ m_transformLayer->setOwner(0);
+}
+
+void GraphicsLayerChromium::setName(const String& inName)
+{
+ String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
+ GraphicsLayer::setName(name);
+}
+
+bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which
+ // will end up calling updateSublayerList() N times.
+ if (childrenChanged)
+ updateSublayerList();
+
+ return childrenChanged;
+}
+
+void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
+{
+ GraphicsLayer::addChild(childLayer);
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
+{
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ updateSublayerList();
+}
+
+bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ updateSublayerList();
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerChromium::removeFromParent()
+{
+ GraphicsLayer::removeFromParent();
+ layerForSuperlayer()->removeFromSuperlayer();
+}
+
+void GraphicsLayerChromium::setPosition(const FloatPoint& point)
+{
+ GraphicsLayer::setPosition(point);
+ updateLayerPosition();
+}
+
+void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
+{
+ if (point == m_anchorPoint)
+ return;
+
+ GraphicsLayer::setAnchorPoint(point);
+ updateAnchorPoint();
+}
+
+void GraphicsLayerChromium::setSize(const FloatSize& size)
+{
+ if (size == m_size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ updateLayerSize();
+}
+
+void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
+{
+ if (transform == m_transform)
+ return;
+
+ GraphicsLayer::setTransform(transform);
+ updateTransform();
+}
+
+void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
+{
+ if (transform == m_childrenTransform)
+ return;
+
+ GraphicsLayer::setChildrenTransform(transform);
+ updateChildrenTransform();
+}
+
+void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
+{
+ if (preserves3D == m_preserves3D)
+ return;
+
+ GraphicsLayer::setPreserves3D(preserves3D);
+ updateLayerPreserves3D();
+}
+
+void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
+{
+ if (masksToBounds == m_masksToBounds)
+ return;
+
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ updateMasksToBounds();
+}
+
+void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
+{
+ if (drawsContent == m_drawsContent)
+ return;
+
+ GraphicsLayer::setDrawsContent(drawsContent);
+ updateLayerDrawsContent();
+}
+
+void GraphicsLayerChromium::setBackgroundColor(const Color& color)
+{
+ if (m_backgroundColorSet && m_backgroundColor == color)
+ return;
+
+ GraphicsLayer::setBackgroundColor(color);
+
+ m_contentsLayerHasBackgroundColor = true;
+ updateLayerBackgroundColor();
+}
+
+void GraphicsLayerChromium::clearBackgroundColor()
+{
+ if (!m_backgroundColorSet)
+ return;
+
+ GraphicsLayer::clearBackgroundColor();
+ clearLayerBackgroundColor(*m_contentsLayer);
+}
+
+void GraphicsLayerChromium::setContentsOpaque(bool opaque)
+{
+ if (m_contentsOpaque == opaque)
+ return;
+
+ GraphicsLayer::setContentsOpaque(opaque);
+ updateContentsOpaque();
+}
+
+void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
+{
+ if (m_backfaceVisibility == visible)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(visible);
+ updateBackfaceVisibility();
+}
+
+void GraphicsLayerChromium::setOpacity(float opacity)
+{
+ float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
+
+ if (m_opacity == clampedOpacity)
+ return;
+
+ GraphicsLayer::setOpacity(clampedOpacity);
+ primaryLayer()->setOpacity(opacity);
+}
+
+void GraphicsLayerChromium::setContentsNeedsDisplay()
+{
+ if (m_contentsLayer)
+ m_contentsLayer->setNeedsDisplay();
+}
+
+void GraphicsLayerChromium::setNeedsDisplay()
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay();
+}
+
+void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (drawsContent())
+ m_layer->setNeedsDisplay(rect);
+}
+
+void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
+{
+ if (rect == m_contentsRect)
+ return;
+
+ GraphicsLayer::setContentsRect(rect);
+ updateContentsRect();
+}
+
+void GraphicsLayerChromium::setContentsToImage(Image* image)
+{
+ bool childrenChanged = false;
+ if (image) {
+ if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) {
+ RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this);
+ setupContentsLayer(imageLayer.get());
+ m_contentsLayer = imageLayer;
+ m_contentsLayerPurpose = ContentsLayerForImage;
+ childrenChanged = true;
+ }
+ ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get());
+ imageLayer->setContents(image);
+ updateContentsRect();
+ } else {
+ if (m_contentsLayer) {
+ childrenChanged = true;
+
+ // The old contents layer will be removed via updateSublayerList.
+ m_contentsLayer = 0;
+ }
+ }
+
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
+{
+ bool childrenChanged = false;
+ if (platformLayer) {
+ platformLayer->setOwner(this);
+ if (m_contentsLayer.get() != platformLayer) {
+ setupContentsLayer(platformLayer);
+ m_contentsLayer = platformLayer;
+ m_contentsLayerPurpose = ContentsLayerForCanvas;
+ childrenChanged = true;
+ }
+ m_contentsLayer->setNeedsDisplay();
+ updateContentsRect();
+ } else {
+ if (m_contentsLayer) {
+ childrenChanged = true;
+
+ // The old contents layer will be removed via updateSublayerList.
+ m_contentsLayer = 0;
+ }
+ }
+
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
+{
+ bool childrenChanged = false;
+ if (layer) {
+ if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) {
+ setupContentsLayer(layer);
+ m_contentsLayer = layer;
+ m_contentsLayerPurpose = ContentsLayerForVideo;
+ childrenChanged = true;
+ }
+ layer->setOwner(this);
+ layer->setNeedsDisplay();
+ updateContentsRect();
+ } else {
+ if (m_contentsLayer) {
+ childrenChanged = true;
+
+ // The old contents layer will be removed via updateSublayerList.
+ m_contentsLayer = 0;
+ }
+ }
+
+ if (childrenChanged)
+ updateSublayerList();
+}
+
+PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const
+{
+ return m_transformLayer ? m_transformLayer.get() : m_layer.get();
+}
+
+PlatformLayer* GraphicsLayerChromium::platformLayer() const
+{
+ return primaryLayer();
+}
+
+void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
+{
+ if (color.isValid())
+ setLayerBackgroundColor(*m_layer, color);
+ else
+ clearLayerBackgroundColor(*m_layer);
+}
+
+void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
+{
+ if (color.isValid()) {
+ setLayerBorderColor(*m_layer, color);
+ m_layer->setBorderWidth(borderWidth);
+ } else {
+ clearBorderColor(*m_layer);
+ m_layer->setBorderWidth(0);
+ }
+}
+
+void GraphicsLayerChromium::updateSublayerList()
+{
+ Vector<RefPtr<LayerChromium> > newSublayers;
+
+ if (m_transformLayer) {
+ // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
+ newSublayers.append(m_layer.get());
+ } else if (m_contentsLayer) {
+ // FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
+ newSublayers.append(m_contentsLayer.get());
+ }
+
+ const Vector<GraphicsLayer*>& childLayers = children();
+ size_t numChildren = childLayers.size();
+ for (size_t i = 0; i < numChildren; ++i) {
+ GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);
+
+ LayerChromium* childLayer = curChild->layerForSuperlayer();
+ newSublayers.append(childLayer);
+ }
+
+ for (size_t i = 0; i < newSublayers.size(); ++i)
+ newSublayers[i]->removeFromSuperlayer();
+
+ if (m_transformLayer) {
+ m_transformLayer->setSublayers(newSublayers);
+
+ if (m_contentsLayer) {
+ // If we have a transform layer, then the contents layer is parented in the
+ // primary layer (which is itself a child of the transform layer).
+ m_layer->removeAllSublayers();
+ m_layer->addSublayer(m_contentsLayer);
+ }
+ } else
+ m_layer->setSublayers(newSublayers);
+}
+
+void GraphicsLayerChromium::updateLayerPosition()
+{
+ // Position is offset on the layer by the layer anchor point.
+ FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(),
+ m_position.y() + m_anchorPoint.y() * m_size.height());
+
+ primaryLayer()->setPosition(layerPosition);
+}
+
+void GraphicsLayerChromium::updateLayerSize()
+{
+ IntSize layerSize(m_size.width(), m_size.height());
+ if (m_transformLayer) {
+ m_transformLayer->setBounds(layerSize);
+ // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
+ FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2);
+ m_layer->setPosition(centerPoint);
+ }
+
+ m_layer->setBounds(layerSize);
+
+ // Note that we don't resize m_contentsLayer. It's up the caller to do that.
+
+ // If we've changed the bounds, we need to recalculate the position
+ // of the layer, taking anchor point into account.
+ updateLayerPosition();
+}
+
+void GraphicsLayerChromium::updateAnchorPoint()
+{
+ primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
+ primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
+ updateLayerPosition();
+}
+
+void GraphicsLayerChromium::updateTransform()
+{
+ primaryLayer()->setTransform(m_transform);
+}
+
+void GraphicsLayerChromium::updateChildrenTransform()
+{
+ primaryLayer()->setSublayerTransform(m_childrenTransform);
+}
+
+void GraphicsLayerChromium::updateMasksToBounds()
+{
+ m_layer->setMasksToBounds(m_masksToBounds);
+ updateDebugIndicators();
+}
+
+void GraphicsLayerChromium::updateContentsOpaque()
+{
+ m_layer->setOpaque(m_contentsOpaque);
+}
+
+void GraphicsLayerChromium::updateBackfaceVisibility()
+{
+ m_layer->setDoubleSided(m_backfaceVisibility);
+}
+
+void GraphicsLayerChromium::updateLayerPreserves3D()
+{
+ if (m_preserves3D && !m_transformLayer) {
+ // Create the transform layer.
+ m_transformLayer = LayerChromium::create(this);
+
+ // Copy the position from this layer.
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f));
+
+ m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
+ TransformationMatrix identity;
+ m_layer->setTransform(identity);
+
+ // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
+ m_layer->setOpacity(1);
+
+ // Move this layer to be a child of the transform layer.
+ if (m_layer->superlayer())
+ m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get());
+ m_transformLayer->addSublayer(m_layer.get());
+
+ updateSublayerList();
+ } else if (!m_preserves3D && m_transformLayer) {
+ // Relace the transformLayer in the parent with this layer.
+ m_layer->removeFromSuperlayer();
+ m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get());
+
+ // Release the transform layer.
+ m_transformLayer = 0;
+
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ updateSublayerList();
+ }
+
+ updateOpacityOnLayer();
+}
+
+void GraphicsLayerChromium::updateLayerDrawsContent()
+{
+ if (m_drawsContent)
+ m_layer->setNeedsDisplay();
+
+ updateDebugIndicators();
+}
+
+void GraphicsLayerChromium::updateLayerBackgroundColor()
+{
+ if (!m_contentsLayer)
+ return;
+
+ // We never create the contents layer just for background color yet.
+ if (m_backgroundColorSet)
+ setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
+ else
+ clearLayerBackgroundColor(*m_contentsLayer);
+}
+
+void GraphicsLayerChromium::updateContentsVideo()
+{
+ // FIXME: Implement
+}
+
+void GraphicsLayerChromium::updateContentsRect()
+{
+ if (!m_contentsLayer)
+ return;
+
+ m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
+ m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
+}
+
+void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer)
+{
+ if (contentsLayer == m_contentsLayer)
+ return;
+
+ if (m_contentsLayer) {
+ m_contentsLayer->removeFromSuperlayer();
+ m_contentsLayer = 0;
+ }
+
+ if (contentsLayer) {
+ m_contentsLayer = contentsLayer;
+
+ m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
+
+ // Insert the content layer first. Video elements require this, because they have
+ // shadow content that must display in front of the video.
+ m_layer->insertSublayer(m_contentsLayer.get(), 0);
+
+ updateContentsRect();
+
+ if (showDebugBorders()) {
+ setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180));
+ m_contentsLayer->setBorderWidth(1);
+ }
+ }
+ updateDebugIndicators();
+}
+
+// This function simply mimics the operation of GraphicsLayerCA
+void GraphicsLayerChromium::updateOpacityOnLayer()
+{
+ primaryLayer()->setOpacity(m_opacity);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
new file mode 100644
index 0000000..130c25c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef GraphicsLayerChromium_h
+#define GraphicsLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+
+namespace WebCore {
+
+class LayerChromium;
+
+class GraphicsLayerChromium : public GraphicsLayer {
+public:
+ GraphicsLayerChromium(GraphicsLayerClient*);
+ virtual ~GraphicsLayerChromium();
+
+ virtual void setName(const String&);
+
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer*);
+ virtual void addChildAtIndex(GraphicsLayer*, int index);
+ virtual void addChildAbove(GraphicsLayer*, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer*, GraphicsLayer* sibling);
+ virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
+
+ virtual void removeFromParent();
+
+ virtual void setPosition(const FloatPoint&);
+ virtual void setAnchorPoint(const FloatPoint3D&);
+ virtual void setSize(const FloatSize&);
+
+ virtual void setTransform(const TransformationMatrix&);
+
+ virtual void setChildrenTransform(const TransformationMatrix&);
+
+ virtual void setPreserves3D(bool);
+ virtual void setMasksToBounds(bool);
+ virtual void setDrawsContent(bool);
+
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+
+ virtual void setContentsOpaque(bool);
+ virtual void setBackfaceVisibility(bool);
+
+ virtual void setOpacity(float);
+
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+ virtual void setContentsNeedsDisplay();
+
+ virtual void setContentsRect(const IntRect&);
+
+ virtual void setContentsToImage(Image*);
+ virtual void setContentsToMedia(PlatformLayer*);
+ virtual void setContentsToCanvas(PlatformLayer*);
+
+ virtual PlatformLayer* platformLayer() const;
+
+ virtual void setDebugBackgroundColor(const Color&);
+ virtual void setDebugBorder(const Color&, float borderWidth);
+
+ void notifySyncRequired()
+ {
+ if (m_client)
+ m_client->notifySyncRequired(this);
+ }
+
+private:
+ void updateOpacityOnLayer();
+
+ LayerChromium* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); }
+ LayerChromium* hostLayerForSublayers() const;
+ LayerChromium* layerForSuperlayer() const;
+
+ void updateSublayerList();
+ void updateLayerPosition();
+ void updateLayerSize();
+ void updateAnchorPoint();
+ void updateTransform();
+ void updateChildrenTransform();
+ void updateMasksToBounds();
+ void updateContentsOpaque();
+ void updateBackfaceVisibility();
+ void updateLayerPreserves3D();
+ void updateLayerDrawsContent();
+ void updateLayerBackgroundColor();
+
+ void updateContentsImage();
+ void updateContentsVideo();
+ void updateContentsRect();
+
+ void setupContentsLayer(LayerChromium*);
+ LayerChromium* contentsLayer() const { return m_contentsLayer.get(); }
+
+ RefPtr<LayerChromium> m_layer;
+ RefPtr<LayerChromium> m_transformLayer;
+ RefPtr<LayerChromium> m_contentsLayer;
+
+ enum ContentsLayerPurpose {
+ NoContentsLayer = 0,
+ ContentsLayerForImage,
+ ContentsLayerForVideo,
+ ContentsLayerForCanvas,
+ };
+
+ ContentsLayerPurpose m_contentsLayerPurpose;
+ bool m_contentsLayerHasBackgroundColor : 1;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
new file mode 100644
index 0000000..056d8eb
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "FontPlatformData.h"
+#include "wtf/OwnArrayPtr.h"
+
+#include "SkFontHost.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkUtils.h"
+
+extern "C" {
+#include "harfbuzz-shaper.h"
+}
+
+// This file implements the callbacks which Harfbuzz requires by using Skia
+// calls. See the Harfbuzz source for references about what these callbacks do.
+
+namespace WebCore {
+
+static HB_Fixed SkiaScalarToHarfbuzzFixed(SkScalar value)
+{
+ // HB_Fixed is a 26.6 fixed point format.
+ return value * 64;
+}
+
+static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length, HB_Glyph* glyphs, hb_uint32* glyphsSize, HB_Bool isRTL)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
+ SkPaint paint;
+
+ font->setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ unsigned codepoints = 0;
+ for (hb_uint32 i = 0; i < length; i++) {
+ if (!SkUTF16_IsHighSurrogate(characters[i]))
+ codepoints++;
+ if (codepoints > *glyphsSize)
+ return 0;
+ }
+
+ int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), reinterpret_cast<uint16_t*>(glyphs));
+
+ // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our
+ // |glyphs| array needs to be converted.
+ for (int i = numGlyphs - 1; i >= 0; --i) {
+ uint16_t value;
+ // We use a memcpy to avoid breaking strict aliasing rules.
+ memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(uint16_t));
+ glyphs[i] = value;
+ }
+
+ *glyphsSize = numGlyphs;
+ return 1;
+}
+
+static void glyphsToAdvances(HB_Font hbFont, const HB_Glyph* glyphs, hb_uint32 numGlyphs, HB_Fixed* advances, int flags)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
+ SkPaint paint;
+
+ font->setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+
+ OwnArrayPtr<uint16_t> glyphs16(new uint16_t[numGlyphs]);
+ if (!glyphs16.get())
+ return;
+ for (unsigned i = 0; i < numGlyphs; ++i)
+ glyphs16[i] = glyphs[i];
+ paint.getTextWidths(glyphs16.get(), numGlyphs * sizeof(uint16_t), reinterpret_cast<SkScalar*>(advances));
+
+ // The |advances| values which Skia outputs are SkScalars, which are floats
+ // in Chromium. However, Harfbuzz wants them in 26.6 fixed point format.
+ // These two formats are both 32-bits long.
+ for (unsigned i = 0; i < numGlyphs; ++i) {
+ float value;
+ // We use a memcpy to avoid breaking strict aliasing rules.
+ memcpy(&value, reinterpret_cast<char*>(advances) + sizeof(float) * i, sizeof(float));
+ advances[i] = SkiaScalarToHarfbuzzFixed(value);
+ }
+}
+
+static HB_Bool canRender(HB_Font hbFont, const HB_UChar16* characters, hb_uint32 length)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
+ SkPaint paint;
+
+ font->setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ OwnArrayPtr<uint16_t> glyphs16(new uint16_t[length]);
+ if (!glyphs16.get())
+ return 0;
+ int numGlyphs = paint.textToGlyphs(characters, length * sizeof(uint16_t), glyphs16.get());
+
+ bool canRender = true;
+ for (int i = 0; i < numGlyphs; ++i) {
+ if (!glyphs16[i]) {
+ canRender = false;
+ break;
+ }
+ }
+
+ return canRender;
+}
+
+static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed* xPos, HB_Fixed* yPos, hb_uint32* resultingNumPoints)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
+ SkPaint paint;
+
+ if (flags & HB_ShaperFlag_UseDesignMetrics)
+ return HB_Err_Invalid_Argument; // This is requesting pre-hinted positions. We can't support this.
+
+ font->setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ uint16_t glyph16 = glyph;
+ SkPath path;
+ paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path);
+ int numPoints = path.getPoints(0, 0);
+ if (point >= static_cast<unsigned>(numPoints))
+ return HB_Err_Invalid_SubTable;
+ SkPoint* points = reinterpret_cast<SkPoint*>(fastMalloc(sizeof(SkPoint) * (point + 1)));
+ if (!points)
+ return HB_Err_Invalid_SubTable;
+ // Skia does let us get a single point from the path.
+ path.getPoints(points, point + 1);
+ *xPos = SkiaScalarToHarfbuzzFixed(points[point].fX);
+ *yPos = SkiaScalarToHarfbuzzFixed(points[point].fY);
+ *resultingNumPoints = numPoints;
+ fastFree(points);
+
+ return HB_Err_Ok;
+}
+
+static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* metrics)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
+ SkPaint paint;
+
+ font->setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ uint16_t glyph16 = glyph;
+ SkScalar width;
+ SkRect bounds;
+ paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds);
+
+ metrics->x = SkiaScalarToHarfbuzzFixed(bounds.fLeft);
+ metrics->y = SkiaScalarToHarfbuzzFixed(bounds.fTop);
+ metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width());
+ metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height());
+
+ metrics->xOffset = SkiaScalarToHarfbuzzFixed(width);
+ // We can't actually get the |y| correct because Skia doesn't export
+ // the vertical advance. However, nor we do ever render vertical text at
+ // the moment so it's unimportant.
+ metrics->yOffset = 0;
+}
+
+static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(hbFont->userData);
+ SkPaint paint;
+
+ font->setupPaint(&paint);
+ SkPaint::FontMetrics skiaMetrics;
+ paint.getFontMetrics(&skiaMetrics);
+
+ switch (metric) {
+ case HB_FontAscent:
+ return SkiaScalarToHarfbuzzFixed(-skiaMetrics.fAscent);
+ // We don't support getting the rest of the metrics and Harfbuzz doesn't seem to need them.
+ default:
+ return 0;
+ }
+}
+
+HB_FontClass harfbuzzSkiaClass = {
+ stringToGlyphs,
+ glyphsToAdvances,
+ canRender,
+ getOutlinePoint,
+ getGlyphMetrics,
+ getFontMetric,
+};
+
+HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag tag, HB_Byte* buffer, HB_UInt* len)
+{
+ FontPlatformData* font = reinterpret_cast<FontPlatformData*>(voidface);
+
+ const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag);
+ if (!tableSize)
+ return HB_Err_Invalid_Argument;
+ // If Harfbuzz specified a NULL buffer then it's asking for the size of the table.
+ if (!buffer) {
+ *len = tableSize;
+ return HB_Err_Ok;
+ }
+
+ if (*len < tableSize)
+ return HB_Err_Invalid_Argument;
+ SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer);
+ return HB_Err_Ok;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.h b/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.h
new file mode 100644
index 0000000..f7e0496
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/HarfbuzzSkia.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HarfbuzzSkia_h
+#define HarfbuzzSkia_h
+
+extern "C" {
+#include "harfbuzz-shaper.h"
+#include "harfbuzz-unicode.h"
+}
+
+namespace WebCore {
+ HB_Error harfbuzzSkiaGetTable(void* voidface, const HB_Tag, HB_Byte* buffer, HB_UInt* len);
+ extern const HB_FontClass harfbuzzSkiaClass;
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
new file mode 100644
index 0000000..16f55e2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008, 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Icon.h"
+
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+Icon::Icon(const PlatformIcon& icon)
+ : m_icon(icon)
+{
+}
+
+Icon::~Icon()
+{
+}
+
+void Icon::paint(GraphicsContext*, const IntRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
new file mode 100644
index 0000000..a24afb2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/IconChromiumMac.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Icon.h"
+
+#include "PassRefPtr.h"
+
+// FIXME: These are temporary stubs, we need real implementations which
+// may come in the form of IconChromium.cpp. The Windows Chromium
+// implementation is currently in IconWin.cpp.
+
+namespace WebCore {
+
+Icon::~Icon()
+{
+}
+
+void Icon::paint(GraphicsContext*, const IntRect&)
+{
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
new file mode 100644
index 0000000..e958d4a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/IconChromiumWin.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Icon.h"
+
+#include <windows.h>
+#include <shellapi.h>
+
+#include "GraphicsContext.h"
+#include "PlatformContextSkia.h"
+#include "PlatformString.h"
+#include "SkiaUtils.h"
+
+namespace WebCore {
+
+Icon::Icon(const PlatformIcon& icon)
+ : m_icon(icon)
+{
+}
+
+Icon::~Icon()
+{
+ if (m_icon)
+ DestroyIcon(m_icon);
+}
+
+void Icon::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (context->paintingDisabled())
+ return;
+
+ HDC hdc = context->platformContext()->canvas()->beginPlatformPaint();
+ DrawIconEx(hdc, rect.x(), rect.y(), m_icon, rect.width(), rect.height(), 0, 0, DI_NORMAL);
+ context->platformContext()->canvas()->endPlatformPaint();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ImageBufferData.h b/Source/WebCore/platform/graphics/chromium/ImageBufferData.h
new file mode 100644
index 0000000..504b893
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ImageBufferData.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ImageBufferData_h
+#define ImageBufferData_h
+
+#include "PlatformContextSkia.h"
+
+#include "skia/ext/platform_canvas.h"
+
+namespace WebCore {
+
+class ImageBufferData {
+public:
+ ImageBufferData(const IntSize&);
+
+ skia::PlatformCanvas m_canvas;
+ PlatformContextSkia m_platformContext;
+};
+
+} // namespace WebCore
+
+#endif // ImageBufferData_h
diff --git a/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp
new file mode 100644
index 0000000..e90d566
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ImageChromium.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2008-2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Image.h"
+
+#include "ChromiumBridge.h"
+
+namespace WebCore {
+
+// Other Image methods are implemented in ImageSkia.cpp
+
+PassRefPtr<Image> Image::loadPlatformResource(const char *name)
+{
+ return ChromiumBridge::loadPlatformImageResource(name);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm b/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm
new file mode 100644
index 0000000..073a409
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ImageChromiumMac.mm
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// A wrapper around Uniscribe that provides a reasonable API.
+
+#include "config.h"
+#include "BitmapImage.h"
+
+#include "ChromiumBridge.h"
+#include "Image.h"
+
+namespace WebCore {
+
+PassRefPtr<Image> Image::loadPlatformResource(const char* name)
+{
+ return ChromiumBridge::loadPlatformImageResource(name);
+}
+
+// FIXME: These are temporary stubs, we need real implementations which
+// may come in the form of ImageChromium.cpp. The Windows Chromium
+// implementation is currently in ImageSkia.cpp.
+
+void BitmapImage::initPlatformData()
+{
+}
+
+void BitmapImage::invalidatePlatformData()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
new file mode 100644
index 0000000..cd299c1
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ImageLayerChromium.h"
+
+#include "Image.h"
+#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
+
+#if PLATFORM(SKIA)
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#endif
+
+#if PLATFORM(CG)
+#include <CoreGraphics/CGBitmapContext.h>
+#include <CoreGraphics/CGContext.h>
+#include <CoreGraphics/CGImage.h>
+#include <wtf/RetainPtr.h>
+#endif
+
+namespace WebCore {
+
+PassRefPtr<ImageLayerChromium> ImageLayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new ImageLayerChromium(owner));
+}
+
+ImageLayerChromium::ImageLayerChromium(GraphicsLayerChromium* owner)
+ : ContentLayerChromium(owner)
+ , m_contents(0)
+{
+}
+
+void ImageLayerChromium::setContents(Image* contents)
+{
+ // Check if the image has changed.
+ if (m_contents == contents)
+ return;
+ m_contents = contents;
+ setNeedsDisplay();
+}
+
+void ImageLayerChromium::updateContentsIfDirty()
+{
+ ASSERT(layerRenderer());
+
+ // FIXME: Remove this test when tiled layers are implemented.
+ if (requiresClippedUpdateRect()) {
+ // Use the base version of updateContents which draws a subset of the
+ // image to a bitmap, as the pixel contents can't be uploaded directly.
+ ContentLayerChromium::updateContentsIfDirty();
+ return;
+ }
+
+ void* pixels = 0;
+ IntSize bitmapSize;
+
+ NativeImagePtr nativeImage = m_contents->nativeImageForCurrentFrame();
+
+#if PLATFORM(SKIA)
+ // The layer contains an Image.
+ NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(nativeImage);
+ const SkBitmap* skiaBitmap = skiaImage;
+ bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
+ ASSERT(skiaBitmap);
+#elif PLATFORM(CG)
+ // NativeImagePtr is a CGImageRef on Mac OS X.
+ int width = CGImageGetWidth(nativeImage);
+ int height = CGImageGetHeight(nativeImage);
+ bitmapSize = IntSize(width, height);
+#endif
+
+ // Clip the dirty rect to the bitmap dimensions.
+ IntRect dirtyRect(m_dirtyRect);
+ dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize));
+
+ if (!m_contentsTexture || !m_contentsTexture->isValid(bitmapSize, GraphicsContext3D::RGBA))
+ dirtyRect = IntRect(IntPoint(0, 0), bitmapSize);
+ else if (!m_contentsDirty) {
+ m_contentsTexture->reserve(bitmapSize, GraphicsContext3D::RGBA);
+ return;
+ }
+
+#if PLATFORM(SKIA)
+ SkAutoLockPixels lock(*skiaBitmap);
+ SkBitmap::Config skiaConfig = skiaBitmap->config();
+ // FIXME: do we need to support more image configurations?
+ if (skiaConfig == SkBitmap::kARGB_8888_Config)
+ pixels = skiaBitmap->getPixels();
+#elif PLATFORM(CG)
+ // FIXME: we should get rid of this temporary copy where possible.
+ int tempRowBytes = width * 4;
+ Vector<uint8_t> tempVector;
+ tempVector.resize(height * tempRowBytes);
+ // Note we do not zero this vector since we are going to
+ // completely overwrite its contents with the image below.
+ // Try to reuse the color space from the image to preserve its colors.
+ // Some images use a color space (such as indexed) unsupported by the bitmap context.
+ RetainPtr<CGColorSpaceRef> colorSpaceReleaser;
+ CGColorSpaceRef colorSpace = CGImageGetColorSpace(nativeImage);
+ CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
+ switch (colorSpaceModel) {
+ case kCGColorSpaceModelMonochrome:
+ case kCGColorSpaceModelRGB:
+ case kCGColorSpaceModelCMYK:
+ case kCGColorSpaceModelLab:
+ case kCGColorSpaceModelDeviceN:
+ break;
+ default:
+ colorSpaceReleaser.adoptCF(CGColorSpaceCreateDeviceRGB());
+ colorSpace = colorSpaceReleaser.get();
+ break;
+ }
+ RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(tempVector.data(),
+ width, height, 8, tempRowBytes,
+ colorSpace,
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ CGContextSetBlendMode(tempContext.get(), kCGBlendModeCopy);
+ CGContextDrawImage(tempContext.get(),
+ CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)),
+ nativeImage);
+ pixels = tempVector.data();
+#else
+#error "Need to implement for your platform."
+#endif
+
+ if (pixels)
+ updateTextureRect(pixels, bitmapSize, dirtyRect);
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
new file mode 100644
index 0000000..a5c1450
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef ImageLayerChromium_h
+#define ImageLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ContentLayerChromium.h"
+
+#if PLATFORM(CG)
+#include <wtf/RetainPtr.h>
+#endif
+
+namespace WebCore {
+
+class Image;
+
+// A Layer that contains only an Image element.
+class ImageLayerChromium : public ContentLayerChromium {
+public:
+ static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0);
+
+ virtual void updateContentsIfDirty();
+ virtual bool drawsContent() { return m_contents; }
+
+ void setContents(Image* image);
+
+private:
+ ImageLayerChromium(GraphicsLayerChromium* owner);
+
+ RefPtr<Image> m_contents;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
new file mode 100644
index 0000000..b7ab098
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#if PLATFORM(SKIA)
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#endif
+#include "RenderLayerBacking.h"
+#include "skia/ext/platform_canvas.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+using namespace std;
+
+const unsigned LayerChromium::s_positionAttribLocation = 0;
+const unsigned LayerChromium::s_texCoordAttribLocation = 1;
+
+static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource)
+{
+ unsigned shader = context->createShader(type);
+ if (!shader)
+ return 0;
+ String sourceString(shaderSource);
+ GLC(context, context->shaderSource(shader, sourceString));
+ GLC(context, context->compileShader(shader));
+ int compiled = 0;
+ GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled));
+ if (!compiled) {
+ GLC(context, context->deleteShader(shader));
+ return 0;
+ }
+ return shader;
+}
+
+LayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_quadVerticesVbo(0)
+ , m_quadElementsVbo(0)
+ , m_maxTextureSize(0)
+ , m_borderShaderProgram(0)
+ , m_borderShaderMatrixLocation(-1)
+ , m_borderShaderColorLocation(-1)
+ , m_initialized(false)
+{
+ // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad.
+ float vertices[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, 0.5f, 0.0f, 1.0f, 1.0f };
+ uint16_t indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad.
+ 0, 1, 2, 3}; // A line path for drawing the layer border.
+
+ GLC(m_context, m_quadVerticesVbo = m_context->createBuffer());
+ GLC(m_context, m_quadElementsVbo = m_context->createBuffer());
+ GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVerticesVbo));
+ GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW));
+ GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadElementsVbo));
+ GLC(m_context, m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GraphicsContext3D::STATIC_DRAW));
+
+ // Get the max texture size supported by the system.
+ GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
+
+ // Shaders for drawing the debug borders around the layers.
+ char borderVertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "uniform mat4 matrix; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ "} \n";
+ char borderFragmentShaderString[] =
+ "precision mediump float; \n"
+ "uniform vec4 color; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_FragColor = vec4(color.xyz * color.w, color.w);\n"
+ "} \n";
+
+ m_borderShaderProgram = createShaderProgram(m_context, borderVertexShaderString, borderFragmentShaderString);
+ if (!m_borderShaderProgram) {
+ LOG_ERROR("ContentLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_borderShaderMatrixLocation = m_context->getUniformLocation(m_borderShaderProgram, "matrix");
+ m_borderShaderColorLocation = m_context->getUniformLocation(m_borderShaderProgram, "color");
+ ASSERT(m_borderShaderMatrixLocation != -1);
+ ASSERT(m_borderShaderColorLocation != -1);
+
+ m_initialized = true;
+}
+
+LayerChromium::SharedValues::~SharedValues()
+{
+ GLC(m_context, m_context->deleteBuffer(m_quadVerticesVbo));
+ GLC(m_context, m_context->deleteBuffer(m_quadElementsVbo));
+ if (m_borderShaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_borderShaderProgram));
+}
+
+
+PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new LayerChromium(owner));
+}
+
+LayerChromium::LayerChromium(GraphicsLayerChromium* owner)
+ : m_owner(owner)
+ , m_contentsDirty(false)
+ , m_targetRenderSurface(0)
+ , m_superlayer(0)
+ , m_anchorPoint(0.5, 0.5)
+ , m_backgroundColor(0, 0, 0, 0)
+ , m_borderColor(0, 0, 0, 0)
+ , m_opacity(1.0)
+ , m_zPosition(0.0)
+ , m_anchorPointZ(0)
+ , m_borderWidth(0)
+ , m_clearsContext(false)
+ , m_doubleSided(true)
+ , m_hidden(false)
+ , m_masksToBounds(false)
+ , m_opaque(true)
+ , m_geometryFlipped(false)
+ , m_needsDisplayOnBoundsChange(false)
+ , m_drawDepth(0)
+ , m_layerRenderer(0)
+ , m_renderSurface(0)
+{
+}
+
+LayerChromium::~LayerChromium()
+{
+ // Our superlayer should be holding a reference to us so there should be no
+ // way for us to be destroyed while we still have a superlayer.
+ ASSERT(!superlayer());
+
+ // Remove the superlayer reference from all sublayers.
+ removeAllSublayers();
+}
+
+void LayerChromium::cleanupResources()
+{
+ if (m_renderSurface)
+ m_renderSurface->cleanupResources();
+}
+
+void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer)
+{
+ // If we're changing layer renderers then we need to free up any resources
+ // allocated by the old renderer.
+ if (layerRenderer() && layerRenderer() != renderer) {
+ cleanupResources();
+ setNeedsDisplay();
+ }
+
+ m_layerRenderer = renderer;
+}
+
+RenderSurfaceChromium* LayerChromium::createRenderSurface()
+{
+ m_renderSurface = new RenderSurfaceChromium(this);
+ return m_renderSurface.get();
+}
+
+unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource)
+{
+ unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource);
+ if (!vertexShader) {
+ LOG_ERROR("Failed to create vertex shader");
+ return 0;
+ }
+
+ unsigned fragmentShader = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShaderSource);
+ if (!fragmentShader) {
+ GLC(context, context->deleteShader(vertexShader));
+ LOG_ERROR("Failed to create fragment shader");
+ return 0;
+ }
+
+ unsigned programObject = context->createProgram();
+ if (!programObject) {
+ LOG_ERROR("Failed to create shader program");
+ return 0;
+ }
+
+ GLC(context, context->attachShader(programObject, vertexShader));
+ GLC(context, context->attachShader(programObject, fragmentShader));
+
+ // Bind the common attrib locations.
+ GLC(context, context->bindAttribLocation(programObject, s_positionAttribLocation, "a_position"));
+ GLC(context, context->bindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord"));
+
+ GLC(context, context->linkProgram(programObject));
+ int linked = 0;
+ GLC(context, context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked));
+ if (!linked) {
+ LOG_ERROR("Failed to link shader program");
+ GLC(context, context->deleteProgram(programObject));
+ return 0;
+ }
+
+ GLC(context, context->deleteShader(vertexShader));
+ GLC(context, context->deleteShader(fragmentShader));
+ return programObject;
+}
+
+void LayerChromium::setNeedsCommit()
+{
+ // Call notifySyncRequired(), which for non-root layers plumbs through to
+ // call setRootLayerNeedsDisplay() on the WebView, which will cause LayerRendererChromium
+ // to render a frame.
+ // This function has no effect on root layers.
+ if (m_owner)
+ m_owner->notifySyncRequired();
+}
+
+void LayerChromium::addSublayer(PassRefPtr<LayerChromium> sublayer)
+{
+ insertSublayer(sublayer, numSublayers());
+}
+
+void LayerChromium::insertSublayer(PassRefPtr<LayerChromium> sublayer, size_t index)
+{
+ index = min(index, m_sublayers.size());
+ sublayer->removeFromSuperlayer();
+ sublayer->setSuperlayer(this);
+ m_sublayers.insert(index, sublayer);
+ setNeedsCommit();
+}
+
+void LayerChromium::removeFromSuperlayer()
+{
+ if (m_superlayer)
+ m_superlayer->removeSublayer(this);
+}
+
+void LayerChromium::removeSublayer(LayerChromium* sublayer)
+{
+ int foundIndex = indexOfSublayer(sublayer);
+ if (foundIndex == -1)
+ return;
+
+ sublayer->setSuperlayer(0);
+ m_sublayers.remove(foundIndex);
+ setNeedsCommit();
+}
+
+void LayerChromium::replaceSublayer(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer)
+{
+ ASSERT_ARG(reference, reference);
+ ASSERT_ARG(reference, reference->superlayer() == this);
+
+ if (reference == newLayer)
+ return;
+
+ int referenceIndex = indexOfSublayer(reference);
+ if (referenceIndex == -1) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ reference->removeFromSuperlayer();
+
+ if (newLayer) {
+ newLayer->removeFromSuperlayer();
+ insertSublayer(newLayer, referenceIndex);
+ }
+}
+
+int LayerChromium::indexOfSublayer(const LayerChromium* reference)
+{
+ for (size_t i = 0; i < m_sublayers.size(); i++) {
+ if (m_sublayers[i] == reference)
+ return i;
+ }
+ return -1;
+}
+
+void LayerChromium::setBounds(const IntSize& size)
+{
+ if (m_bounds == size)
+ return;
+
+ bool firstResize = !m_bounds.width() && !m_bounds.height() && size.width() && size.height();
+
+ m_bounds = size;
+ m_backingStoreSize = size;
+
+ if (firstResize)
+ setNeedsDisplay(FloatRect(0, 0, m_bounds.width(), m_bounds.height()));
+ else
+ setNeedsCommit();
+}
+
+void LayerChromium::setFrame(const FloatRect& rect)
+{
+ if (rect == m_frame)
+ return;
+
+ m_frame = rect;
+ setNeedsDisplay(FloatRect(0, 0, m_bounds.width(), m_bounds.height()));
+}
+
+const LayerChromium* LayerChromium::rootLayer() const
+{
+ const LayerChromium* layer = this;
+ for (LayerChromium* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
+ return layer;
+}
+
+void LayerChromium::removeAllSublayers()
+{
+ while (m_sublayers.size()) {
+ LayerChromium* layer = m_sublayers[0].get();
+ ASSERT(layer->superlayer());
+ layer->removeFromSuperlayer();
+ }
+}
+
+void LayerChromium::setSublayers(const Vector<RefPtr<LayerChromium> >& sublayers)
+{
+ if (sublayers == m_sublayers)
+ return;
+
+ removeAllSublayers();
+ size_t listSize = sublayers.size();
+ for (size_t i = 0; i < listSize; i++)
+ addSublayer(sublayers[i]);
+}
+
+LayerChromium* LayerChromium::superlayer() const
+{
+ return m_superlayer;
+}
+
+void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect)
+{
+ // Simply mark the contents as dirty. For non-root layers, the call to
+ // setNeedsCommit will schedule a fresh compositing pass.
+ // For the root layer, setNeedsCommit has no effect.
+ m_contentsDirty = true;
+
+ m_dirtyRect.unite(dirtyRect);
+ setNeedsCommit();
+}
+
+void LayerChromium::setNeedsDisplay()
+{
+ m_dirtyRect.setLocation(FloatPoint());
+ m_dirtyRect.setSize(m_bounds);
+ m_contentsDirty = true;
+ setNeedsCommit();
+}
+
+void LayerChromium::resetNeedsDisplay()
+{
+ m_dirtyRect = FloatRect();
+ m_contentsDirty = false;
+}
+
+void LayerChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
+{
+ flattened[0] = m.m11();
+ flattened[1] = m.m12();
+ flattened[2] = m.m13();
+ flattened[3] = m.m14();
+ flattened[4] = m.m21();
+ flattened[5] = m.m22();
+ flattened[6] = m.m23();
+ flattened[7] = m.m24();
+ flattened[8] = m.m31();
+ flattened[9] = m.m32();
+ flattened[10] = m.m33();
+ flattened[11] = m.m34();
+ flattened[12] = m.m41();
+ flattened[13] = m.m42();
+ flattened[14] = m.m43();
+ flattened[15] = m.m44();
+}
+
+GraphicsContext3D* LayerChromium::layerRendererContext() const
+{
+ ASSERT(layerRenderer());
+ return layerRenderer()->context();
+}
+
+void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix,
+ float width, float height, float opacity,
+ int matrixLocation, int alphaLocation)
+{
+ static float glMatrix[16];
+
+ TransformationMatrix renderMatrix = drawMatrix;
+
+ // Apply a scaling factor to size the quad from 1x1 to its intended size.
+ renderMatrix.scale3d(width, height, 1);
+
+ // Apply the projection matrix before sending the transform over to the shader.
+ renderMatrix.multiply(projectionMatrix);
+
+ toGLMatrix(&glMatrix[0], renderMatrix);
+
+ GLC(context, context->uniformMatrix4fv(matrixLocation, false, &glMatrix[0], 1));
+
+ if (alphaLocation != -1)
+ GLC(context, context->uniform1f(alphaLocation, opacity));
+
+ GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
+}
+
+void LayerChromium::drawDebugBorder()
+{
+ static float glMatrix[16];
+ if (!borderColor().alpha())
+ return;
+
+ ASSERT(layerRenderer());
+ const SharedValues* sv = layerRenderer()->layerSharedValues();
+ ASSERT(sv && sv->initialized());
+ layerRenderer()->useShader(sv->borderShaderProgram());
+ TransformationMatrix renderMatrix = drawTransform();
+ renderMatrix.scale3d(bounds().width(), bounds().height(), 1);
+ renderMatrix.multiply(layerRenderer()->projectionMatrix());
+ toGLMatrix(&glMatrix[0], renderMatrix);
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->uniformMatrix4fv(sv->borderShaderMatrixLocation(), false, &glMatrix[0], 1));
+
+ GLC(context, context->uniform4f(sv->borderShaderColorLocation(), borderColor().red() / 255.0, borderColor().green() / 255.0, borderColor().blue() / 255.0, 1));
+
+ GLC(context, context->lineWidth(borderWidth()));
+
+ // The indices for the line are stored in the same array as the triangle indices.
+ GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
+}
+
+const IntRect LayerChromium::getDrawRect() const
+{
+ // Form the matrix used by the shader to map the corners of the layer's
+ // bounds into the view space.
+ FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height());
+ IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect));
+ return mappedRect;
+}
+
+// Returns true if any of the layer's descendants has drawable content.
+bool LayerChromium::descendantsDrawContent()
+{
+ const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers();
+ for (size_t i = 0; i < sublayers.size(); ++i)
+ if (sublayers[i]->descendantsDrawContentRecursive())
+ return true;
+ return false;
+}
+
+// Returns true if either this layer or one of its descendants has drawable content.
+bool LayerChromium::descendantsDrawContentRecursive()
+{
+ if (drawsContent())
+ return true;
+
+ const Vector<RefPtr<LayerChromium> >& sublayers = getSublayers();
+ for (size_t i = 0; i < sublayers.size(); ++i)
+ if (sublayers[i]->descendantsDrawContentRecursive())
+ return true;
+ return false;
+}
+
+// static
+void LayerChromium::prepareForDraw(const SharedValues* sv)
+{
+ GraphicsContext3D* context = sv->context();
+ GLC(context, context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, sv->quadVerticesVbo()));
+ GLC(context, context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sv->quadElementsVbo()));
+ unsigned offset = 0;
+ GLC(context, context->vertexAttribPointer(s_positionAttribLocation, 3, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset));
+ offset += 3 * sizeof(float);
+ GLC(context, context->vertexAttribPointer(s_texCoordAttribLocation, 2, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset));
+ GLC(context, context->enableVertexAttribArray(s_positionAttribLocation));
+ GLC(context, context->enableVertexAttribArray(s_texCoordAttribLocation));
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
new file mode 100644
index 0000000..a0a690f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef LayerChromium_h
+#define LayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayerChromium.h"
+#include "PlatformString.h"
+#include "RenderSurfaceChromium.h"
+#include "TransformationMatrix.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+
+namespace skia {
+class PlatformCanvas;
+}
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class LayerRendererChromium;
+
+// Base class for composited layers. Special layer types are derived from
+// this class.
+class LayerChromium : public RefCounted<LayerChromium> {
+ friend class LayerRendererChromium;
+ friend class LayerTilerChromium;
+public:
+ static PassRefPtr<LayerChromium> create(GraphicsLayerChromium* owner = 0);
+
+ virtual ~LayerChromium();
+
+ const LayerChromium* rootLayer() const;
+ LayerChromium* superlayer() const;
+ void addSublayer(PassRefPtr<LayerChromium>);
+ void insertSublayer(PassRefPtr<LayerChromium>, size_t index);
+ void replaceSublayer(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer);
+ void removeFromSuperlayer();
+ void removeAllSublayers();
+ void setSublayers(const Vector<RefPtr<LayerChromium> >&);
+ const Vector<RefPtr<LayerChromium> >& getSublayers() const { return m_sublayers; }
+
+ void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; setNeedsCommit(); }
+ FloatPoint anchorPoint() const { return m_anchorPoint; }
+
+ void setAnchorPointZ(float anchorPointZ) { m_anchorPointZ = anchorPointZ; setNeedsCommit(); }
+ float anchorPointZ() const { return m_anchorPointZ; }
+
+ void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); }
+ Color backgroundColor() const { return m_backgroundColor; }
+
+ void setBorderColor(const Color& color) { m_borderColor = color; setNeedsCommit(); }
+ Color borderColor() const { return m_borderColor; }
+
+ void setBorderWidth(float width) { m_borderWidth = width; setNeedsCommit(); }
+ float borderWidth() const { return m_borderWidth; }
+
+ void setBounds(const IntSize&);
+ IntSize bounds() const { return m_bounds; }
+
+ void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); }
+ bool clearsContext() const { return m_clearsContext; }
+
+ void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); }
+ bool doubleSided() const { return m_doubleSided; }
+
+ void setFrame(const FloatRect&);
+ FloatRect frame() const { return m_frame; }
+
+ void setHidden(bool hidden) { m_hidden = hidden; setNeedsCommit(); }
+ bool isHidden() const { return m_hidden; }
+
+ void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; }
+ bool masksToBounds() const { return m_masksToBounds; }
+
+ void setName(const String& name) { m_name = name; }
+ String name() const { return m_name; }
+
+ void setNeedsDisplay(const FloatRect& dirtyRect);
+ void setNeedsDisplay();
+ const FloatRect& dirtyRect() const { return m_dirtyRect; }
+ void resetNeedsDisplay();
+
+ void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; }
+
+ void setOpacity(float opacity) { m_opacity = opacity; setNeedsCommit(); }
+ float opacity() const { return m_opacity; }
+
+ void setOpaque(bool opaque) { m_opaque = opaque; setNeedsCommit(); }
+ bool opaque() const { return m_opaque; }
+
+ void setPosition(const FloatPoint& position) { m_position = position; setNeedsCommit(); }
+ FloatPoint position() const { return m_position; }
+
+ void setZPosition(float zPosition) { m_zPosition = zPosition; setNeedsCommit(); }
+ float zPosition() const { return m_zPosition; }
+
+ void setSublayerTransform(const TransformationMatrix& transform) { m_sublayerTransform = transform; setNeedsCommit(); }
+ const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; }
+
+ void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); }
+ const TransformationMatrix& transform() const { return m_transform; }
+
+ // FIXME: This setting is currently ignored.
+ void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); }
+ bool geometryFlipped() const { return m_geometryFlipped; }
+
+ const TransformationMatrix& drawTransform() const { return m_drawTransform; }
+ float drawOpacity() const { return m_drawOpacity; }
+
+ bool preserves3D() { return m_owner && m_owner->preserves3D(); }
+
+ // Derived types must override this method if they need to react to a change
+ // in the LayerRendererChromium.
+ virtual void setLayerRenderer(LayerRendererChromium*);
+
+ void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; }
+
+ // Returns the rect containtaining this layer in the current view's coordinate system.
+ const IntRect getDrawRect() const;
+
+ // These methods typically need to be overwritten by derived classes.
+ virtual bool drawsContent() { return false; }
+ virtual void updateContentsIfDirty() { }
+ virtual void draw() { }
+
+ void drawDebugBorder();
+
+ RenderSurfaceChromium* createRenderSurface();
+
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+
+ GraphicsContext3D* context() const { return m_context; }
+ unsigned quadVerticesVbo() const { return m_quadVerticesVbo; }
+ unsigned quadElementsVbo() const { return m_quadElementsVbo; }
+ int maxTextureSize() const { return m_maxTextureSize; }
+ unsigned borderShaderProgram() const { return m_borderShaderProgram; }
+ int borderShaderMatrixLocation() const { return m_borderShaderMatrixLocation; }
+ int borderShaderColorLocation() const { return m_borderShaderColorLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+ unsigned m_quadVerticesVbo;
+ unsigned m_quadElementsVbo;
+ int m_maxTextureSize;
+ unsigned m_borderShaderProgram;
+ int m_borderShaderMatrixLocation;
+ int m_borderShaderColorLocation;
+ bool m_initialized;
+ };
+
+ static void prepareForDraw(const SharedValues*);
+
+ LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); }
+
+ static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource);
+
+ static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
+ float width, float height, float opacity,
+ int matrixLocation, int alphaLocation);
+
+protected:
+ GraphicsLayerChromium* m_owner;
+ LayerChromium(GraphicsLayerChromium* owner);
+
+ // This is called to clean up resources being held in the same context as
+ // layerRendererContext(). Subclasses should override this method if they
+ // hold context-dependent resources such as textures.
+ virtual void cleanupResources();
+
+ GraphicsContext3D* layerRendererContext() const;
+
+ // Returns true if any of the layer's descendants has content to draw.
+ bool descendantsDrawContent();
+
+ static void toGLMatrix(float*, const TransformationMatrix&);
+
+ IntSize m_bounds;
+ FloatRect m_dirtyRect;
+ bool m_contentsDirty;
+
+ // Render surface this layer draws into. This is a surface that can belong
+ // either to this layer (if m_targetRenderSurface == m_renderSurface) or
+ // to an ancestor of this layer. The target render surface determines the
+ // coordinate system the layer's transforms are relative to.
+ RenderSurfaceChromium* m_targetRenderSurface;
+
+ // All layer shaders share the same attribute locations for the vertex positions
+ // and texture coordinates. This allows switching shaders without rebinding attribute
+ // arrays.
+ static const unsigned s_positionAttribLocation;
+ static const unsigned s_texCoordAttribLocation;
+
+private:
+ void setNeedsCommit();
+
+ void setSuperlayer(LayerChromium* superlayer) { m_superlayer = superlayer; }
+
+ size_t numSublayers() const
+ {
+ return m_sublayers.size();
+ }
+
+ // Returns the index of the sublayer or -1 if not found.
+ int indexOfSublayer(const LayerChromium*);
+
+ // This should only be called from removeFromSuperlayer.
+ void removeSublayer(LayerChromium*);
+
+ bool descendantsDrawContentRecursive();
+
+ Vector<RefPtr<LayerChromium> > m_sublayers;
+ LayerChromium* m_superlayer;
+
+ // Layer properties.
+ IntSize m_backingStoreSize;
+ FloatPoint m_position;
+ FloatPoint m_anchorPoint;
+ Color m_backgroundColor;
+ Color m_borderColor;
+ float m_opacity;
+ float m_zPosition;
+ float m_anchorPointZ;
+ float m_borderWidth;
+ float m_drawOpacity;
+ bool m_clearsContext;
+ bool m_doubleSided;
+ bool m_hidden;
+ bool m_masksToBounds;
+ bool m_opaque;
+ bool m_geometryFlipped;
+ bool m_needsDisplayOnBoundsChange;
+
+ // The global depth value of the center of the layer. This value is used
+ // to sort layers from back to front.
+ float m_drawDepth;
+
+ // Points to the layer renderer that updates and draws this layer.
+ RefPtr<LayerRendererChromium> m_layerRenderer;
+
+ FloatRect m_frame;
+ TransformationMatrix m_transform;
+ TransformationMatrix m_sublayerTransform;
+ TransformationMatrix m_drawTransform;
+
+ // The scissor rectangle that should be used when this layer is drawn.
+ // Inherited by the parent layer and further restricted if this layer masks
+ // to bounds.
+ IntRect m_scissorRect;
+
+ // Render surface associated with this layer. The layer and its descendants
+ // will render to this surface.
+ OwnPtr<RenderSurfaceChromium> m_renderSurface;
+
+ // Hierarchical bounding rect containing the layer and its descendants.
+ IntRect m_drawableContentRect;
+
+ String m_name;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
new file mode 100644
index 0000000..8d77bea
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -0,0 +1,803 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "LayerRendererChromium.h"
+
+#include "Canvas2DLayerChromium.h"
+#include "GraphicsContext3D.h"
+#include "LayerChromium.h"
+#include "LayerTexture.h"
+#include "NotImplemented.h"
+#include "TextureManager.h"
+#include "WebGLLayerChromium.h"
+#if PLATFORM(SKIA)
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#elif PLATFORM(CG)
+#include <CoreGraphics/CGBitmapContext.h>
+#endif
+
+namespace WebCore {
+
+// FIXME: Make this limit adjustable and give it a useful value.
+static size_t textureMemoryLimitBytes = 64 * 1024 * 1024;
+
+static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
+{
+ float deltaX = right - left;
+ float deltaY = top - bottom;
+ TransformationMatrix ortho;
+ if (!deltaX || !deltaY)
+ return ortho;
+ ortho.setM11(2.0f / deltaX);
+ ortho.setM41(-(right + left) / deltaX);
+ ortho.setM22(2.0f / deltaY);
+ ortho.setM42(-(top + bottom) / deltaY);
+
+ // Z component of vertices is always set to zero as we don't use the depth buffer
+ // while drawing.
+ ortho.setM33(0);
+
+ return ortho;
+}
+
+// Returns true if the matrix has no rotation, skew or perspective components to it.
+static bool isScaleOrTranslation(const TransformationMatrix& m)
+{
+ return !m.m12() && !m.m13() && !m.m14()
+ && !m.m21() && !m.m23() && !m.m24()
+ && !m.m31() && !m.m32() && !m.m43()
+ && m.m44();
+
+}
+
+bool LayerRendererChromium::compareLayerZ(const LayerChromium* a, const LayerChromium* b)
+{
+ return a->m_drawDepth < b->m_drawDepth;
+}
+
+PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context)
+{
+ if (!context)
+ return 0;
+
+ RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context)));
+ if (!layerRenderer->hardwareCompositing())
+ return 0;
+
+ return layerRenderer.release();
+}
+
+LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context)
+ : m_rootLayerTextureWidth(0)
+ , m_rootLayerTextureHeight(0)
+ , m_rootLayer(0)
+ , m_scrollPosition(IntPoint(-1, -1))
+ , m_currentShader(0)
+ , m_currentRenderSurface(0)
+ , m_offscreenFramebufferId(0)
+ , m_compositeOffscreen(false)
+ , m_context(context)
+ , m_defaultRenderSurface(0)
+{
+ m_hardwareCompositing = initializeSharedObjects();
+ m_rootLayerTiler = LayerTilerChromium::create(this, IntSize(256, 256));
+ ASSERT(m_rootLayerTiler);
+}
+
+LayerRendererChromium::~LayerRendererChromium()
+{
+ cleanupSharedObjects();
+
+ // Because the tilers need to clean up textures, clean them up explicitly
+ // before the GraphicsContext3D is destroyed.
+ m_rootLayerTiler.clear();
+ m_horizontalScrollbarTiler.clear();
+ m_verticalScrollbarTiler.clear();
+}
+
+GraphicsContext3D* LayerRendererChromium::context()
+{
+ return m_context.get();
+}
+
+void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line)
+{
+ unsigned long error = context->getError();
+ if (error != GraphicsContext3D::NO_ERROR)
+ LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
+}
+
+void LayerRendererChromium::useShader(unsigned programId)
+{
+ if (programId != m_currentShader) {
+ GLC(m_context.get(), m_context->useProgram(programId));
+ m_currentShader = programId;
+ }
+}
+
+IntRect LayerRendererChromium::verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect)
+{
+ IntRect verticalScrollbar(IntPoint(contentRect.right(), contentRect.y()), IntSize(visibleRect.width() - contentRect.width(), visibleRect.height()));
+ return verticalScrollbar;
+}
+
+IntRect LayerRendererChromium::horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect)
+{
+ IntRect horizontalScrollbar(IntPoint(contentRect.x(), contentRect.bottom()), IntSize(visibleRect.width(), visibleRect.height() - contentRect.height()));
+ return horizontalScrollbar;
+}
+
+void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect)
+{
+ if (contentRect.intersects(dirtyRect))
+ m_rootLayerTiler->invalidateRect(dirtyRect);
+ if (m_horizontalScrollbarTiler) {
+ IntRect scrollbar = horizontalScrollbarRect(visibleRect, contentRect);
+ if (dirtyRect.intersects(scrollbar)) {
+ m_horizontalScrollbarTiler->setLayerPosition(scrollbar.location());
+ m_horizontalScrollbarTiler->invalidateRect(dirtyRect);
+ }
+ }
+ if (m_verticalScrollbarTiler) {
+ IntRect scrollbar = verticalScrollbarRect(visibleRect, contentRect);
+ if (dirtyRect.intersects(scrollbar)) {
+ m_verticalScrollbarTiler->setLayerPosition(scrollbar.location());
+ m_verticalScrollbarTiler->invalidateRect(dirtyRect);
+ }
+ }
+}
+
+void LayerRendererChromium::updateAndDrawRootLayer(TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect)
+{
+ m_rootLayerTiler->update(tilePaint, visibleRect);
+ m_rootLayerTiler->draw(visibleRect);
+
+ if (visibleRect.width() > contentRect.width()) {
+ IntRect verticalScrollbar = verticalScrollbarRect(visibleRect, contentRect);
+ IntSize tileSize = verticalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize));
+ if (!m_verticalScrollbarTiler)
+ m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize);
+ else
+ m_verticalScrollbarTiler->setTileSize(tileSize);
+ m_verticalScrollbarTiler->setLayerPosition(verticalScrollbar.location());
+ m_verticalScrollbarTiler->update(scrollbarPaint, visibleRect);
+ m_verticalScrollbarTiler->draw(visibleRect);
+ }
+
+ if (visibleRect.height() > contentRect.height()) {
+ IntRect horizontalScrollbar = horizontalScrollbarRect(visibleRect, contentRect);
+ IntSize tileSize = horizontalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize));
+ if (!m_horizontalScrollbarTiler)
+ m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize);
+ else
+ m_horizontalScrollbarTiler->setTileSize(tileSize);
+ m_horizontalScrollbarTiler->setLayerPosition(horizontalScrollbar.location());
+ m_horizontalScrollbarTiler->update(scrollbarPaint, visibleRect);
+ m_horizontalScrollbarTiler->draw(visibleRect);
+ }
+}
+
+void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect& contentRect,
+ const IntPoint& scrollPosition, TilePaintInterface& tilePaint,
+ TilePaintInterface& scrollbarPaint)
+{
+ ASSERT(m_hardwareCompositing);
+
+ if (!m_rootLayer)
+ return;
+
+ makeContextCurrent();
+
+ // If the size of the visible area has changed then allocate a new texture
+ // to store the contents of the root layer and adjust the projection matrix
+ // and viewport.
+ int visibleRectWidth = visibleRect.width();
+ int visibleRectHeight = visibleRect.height();
+
+ if (!m_rootLayer->m_renderSurface)
+ m_rootLayer->createRenderSurface();
+ m_rootLayer->m_renderSurface->m_contentRect = IntRect(0, 0, visibleRectWidth, visibleRectHeight);
+
+ if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) {
+ m_rootLayerTextureWidth = visibleRectWidth;
+ m_rootLayerTextureHeight = visibleRectHeight;
+
+ // Reset the current render surface to force an update of the viewport and
+ // projection matrix next time useRenderSurface is called.
+ m_currentRenderSurface = 0;
+ }
+
+ // The GL viewport covers the entire visible area, including the scrollbars.
+ GLC(m_context.get(), m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight));
+
+ // Bind the common vertex attributes used for drawing all the layers.
+ LayerChromium::prepareForDraw(layerSharedValues());
+
+ // FIXME: These calls can be made once, when the compositor context is initialized.
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
+
+ // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
+
+ m_scrollPosition = scrollPosition;
+
+ ASSERT(m_rootLayer->m_renderSurface);
+ m_defaultRenderSurface = m_rootLayer->m_renderSurface.get();
+
+ useRenderSurface(m_defaultRenderSurface);
+
+ // Clear to blue to make it easier to spot unrendered regions.
+ m_context->clearColor(0, 0, 1, 1);
+ m_context->colorMask(true, true, true, true);
+ m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
+ // Mask out writes to alpha channel: subpixel antialiasing via Skia results in invalid
+ // zero alpha values on text glyphs. The root layer is always opaque.
+ m_context->colorMask(true, true, true, false);
+
+ updateAndDrawRootLayer(tilePaint, scrollbarPaint, visibleRect, contentRect);
+
+ // Set the root visible/content rects --- used by subsequent drawLayers calls.
+ m_rootVisibleRect = visibleRect;
+ m_rootContentRect = contentRect;
+
+ // Scissor out the scrollbars to avoid rendering on top of them.
+ IntRect rootScissorRect(contentRect);
+ // The scissorRect should not include the scroll offset.
+ rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y());
+ m_rootLayer->m_scissorRect = rootScissorRect;
+
+ Vector<LayerChromium*> renderSurfaceLayerList;
+ renderSurfaceLayerList.append(m_rootLayer.get());
+
+ TransformationMatrix identityMatrix;
+ m_defaultRenderSurface->m_layerList.clear();
+ updateLayersRecursive(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList);
+
+ // The shader used to render layers returns pre-multiplied alpha colors
+ // so we need to send the blending mode appropriately.
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
+ GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+
+ // Update the contents of the render surfaces. We traverse the array from
+ // back to front to guarantee that nested render surfaces get rendered in the
+ // correct order.
+ for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
+ LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
+ ASSERT(renderSurfaceLayer->m_renderSurface);
+
+ // Render surfaces whose drawable area has zero width or height
+ // will have no layers associated with them and should be skipped.
+ if (!renderSurfaceLayer->m_renderSurface->m_layerList.size())
+ continue;
+
+ if (useRenderSurface(renderSurfaceLayer->m_renderSurface.get())) {
+ if (renderSurfaceLayer != m_rootLayer) {
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
+ GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ }
+
+ Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList;
+ ASSERT(layerList.size());
+ for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
+ drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get());
+ }
+ }
+
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
+}
+
+void LayerRendererChromium::finish()
+{
+ m_context->finish();
+}
+
+void LayerRendererChromium::present()
+{
+ // We're done! Time to swapbuffers!
+
+ // Note that currently this has the same effect as swapBuffers; we should
+ // consider exposing a different entry point on GraphicsContext3D.
+ m_context->prepareTexture();
+}
+
+void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer)
+{
+ m_rootLayer = layer;
+ m_rootLayerTiler->invalidateEntireLayer();
+ if (m_horizontalScrollbarTiler)
+ m_horizontalScrollbarTiler->invalidateEntireLayer();
+ if (m_verticalScrollbarTiler)
+ m_verticalScrollbarTiler->invalidateEntireLayer();
+}
+
+void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
+{
+ ASSERT(rect.right() <= rootLayerTextureSize().width()
+ && rect.bottom() <= rootLayerTextureSize().height());
+
+ if (!pixels)
+ return;
+
+ makeContextCurrent();
+
+ GLC(m_context.get(), m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
+ GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+}
+
+// FIXME: This method should eventually be replaced by a proper texture manager.
+unsigned LayerRendererChromium::createLayerTexture()
+{
+ unsigned textureId = 0;
+ GLC(m_context.get(), textureId = m_context->createTexture());
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ // Do basic linear filtering on resize.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+ return textureId;
+}
+
+void LayerRendererChromium::deleteLayerTexture(unsigned textureId)
+{
+ if (!textureId)
+ return;
+
+ GLC(m_context.get(), m_context->deleteTexture(textureId));
+}
+
+// Returns true if any part of the layer falls within the visibleRect
+bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const TransformationMatrix& matrix, const IntRect& visibleRect)
+{
+ // Form the matrix used by the shader to map the corners of the layer's
+ // bounds into clip space.
+ TransformationMatrix renderMatrix = matrix;
+ renderMatrix.scale3d(layer->bounds().width(), layer->bounds().height(), 1);
+ renderMatrix.multiply(m_projectionMatrix);
+
+ FloatRect layerRect(-0.5, -0.5, 1, 1);
+ FloatRect mappedRect = renderMatrix.mapRect(layerRect);
+
+ // The layer is visible if it intersects any part of a rectangle whose origin
+ // is at (-1, -1) and size is 2x2.
+ return mappedRect.intersects(FloatRect(-1, -1, 2, 2));
+}
+
+// Recursively walks the layer tree starting at the given node and computes all the
+// necessary transformations, scissor rectangles, render surfaces, etc.
+void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList)
+{
+ layer->setLayerRenderer(this);
+
+ // Compute the new matrix transformation that will be applied to this layer and
+ // all its sublayers. It's important to remember that the layer's position
+ // is the position of the layer's anchor point. Also, the coordinate system used
+ // assumes that the origin is at the lower left even though the coordinates the browser
+ // gives us for the layers are for the upper left corner. The Y flip happens via
+ // the orthographic projection applied at render time.
+ // The transformation chain for the layer is (using the Matrix x Vector order):
+ // M = M[p] * Tr[l] * M[l] * Tr[c]
+ // Where M[p] is the parent matrix passed down to the function
+ // Tr[l] is the translation matrix locating the layer's anchor point
+ // Tr[c] is the translation offset between the anchor point and the center of the layer
+ // M[l] is the layer's matrix (applied at the anchor point)
+ // This transform creates a coordinate system whose origin is the center of the layer.
+ // Note that the final matrix used by the shader for the layer is P * M * S . This final product
+ // is computed in drawTexturedQuad().
+ // Where: P is the projection matrix
+ // M is the layer's matrix computed above
+ // S is the scale adjustment (to scale up to the layer size)
+ IntSize bounds = layer->bounds();
+ FloatPoint anchorPoint = layer->anchorPoint();
+ FloatPoint position = layer->position();
+
+ // Offset between anchor point and the center of the quad.
+ float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width();
+ float centerOffsetY = (0.5 - anchorPoint.y()) * bounds.height();
+
+ TransformationMatrix layerLocalTransform;
+ // LT = Tr[l]
+ layerLocalTransform.translate3d(position.x(), position.y(), layer->anchorPointZ());
+ // LT = Tr[l] * M[l]
+ layerLocalTransform.multLeft(layer->transform());
+ // LT = Tr[l] * M[l] * Tr[c]
+ layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ());
+
+ TransformationMatrix combinedTransform = parentMatrix;
+ combinedTransform = combinedTransform.multLeft(layerLocalTransform);
+
+ FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height());
+ IntRect transformedLayerRect;
+
+ // The layer and its descendants render on a new RenderSurface if any of
+ // these conditions hold:
+ // 1. The layer clips its descendants and its transform is not a simple translation.
+ // 2. If the layer has opacity != 1 and does not have a preserves-3d transform style.
+ // If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening
+ // out its children. The opacity value of the children layers is multiplied by the opacity
+ // of their parent.
+ bool useSurfaceForClipping = layer->masksToBounds() && !isScaleOrTranslation(combinedTransform);
+ bool useSurfaceForOpacity = layer->opacity() != 1 && !layer->preserves3D();
+ if ((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent()) {
+ RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get();
+ if (!renderSurface)
+ renderSurface = layer->createRenderSurface();
+
+ // The origin of the new surface is the upper left corner of the layer.
+ layer->m_drawTransform = TransformationMatrix();
+ layer->m_drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0);
+
+ transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height());
+
+ // Layer's opacity will be applied when drawing the render surface.
+ renderSurface->m_drawOpacity = layer->opacity();
+ if (layer->superlayer()->preserves3D())
+ renderSurface->m_drawOpacity *= layer->superlayer()->drawOpacity();
+ layer->m_drawOpacity = 1;
+
+ TransformationMatrix layerOriginTransform = combinedTransform;
+ layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
+ renderSurface->m_originTransform = layerOriginTransform;
+ if (layerOriginTransform.isInvertible() && layer->superlayer()) {
+ TransformationMatrix parentToLayer = layerOriginTransform.inverse();
+
+ layer->m_scissorRect = parentToLayer.mapRect(layer->superlayer()->m_scissorRect);
+ } else
+ layer->m_scissorRect = IntRect();
+
+ // The render surface scissor rect is the scissor rect that needs to
+ // be applied before drawing the render surface onto its containing
+ // surface and is therefore expressed in the superlayer's coordinate system.
+ renderSurface->m_scissorRect = layer->superlayer()->m_scissorRect;
+
+ renderSurface->m_layerList.clear();
+
+ renderSurfaceLayerList.append(layer);
+ } else {
+ // DT = M[p] * LT
+ layer->m_drawTransform = combinedTransform;
+ transformedLayerRect = enclosingIntRect(layer->m_drawTransform.mapRect(layerRect));
+
+ layer->m_drawOpacity = layer->opacity();
+
+ if (layer->superlayer()) {
+ if (layer->superlayer()->preserves3D())
+ layer->m_drawOpacity *= layer->superlayer()->m_drawOpacity;
+
+ // Layers inherit the scissor rect from their superlayer.
+ layer->m_scissorRect = layer->superlayer()->m_scissorRect;
+
+ layer->m_targetRenderSurface = layer->superlayer()->m_targetRenderSurface;
+ }
+
+ if (layer != m_rootLayer)
+ layer->m_renderSurface = 0;
+
+ if (layer->masksToBounds())
+ layer->m_scissorRect.intersect(transformedLayerRect);
+ }
+
+ if (layer->m_renderSurface)
+ layer->m_targetRenderSurface = layer->m_renderSurface.get();
+ else {
+ ASSERT(layer->superlayer());
+ layer->m_targetRenderSurface = layer->superlayer()->m_targetRenderSurface;
+ }
+
+ // m_drawableContentRect is always stored in the coordinate system of the
+ // RenderSurface the layer draws into.
+ if (layer->drawsContent())
+ layer->m_drawableContentRect = transformedLayerRect;
+ else
+ layer->m_drawableContentRect = IntRect();
+
+ TransformationMatrix sublayerMatrix = layer->m_drawTransform;
+
+ // Flatten to 2D if the layer doesn't preserve 3D.
+ if (!layer->preserves3D()) {
+ sublayerMatrix.setM13(0);
+ sublayerMatrix.setM23(0);
+ sublayerMatrix.setM31(0);
+ sublayerMatrix.setM32(0);
+ sublayerMatrix.setM33(1);
+ sublayerMatrix.setM34(0);
+ sublayerMatrix.setM43(0);
+ }
+
+ // Apply the sublayer transform at the center of the layer.
+ sublayerMatrix.multLeft(layer->sublayerTransform());
+
+ // The origin of the sublayers is the top left corner of the layer, not the
+ // center. The matrix passed down to the sublayers is therefore:
+ // M[s] = M * Tr[-center]
+ sublayerMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0);
+
+ Vector<LayerChromium*>& descendants = (layer->m_renderSurface ? layer->m_renderSurface->m_layerList : layerList);
+ descendants.append(layer);
+ unsigned thisLayerIndex = descendants.size() - 1;
+
+ const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
+ for (size_t i = 0; i < sublayers.size(); ++i) {
+ LayerChromium* sublayer = sublayers[i].get();
+ updateLayersRecursive(sublayer, sublayerMatrix, renderSurfaceLayerList, descendants);
+
+ if (sublayer->m_renderSurface) {
+ RenderSurfaceChromium* sublayerRenderSurface = sublayer->m_renderSurface.get();
+ const IntRect& contentRect = sublayerRenderSurface->contentRect();
+ FloatRect sublayerRect(-0.5 * contentRect.width(), -0.5 * contentRect.height(),
+ contentRect.width(), contentRect.height());
+ layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->m_drawTransform.mapRect(sublayerRect)));
+ descendants.append(sublayer);
+ } else
+ layer->m_drawableContentRect.unite(sublayer->m_drawableContentRect);
+ }
+
+ if (layer->masksToBounds())
+ layer->m_drawableContentRect.intersect(transformedLayerRect);
+
+ if (layer->m_renderSurface && layer != m_rootLayer) {
+ RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get();
+ renderSurface->m_contentRect = layer->m_drawableContentRect;
+ FloatPoint surfaceCenter = renderSurface->contentRectCenter();
+
+ // Restrict the RenderSurface size to the portion that's visible.
+ FloatSize centerOffsetDueToClipping;
+ renderSurface->m_contentRect.intersect(layer->m_scissorRect);
+ FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter();
+ centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter;
+
+ // The RenderSurface backing texture cannot exceed the maximum supported
+ // texture size.
+ renderSurface->m_contentRect.setWidth(std::min(renderSurface->m_contentRect.width(), m_maxTextureSize));
+ renderSurface->m_contentRect.setHeight(std::min(renderSurface->m_contentRect.height(), m_maxTextureSize));
+
+ if (renderSurface->m_contentRect.isEmpty())
+ renderSurface->m_layerList.clear();
+
+ // Since the layer starts a new render surface we need to adjust its
+ // scissor rect to be expressed in the new surface's coordinate system.
+ layer->m_scissorRect = layer->m_drawableContentRect;
+
+ // Adjust the origin of the transform to be the center of the render surface.
+ renderSurface->m_drawTransform = renderSurface->m_originTransform;
+ renderSurface->m_drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0);
+ }
+
+ // Compute the depth value of the center of the layer which will be used when
+ // sorting the layers for the preserves-3d property.
+ TransformationMatrix& layerDrawMatrix = layer->m_renderSurface ? layer->m_renderSurface->m_drawTransform : layer->m_drawTransform;
+ if (layer->superlayer()) {
+ if (!layer->superlayer()->preserves3D())
+ layer->m_drawDepth = layer->superlayer()->m_drawDepth;
+ else
+ layer->m_drawDepth = layerDrawMatrix.m43();
+ } else
+ layer->m_drawDepth = 0;
+
+ // If preserves-3d then sort all the descendants by the Z coordinate of their
+ // center. If the preserves-3d property is also set on the superlayer then
+ // skip the sorting as the superlayer will sort all the descendants anyway.
+ if (layer->preserves3D() && (!layer->superlayer() || !layer->superlayer()->preserves3D()))
+ std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ);
+}
+
+void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen)
+{
+ m_compositeOffscreen = compositeOffscreen;
+
+ if (!m_rootLayer) {
+ m_compositeOffscreen = false;
+ return;
+ }
+
+ if (m_compositeOffscreen) {
+ // Need to explicitly set a LayerRendererChromium for the layer with the offscreen texture,
+ // or else the call to prepareContentsTexture() in useRenderSurface() will fail.
+ m_rootLayer->setLayerRenderer(this);
+ } else
+ m_rootLayer->m_renderSurface.clear();
+}
+
+bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurface)
+{
+ if (m_currentRenderSurface == renderSurface)
+ return true;
+
+ m_currentRenderSurface = renderSurface;
+
+ if (renderSurface == m_defaultRenderSurface && !m_compositeOffscreen) {
+ GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ setDrawViewportRect(renderSurface->m_contentRect, true);
+ return true;
+ }
+
+ GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
+
+ if (!renderSurface->prepareContentsTexture())
+ return false;
+
+ renderSurface->m_contentsTexture->framebufferTexture2D();
+
+#if !defined ( NDEBUG )
+ if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+#endif
+
+ setDrawViewportRect(renderSurface->m_contentRect, false);
+ return true;
+}
+
+void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromium* targetSurface)
+{
+ if (layer->m_renderSurface && layer->m_renderSurface != targetSurface) {
+ layer->m_renderSurface->draw();
+ return;
+ }
+
+ if (layer->m_bounds.isEmpty())
+ return;
+
+ setScissorToRect(layer->m_scissorRect);
+
+ // Check if the layer falls within the visible bounds of the page.
+ IntRect layerRect = layer->getDrawRect();
+ bool isLayerVisible = layer->m_scissorRect.intersects(layerRect);
+ if (!isLayerVisible)
+ return;
+
+ // FIXME: Need to take into account the transform of the containing
+ // RenderSurface here, otherwise single-sided layers that draw on
+ // transformed surfaces won't always be culled properly.
+ if (!layer->doubleSided() && layer->m_drawTransform.m33() < 0)
+ return;
+
+ if (layer->drawsContent()) {
+ // Update the contents of the layer if necessary.
+ layer->updateContentsIfDirty();
+ m_context->makeContextCurrent();
+ layer->draw();
+ }
+
+ // Draw the debug border if there is one.
+ layer->drawDebugBorder();
+}
+
+// Sets the scissor region to the given rectangle. The coordinate system for the
+// scissorRect has its origin at the top left corner of the current visible rect.
+void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
+{
+ // The scissor coordinates must be supplied in viewport space so we need to offset
+ // by the relative position of the top left corner of the current render surface.
+ int scissorX = scissorRect.x() - m_currentRenderSurface->m_contentRect.x();
+ // When rendering to the default render surface we're rendering upside down so the top
+ // of the GL scissor is the bottom of our layer.
+ // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
+ int scissorY;
+ if (m_currentRenderSurface == m_defaultRenderSurface && !m_compositeOffscreen)
+ scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.bottom() - m_currentRenderSurface->m_contentRect.y());
+ else
+ scissorY = scissorRect.y() - m_currentRenderSurface->m_contentRect.y();
+ GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
+}
+
+bool LayerRendererChromium::makeContextCurrent()
+{
+ m_context->makeContextCurrent();
+ return true;
+}
+
+// Checks whether a given size is within the maximum allowed texture size range.
+bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize)
+{
+ if (textureSize.width() > m_maxTextureSize || textureSize.height() > m_maxTextureSize)
+ return false;
+ return true;
+}
+
+// Sets the coordinate range of content that ends being drawn onto the target render surface.
+// The target render surface is assumed to have an origin at 0, 0 and the width and height of
+// of the drawRect.
+void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
+{
+ if (flipY)
+ m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.bottom(), drawRect.y());
+ else
+ m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.y(), drawRect.bottom());
+ GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
+}
+
+
+
+void LayerRendererChromium::resizeOnscreenContent(const IntSize& size)
+{
+ if (m_context)
+ m_context->reshape(size.width(), size.height());
+}
+
+bool LayerRendererChromium::initializeSharedObjects()
+{
+ makeContextCurrent();
+
+ // Get the max texture size supported by the system.
+ m_maxTextureSize = 0;
+ GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
+
+ // Create an FBO for doing offscreen rendering.
+ GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
+
+ m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get()));
+ m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get()));
+ m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get()));
+ m_videoLayerSharedValues = adoptPtr(new VideoLayerChromium::SharedValues(m_context.get()));
+ m_pluginLayerSharedValues = adoptPtr(new PluginLayerChromium::SharedValues(m_context.get()));
+ m_renderSurfaceSharedValues = adoptPtr(new RenderSurfaceChromium::SharedValues(m_context.get()));
+
+ if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized()
+ || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized() || !m_renderSurfaceSharedValues->initialized()) {
+ cleanupSharedObjects();
+ return false;
+ }
+
+ m_textureManager = TextureManager::create(m_context.get(), textureMemoryLimitBytes, m_maxTextureSize);
+ return true;
+}
+
+void LayerRendererChromium::cleanupSharedObjects()
+{
+ makeContextCurrent();
+
+ m_layerSharedValues.clear();
+ m_contentLayerSharedValues.clear();
+ m_canvasLayerSharedValues.clear();
+ m_videoLayerSharedValues.clear();
+ m_pluginLayerSharedValues.clear();
+ m_renderSurfaceSharedValues.clear();
+ if (m_offscreenFramebufferId)
+ GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
+
+ m_textureManager.clear();
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
new file mode 100644
index 0000000..3d3e784
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef LayerRendererChromium_h
+#define LayerRendererChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayerChromium.h"
+#include "ContentLayerChromium.h"
+#include "IntRect.h"
+#include "LayerChromium.h"
+#include "LayerTilerChromium.h"
+#include "PluginLayerChromium.h"
+#include "RenderSurfaceChromium.h"
+#include "SkBitmap.h"
+#include "VideoLayerChromium.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(CG)
+#include <CoreGraphics/CGContext.h>
+#include <wtf/RetainPtr.h>
+#endif
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+// Class that handles drawing of composited render layers using GL.
+class LayerRendererChromium : public RefCounted<LayerRendererChromium> {
+public:
+ static PassRefPtr<LayerRendererChromium> create(PassRefPtr<GraphicsContext3D> graphicsContext3D);
+
+ ~LayerRendererChromium();
+
+ GraphicsContext3D* context();
+
+ void invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect);
+
+ // updates and draws the current layers onto the backbuffer
+ void drawLayers(const IntRect& visibleRect, const IntRect& contentRect,
+ const IntPoint& scrollPosition, TilePaintInterface& tilePaint,
+ TilePaintInterface& scrollbarPaint);
+
+ // waits for rendering to finish
+ void finish();
+
+ // puts backbuffer onscreen
+ void present();
+
+ void setRootLayer(PassRefPtr<LayerChromium> layer);
+ LayerChromium* rootLayer() { return m_rootLayer.get(); }
+ void transferRootLayer(LayerRendererChromium* other) { other->m_rootLayer = m_rootLayer.release(); }
+
+ bool hardwareCompositing() const { return m_hardwareCompositing; }
+
+ void setCompositeOffscreen(bool);
+ bool isCompositingOffscreen() { return m_compositeOffscreen; }
+ LayerTexture* getOffscreenLayerTexture() { return m_compositeOffscreen ? m_rootLayer->m_renderSurface->m_contentsTexture.get() : 0; }
+
+ void setRootLayerCanvasSize(const IntSize&);
+
+ GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); }
+
+ unsigned createLayerTexture();
+ void deleteLayerTexture(unsigned);
+
+ static void debugGLCall(GraphicsContext3D*, const char* command, const char* file, int line);
+
+ const TransformationMatrix& projectionMatrix() const { return m_projectionMatrix; }
+
+ void useShader(unsigned);
+
+ bool checkTextureSize(const IntSize&);
+
+ const LayerChromium::SharedValues* layerSharedValues() const { return m_layerSharedValues.get(); }
+ const ContentLayerChromium::SharedValues* contentLayerSharedValues() const { return m_contentLayerSharedValues.get(); }
+ const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); }
+ const VideoLayerChromium::SharedValues* videoLayerSharedValues() const { return m_videoLayerSharedValues.get(); }
+ const PluginLayerChromium::SharedValues* pluginLayerSharedValues() const { return m_pluginLayerSharedValues.get(); }
+ const RenderSurfaceChromium::SharedValues* renderSurfaceSharedValues() const { return m_renderSurfaceSharedValues.get(); }
+
+ void resizeOnscreenContent(const IntSize&);
+
+ IntSize rootLayerTextureSize() const { return IntSize(m_rootLayerTextureWidth, m_rootLayerTextureHeight); }
+ IntRect rootLayerContentRect() const { return m_rootContentRect; }
+ void getFramebufferPixels(void *pixels, const IntRect& rect);
+
+ TextureManager* textureManager() const { return m_textureManager.get(); }
+
+ void setScissorToRect(const IntRect&);
+
+private:
+ explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D);
+ void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList);
+
+ void drawLayer(LayerChromium*, RenderSurfaceChromium*);
+
+ void updateAndDrawRootLayer(TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect);
+
+ bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
+
+ void setDrawViewportRect(const IntRect&, bool flipY);
+
+ bool useRenderSurface(RenderSurfaceChromium*);
+
+ bool makeContextCurrent();
+
+ static bool compareLayerZ(const LayerChromium*, const LayerChromium*);
+
+ bool initializeSharedObjects();
+ void cleanupSharedObjects();
+
+ static IntRect verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect);
+ static IntRect horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect);
+
+ int m_rootLayerTextureWidth;
+ int m_rootLayerTextureHeight;
+
+ TransformationMatrix m_projectionMatrix;
+
+ RefPtr<LayerChromium> m_rootLayer;
+ OwnPtr<LayerTilerChromium> m_rootLayerTiler;
+ OwnPtr<LayerTilerChromium> m_horizontalScrollbarTiler;
+ OwnPtr<LayerTilerChromium> m_verticalScrollbarTiler;
+
+ IntPoint m_scrollPosition;
+ bool m_hardwareCompositing;
+
+ unsigned m_currentShader;
+ RenderSurfaceChromium* m_currentRenderSurface;
+
+ unsigned m_offscreenFramebufferId;
+ bool m_compositeOffscreen;
+
+#if PLATFORM(SKIA)
+ OwnPtr<skia::PlatformCanvas> m_rootLayerCanvas;
+ OwnPtr<PlatformContextSkia> m_rootLayerSkiaContext;
+ OwnPtr<GraphicsContext> m_rootLayerGraphicsContext;
+#elif PLATFORM(CG)
+ Vector<uint8_t> m_rootLayerBackingStore;
+ RetainPtr<CGContextRef> m_rootLayerCGContext;
+ OwnPtr<GraphicsContext> m_rootLayerGraphicsContext;
+#endif
+
+ IntSize m_rootLayerCanvasSize;
+
+ IntRect m_rootVisibleRect;
+ IntRect m_rootContentRect;
+
+ // Maximum texture dimensions supported.
+ int m_maxTextureSize;
+
+ // Store values that are shared between instances of each layer type
+ // associated with this instance of the compositor. Since there can be
+ // multiple instances of the compositor running in the same renderer process
+ // we cannot store these values in static variables.
+ OwnPtr<LayerChromium::SharedValues> m_layerSharedValues;
+ OwnPtr<ContentLayerChromium::SharedValues> m_contentLayerSharedValues;
+ OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues;
+ OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues;
+ OwnPtr<PluginLayerChromium::SharedValues> m_pluginLayerSharedValues;
+ OwnPtr<RenderSurfaceChromium::SharedValues> m_renderSurfaceSharedValues;
+
+ OwnPtr<TextureManager> m_textureManager;
+
+ RefPtr<GraphicsContext3D> m_context;
+
+ RenderSurfaceChromium* m_defaultRenderSurface;
+};
+
+// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL
+// call made by the compositor. Useful for debugging rendering issues but
+// will significantly degrade performance.
+#define DEBUG_GL_CALLS 0
+
+#if DEBUG_GL_CALLS && !defined ( NDEBUG )
+#define GLC(context, x) { (x), LayerRendererChromium::debugGLCall(context, #x, __FILE__, __LINE__); }
+#else
+#define GLC(context, x) (x)
+#endif
+
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp b/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp
new file mode 100644
index 0000000..32bfa0b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerTexture.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerTexture.h"
+
+#include "GraphicsContext3D.h"
+#include "TextureManager.h"
+
+namespace WebCore {
+
+LayerTexture::LayerTexture(GraphicsContext3D* context, TextureManager* manager)
+ : m_context(context)
+ , m_textureManager(manager)
+ , m_token(0)
+ , m_format(0)
+ , m_textureId(0)
+{
+}
+
+LayerTexture::~LayerTexture()
+{
+ if (m_token)
+ m_textureManager->releaseToken(m_token);
+}
+
+bool LayerTexture::isValid(const IntSize& size, unsigned format)
+{
+ return m_token && size == m_size && format == m_format && m_textureManager->hasTexture(m_token);
+}
+
+bool LayerTexture::reserve(const IntSize& size, unsigned format)
+{
+ if (!m_token)
+ m_token = m_textureManager->getToken();
+
+ if (size == m_size && format == m_format && m_textureManager->hasTexture(m_token))
+ m_textureManager->protectTexture(m_token);
+ else {
+ m_textureId = m_textureManager->requestTexture(m_token, size, format);
+ if (m_textureId) {
+ m_size = size;
+ m_format = format;
+ }
+ }
+
+ return m_textureId;
+}
+
+void LayerTexture::unreserve()
+{
+ if (m_token)
+ m_textureManager->unprotectTexture(m_token);
+}
+
+void LayerTexture::bindTexture()
+{
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
+}
+
+void LayerTexture::framebufferTexture2D()
+{
+ m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTexture.h b/Source/WebCore/platform/graphics/chromium/LayerTexture.h
new file mode 100644
index 0000000..312adfa
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerTexture.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LayerTexture_h
+#define LayerTexture_h
+
+#include "IntSize.h"
+#include "TextureManager.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class TextureManager;
+
+class LayerTexture : public Noncopyable {
+public:
+ static PassOwnPtr<LayerTexture> create(GraphicsContext3D* context, TextureManager* manager)
+ {
+ return adoptPtr(new LayerTexture(context, manager));
+ }
+ ~LayerTexture();
+
+ bool isValid(const IntSize&, unsigned format);
+ bool reserve(const IntSize&, unsigned format);
+ void unreserve();
+
+ void bindTexture();
+ void framebufferTexture2D();
+
+private:
+ LayerTexture(GraphicsContext3D*, TextureManager*);
+
+ RefPtr<GraphicsContext3D> m_context;
+ TextureManager* m_textureManager;
+ TextureToken m_token;
+ IntSize m_size;
+ unsigned m_format;
+ unsigned m_textureId;
+};
+
+}
+
+#endif
+
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
new file mode 100644
index 0000000..31649a4
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerTilerChromium.h"
+
+#include "GraphicsContext.h"
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+
+#if PLATFORM(SKIA)
+#include "NativeImageSkia.h"
+#include "PlatformContextSkia.h"
+#elif PLATFORM(CG)
+#include <CoreGraphics/CGBitmapContext.h>
+#endif
+
+#include <wtf/PassOwnArrayPtr.h>
+
+namespace WebCore {
+
+PassOwnPtr<LayerTilerChromium> LayerTilerChromium::create(LayerRendererChromium* layerRenderer, const IntSize& tileSize)
+{
+ if (!layerRenderer || tileSize.isEmpty())
+ return 0;
+
+ return adoptPtr(new LayerTilerChromium(layerRenderer, tileSize));
+}
+
+LayerTilerChromium::LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize)
+ : m_layerRenderer(layerRenderer)
+{
+ setTileSize(tileSize);
+}
+
+LayerTilerChromium::~LayerTilerChromium()
+{
+ reset();
+}
+
+GraphicsContext3D* LayerTilerChromium::layerRendererContext() const
+{
+ ASSERT(layerRenderer());
+ return layerRenderer()->context();
+}
+
+void LayerTilerChromium::setTileSize(const IntSize& size)
+{
+ if (m_tileSize == size)
+ return;
+
+ reset();
+
+ m_tileSize = size;
+ m_tilePixels = adoptArrayPtr(new uint8_t[m_tileSize.width() * m_tileSize.height() * 4]);
+}
+
+void LayerTilerChromium::reset()
+{
+ for (size_t i = 0; i < m_tiles.size(); ++i) {
+ if (!m_tiles[i])
+ continue;
+ layerRenderer()->deleteLayerTexture(m_tiles[i]->releaseTextureId());
+ }
+ m_tiles.clear();
+ for (size_t i = 0; i < m_unusedTiles.size(); ++i) {
+ if (!m_unusedTiles[i])
+ continue;
+ layerRenderer()->deleteLayerTexture(m_unusedTiles[i]->releaseTextureId());
+ }
+ m_unusedTiles.clear();
+
+ m_layerSize = IntSize();
+ m_layerTileSize = IntSize();
+ m_lastUpdateLayerRect = IntRect();
+}
+
+LayerTilerChromium::Tile* LayerTilerChromium::createTile(int i, int j)
+{
+ const int index = tileIndex(i, j);
+ ASSERT(!m_tiles[index]);
+
+ if (m_unusedTiles.size() > 0) {
+ m_tiles[index] = m_unusedTiles.last().release();
+ m_unusedTiles.removeLast();
+ } else {
+ const unsigned int textureId = layerRenderer()->createLayerTexture();
+ OwnPtr<Tile> tile = adoptPtr(new Tile(textureId));
+
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_tileSize.width(), m_tileSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE));
+
+ m_tiles[index] = tile.release();
+ }
+
+ m_tiles[index]->m_dirtyLayerRect = tileLayerRect(i, j);
+ return m_tiles[index].get();
+}
+
+void LayerTilerChromium::invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect)
+{
+ if (!m_tiles.size())
+ return;
+
+ IntRect oldContentRect = layerRectToContentRect(oldLayerRect);
+ int oldLeft, oldTop, oldRight, oldBottom;
+ contentRectToTileIndices(oldContentRect, oldLeft, oldTop, oldRight, oldBottom);
+
+ IntRect newContentRect = layerRectToContentRect(newLayerRect);
+ int newLeft, newTop, newRight, newBottom;
+ contentRectToTileIndices(newContentRect, newLeft, newTop, newRight, newBottom);
+
+ // Iterating through just the old tile indices is an optimization to avoid
+ // iterating through the entire m_tiles array.
+ for (int j = oldTop; j <= oldBottom; ++j) {
+ for (int i = oldLeft; i <= oldRight; ++i) {
+ if (i >= newLeft && i <= newRight && j >= newTop && j <= newBottom)
+ continue;
+
+ const int index = tileIndex(i, j);
+ if (m_tiles[index])
+ m_unusedTiles.append(m_tiles[index].release());
+ }
+ }
+}
+
+void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const
+{
+ const IntRect layerRect = contentRectToLayerRect(contentRect);
+
+ left = layerRect.x() / m_tileSize.width();
+ top = layerRect.y() / m_tileSize.height();
+ right = (layerRect.right() - 1) / m_tileSize.width();
+ bottom = (layerRect.bottom() - 1) / m_tileSize.height();
+}
+
+IntRect LayerTilerChromium::contentRectToLayerRect(const IntRect& contentRect) const
+{
+ IntPoint pos(contentRect.x() - m_layerPosition.x(), contentRect.y() - m_layerPosition.y());
+ IntRect layerRect(pos, contentRect.size());
+
+ // Clip to the position.
+ if (pos.x() < 0 || pos.y() < 0)
+ layerRect = IntRect(IntPoint(0, 0), IntSize(contentRect.width() + pos.x(), contentRect.height() + pos.y()));
+ return layerRect;
+}
+
+IntRect LayerTilerChromium::layerRectToContentRect(const IntRect& layerRect) const
+{
+ IntRect contentRect = layerRect;
+ contentRect.move(m_layerPosition.x(), m_layerPosition.y());
+ return contentRect;
+}
+
+int LayerTilerChromium::tileIndex(int i, int j) const
+{
+ ASSERT(i >= 0 && j >= 0 && i < m_layerTileSize.width() && j < m_layerTileSize.height());
+ return i + j * m_layerTileSize.width();
+}
+
+IntRect LayerTilerChromium::tileContentRect(int i, int j) const
+{
+ IntPoint anchor(m_layerPosition.x() + i * m_tileSize.width(), m_layerPosition.y() + j * m_tileSize.height());
+ IntRect tile(anchor, m_tileSize);
+ return tile;
+}
+
+IntRect LayerTilerChromium::tileLayerRect(int i, int j) const
+{
+ IntPoint anchor(i * m_tileSize.width(), j * m_tileSize.height());
+ IntRect tile(anchor, m_tileSize);
+ return tile;
+}
+
+void LayerTilerChromium::invalidateRect(const IntRect& contentRect)
+{
+ if (contentRect.isEmpty())
+ return;
+
+ growLayerToContain(contentRect);
+
+ // Dirty rects are always in layer space, as the layer could be repositioned
+ // after invalidation.
+ IntRect layerRect = contentRectToLayerRect(contentRect);
+
+ int left, top, right, bottom;
+ contentRectToTileIndices(contentRect, left, top, right, bottom);
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ Tile* tile = m_tiles[tileIndex(i, j)].get();
+ if (!tile)
+ continue;
+ IntRect bound = tileLayerRect(i, j);
+ bound.intersect(layerRect);
+ tile->m_dirtyLayerRect.unite(bound);
+ }
+ }
+}
+
+void LayerTilerChromium::invalidateEntireLayer()
+{
+ for (size_t i = 0; i < m_tiles.size(); ++i) {
+ if (m_tiles[i])
+ m_unusedTiles.append(m_tiles[i].release());
+ }
+ m_tiles.clear();
+
+ m_layerSize = IntSize();
+ m_layerTileSize = IntSize();
+ m_lastUpdateLayerRect = IntRect();
+}
+
+void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& contentRect)
+{
+ // Invalidate old tiles that were previously used but aren't in use this
+ // frame so that they can get reused for new tiles.
+ IntRect layerRect = contentRectToLayerRect(contentRect);
+ invalidateTiles(m_lastUpdateLayerRect, layerRect);
+ m_lastUpdateLayerRect = layerRect;
+
+ growLayerToContain(contentRect);
+
+ // Create tiles as needed, expanding a dirty rect to contain all
+ // the dirty regions currently being drawn.
+ IntRect dirtyLayerRect;
+ int left, top, right, bottom;
+ contentRectToTileIndices(contentRect, left, top, right, bottom);
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ Tile* tile = m_tiles[tileIndex(i, j)].get();
+ if (!tile)
+ tile = createTile(i, j);
+ dirtyLayerRect.unite(tile->m_dirtyLayerRect);
+ }
+ }
+
+ if (dirtyLayerRect.isEmpty())
+ return;
+
+ const IntRect paintRect = layerRectToContentRect(dirtyLayerRect);
+ GraphicsContext3D* context = layerRendererContext();
+#if PLATFORM(SKIA)
+ OwnPtr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas(paintRect.width(), paintRect.height(), false));
+ OwnPtr<PlatformContextSkia> skiaContext(new PlatformContextSkia(canvas.get()));
+ OwnPtr<GraphicsContext> graphicsContext(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get())));
+
+ // Bring the canvas into the coordinate system of the paint rect.
+ canvas->translate(static_cast<SkScalar>(-paintRect.x()), static_cast<SkScalar>(-paintRect.y()));
+
+ painter.paint(*graphicsContext, paintRect);
+
+ // Get the contents of the updated rect.
+ const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
+ ASSERT(bitmap.width() == paintRect.width() && bitmap.height() == paintRect.height());
+ uint8_t* paintPixels = static_cast<uint8_t*>(bitmap.getPixels());
+#elif PLATFORM(CG)
+ Vector<uint8_t> canvasPixels;
+ int rowBytes = 4 * paintRect.width();
+ canvasPixels.resize(rowBytes * paintRect.height());
+ memset(canvasPixels.data(), 0, canvasPixels.size());
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGContextRef> m_cgContext;
+ m_cgContext.adoptCF(CGBitmapContextCreate(canvasPixels.data(),
+ paintRect.width(), paintRect.height(), 8, rowBytes,
+ colorSpace.get(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ CGContextTranslateCTM(m_cgContext.get(), 0, paintRect.height());
+ CGContextScaleCTM(m_cgContext.get(), 1, -1);
+ OwnPtr<GraphicsContext> m_graphicsContext(new GraphicsContext(m_cgContext.get()));
+
+ // Bring the CoreGraphics context into the coordinate system of the paint rect.
+ CGContextTranslateCTM(m_cgContext.get(), -paintRect.x(), -paintRect.y());
+ painter.paint(*m_graphicsContext, paintRect);
+
+ // Get the contents of the updated rect.
+ ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_cgContext.get())) == paintRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_cgContext.get())) == paintRect.height());
+ uint8_t* paintPixels = static_cast<uint8_t*>(canvasPixels.data());
+#else
+#error "Need to implement for your platform."
+#endif
+
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ Tile* tile = m_tiles[tileIndex(i, j)].get();
+ if (!tile->dirty())
+ continue;
+
+ // Calculate page-space rectangle to copy from.
+ IntRect sourceRect = tileContentRect(i, j);
+ const IntPoint anchor = sourceRect.location();
+ sourceRect.intersect(layerRectToContentRect(tile->m_dirtyLayerRect));
+
+ // Calculate tile-space rectangle to upload into.
+ IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()), sourceRect.size());
+
+ // Offset from paint rectangle to this tile's dirty rectangle.
+ IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y());
+
+ uint8_t* pixelSource;
+ if (paintRect.width() == sourceRect.width() && !paintOffset.x())
+ pixelSource = &paintPixels[4 * paintOffset.y() * paintRect.width()];
+ else {
+ // Strides not equal, so do a row-by-row memcpy from the
+ // paint results into a temp buffer for uploading.
+ for (int row = 0; row < destRect.height(); ++row)
+ memcpy(&m_tilePixels[destRect.width() * 4 * row],
+ &paintPixels[4 * (paintOffset.x() + (paintOffset.y() + row) * paintRect.width())],
+ destRect.width() * 4);
+
+ pixelSource = &m_tilePixels[0];
+ }
+
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, tile->textureId()));
+ GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destRect.x(), destRect.y(), destRect.width(), destRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixelSource));
+
+ tile->clearDirty();
+ }
+ }
+}
+
+void LayerTilerChromium::setLayerPosition(const IntPoint& layerPosition)
+{
+ m_layerPosition = layerPosition;
+}
+
+void LayerTilerChromium::draw(const IntRect& contentRect)
+{
+ // We reuse the shader program used by ContentLayerChromium.
+ GraphicsContext3D* context = layerRendererContext();
+ const ContentLayerChromium::SharedValues* contentLayerValues = layerRenderer()->contentLayerSharedValues();
+ layerRenderer()->useShader(contentLayerValues->contentShaderProgram());
+ GLC(context, context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0));
+
+ int left, top, right, bottom;
+ contentRectToTileIndices(contentRect, left, top, right, bottom);
+ for (int j = top; j <= bottom; ++j) {
+ for (int i = left; i <= right; ++i) {
+ Tile* tile = m_tiles[tileIndex(i, j)].get();
+ ASSERT(tile);
+
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, tile->textureId()));
+
+ TransformationMatrix tileMatrix;
+ IntRect tileRect = tileContentRect(i, j);
+ tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0);
+
+ LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), tileMatrix, m_tileSize.width(), m_tileSize.height(), 1, contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation());
+ }
+ }
+}
+
+void LayerTilerChromium::resizeLayer(const IntSize& size)
+{
+ if (m_layerSize == size)
+ return;
+
+ int width = (size.width() + m_tileSize.width() - 1) / m_tileSize.width();
+ int height = (size.height() + m_tileSize.height() - 1) / m_tileSize.height();
+
+ Vector<OwnPtr<Tile> > newTiles;
+ newTiles.resize(width * height);
+ for (int j = 0; j < m_layerTileSize.height(); ++j)
+ for (int i = 0; i < m_layerTileSize.width(); ++i)
+ newTiles[i + j * width].swap(m_tiles[i + j * m_layerTileSize.width()]);
+
+ m_tiles.swap(newTiles);
+ m_layerSize = size;
+ m_layerTileSize = IntSize(width, height);
+}
+
+void LayerTilerChromium::growLayerToContain(const IntRect& contentRect)
+{
+ // Grow the tile array to contain this content rect.
+ IntRect layerRect = contentRectToLayerRect(contentRect);
+ IntSize layerSize = IntSize(layerRect.right(), layerRect.bottom());
+
+ IntSize newSize = layerSize.expandedTo(m_layerSize);
+ resizeLayer(newSize);
+}
+
+LayerTilerChromium::Tile::~Tile()
+{
+ // Each tile doesn't have a reference to the context, so can't clean up
+ // its own texture. If this assert is hit, then the LayerTilerChromium
+ // destructor didn't clean this up.
+ ASSERT(!m_textureId);
+}
+
+unsigned int LayerTilerChromium::Tile::releaseTextureId()
+{
+ unsigned int id = m_textureId;
+ m_textureId = 0;
+ return id;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
new file mode 100644
index 0000000..c066fdf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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 LayerTilerChromium_h
+#define LayerTilerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+#include <wtf/OwnArrayPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class LayerRendererChromium;
+
+class TilePaintInterface {
+public:
+ virtual void paint(GraphicsContext& context, const IntRect& contentRect) = 0;
+};
+
+class LayerTilerChromium : public Noncopyable {
+public:
+ static PassOwnPtr<LayerTilerChromium> create(LayerRendererChromium* layerRenderer, const IntSize& tileSize);
+
+ ~LayerTilerChromium();
+
+ void invalidateRect(const IntRect& contentRect);
+ void invalidateEntireLayer();
+ void update(TilePaintInterface& painter, const IntRect& contentRect);
+ void draw(const IntRect& contentRect);
+
+ // Set position of this tiled layer in content space.
+ void setLayerPosition(const IntPoint& position);
+ // Change the tile size. This may invalidate all the existing tiles.
+ void setTileSize(const IntSize& size);
+
+private:
+ LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize);
+
+ class Tile {
+ public:
+ explicit Tile(unsigned int textureId) : m_textureId(textureId) { }
+ ~Tile();
+
+ unsigned int textureId() const { return m_textureId; }
+ unsigned int releaseTextureId();
+
+ bool dirty() const { return !m_dirtyLayerRect.isEmpty(); }
+ void clearDirty() { m_dirtyLayerRect = IntRect(); }
+
+ // Layer-space dirty rectangle that needs to be repainted.
+ IntRect m_dirtyLayerRect;
+ private:
+ unsigned int m_textureId;
+ };
+
+ void resizeLayer(const IntSize& size);
+ // Grow layer size to contain this rectangle.
+ void growLayerToContain(const IntRect& contentRect);
+
+ LayerRendererChromium* layerRenderer() const { return m_layerRenderer; }
+ GraphicsContext3D* layerRendererContext() const;
+ Tile* createTile(int i, int j);
+ // Invalidate any tiles which do not intersect with the newLayerRect.
+ void invalidateTiles(const IntRect& oldLayerRect, const IntRect& newLayerRect);
+ void reset();
+ void contentRectToTileIndices(const IntRect& contentRect, int &left, int &top, int &right, int &bottom) const;
+ IntRect contentRectToLayerRect(const IntRect& contentRect) const;
+ IntRect layerRectToContentRect(const IntRect& layerRect) const;
+
+ // Returns the index into m_tiles for a given tile location.
+ int tileIndex(int i, int j) const;
+ // Returns the bounds in content space for a given tile location.
+ IntRect tileContentRect(int i, int j) const;
+ // Returns the bounds in layer space for a given tile location.
+ IntRect tileLayerRect(int i, int j) const;
+
+ IntSize m_tileSize;
+ IntSize m_layerSize;
+ IntSize m_layerTileSize;
+ IntRect m_lastUpdateLayerRect;
+ IntPoint m_layerPosition;
+
+ // Logical 2D array of tiles (dimensions of m_layerTileSize)
+ Vector<OwnPtr<Tile> > m_tiles;
+ // Linear array of unused tiles.
+ Vector<OwnPtr<Tile> > m_unusedTiles;
+
+ // Cache a tile-sized pixel buffer to draw into.
+ OwnArrayPtr<uint8_t> m_tilePixels;
+
+ LayerRendererChromium* m_layerRenderer;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h b/Source/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
new file mode 100644
index 0000000..534244d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/MediaPlayerPrivateChromium.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MediaPlayerPrivateChromium_h
+#define MediaPlayerPrivateChromium_h
+
+#if ENABLE(VIDEO)
+
+#include "MediaPlayerPrivate.h"
+
+namespace WebCore {
+
+class MediaPlayerPrivate {
+public:
+ static void registerMediaEngine(MediaEngineRegistrar);
+};
+
+} // namespace WebCore
+
+#endif
+
+#endif // MediaPlayerPrivateChromium_h
diff --git a/Source/WebCore/platform/graphics/chromium/PlatformIcon.h b/Source/WebCore/platform/graphics/chromium/PlatformIcon.h
new file mode 100644
index 0000000..51613b8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/PlatformIcon.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlatformIcon_h
+#define PlatformIcon_h
+
+typedef struct HICON__* HICON;
+
+namespace WebCore {
+
+typedef HICON PlatformIcon;
+
+} // namespace WebCore
+
+#endif // PlatformIcon_h
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
new file mode 100644
index 0000000..878c142
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "PluginLayerChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include <GLES2/gl2.h>
+
+namespace WebCore {
+
+PluginLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_shaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ char vertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+ char fragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, v_texCoord.y)); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_shaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString);
+ if (!m_shaderProgram) {
+ LOG_ERROR("PluginLayerChromium: Failed to create shader program");
+ return;
+ }
+
+ m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture");
+ m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix");
+ m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha");
+ ASSERT(m_shaderSamplerLocation != -1);
+ ASSERT(m_shaderMatrixLocation != -1);
+ ASSERT(m_shaderAlphaLocation != -1);
+
+ m_initialized = true;
+}
+
+PluginLayerChromium::SharedValues::~SharedValues()
+{
+ if (m_shaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_shaderProgram));
+}
+
+PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new PluginLayerChromium(owner));
+}
+
+PluginLayerChromium::PluginLayerChromium(GraphicsLayerChromium* owner)
+ : LayerChromium(owner)
+{
+}
+
+void PluginLayerChromium::setTextureId(unsigned id)
+{
+ m_textureId = id;
+}
+
+void PluginLayerChromium::updateContentsIfDirty()
+{
+}
+
+void PluginLayerChromium::draw()
+{
+ ASSERT(layerRenderer());
+ const PluginLayerChromium::SharedValues* sv = layerRenderer()->pluginLayerSharedValues();
+ ASSERT(sv && sv->initialized());
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->activeTexture(GL_TEXTURE0));
+ GLC(context, context->bindTexture(GL_TEXTURE_2D, m_textureId));
+
+ // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
+ // where it will only happen once per texture.
+ GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
+ GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
+ GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+ GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+
+ layerRenderer()->useShader(sv->shaderProgram());
+ GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
new file mode 100644
index 0000000..853b328
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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 PluginLayerChromium_h
+#define PluginLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+
+namespace WebCore {
+
+// A Layer containing a the rendered output of a plugin instance.
+class PluginLayerChromium : public LayerChromium {
+public:
+ static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0);
+ virtual bool drawsContent() { return true; }
+ virtual void updateContentsIfDirty();
+ virtual void draw();
+
+ void setTextureId(unsigned textureId);
+
+ class SharedValues {
+ public:
+ SharedValues(GraphicsContext3D* context);
+ ~SharedValues();
+
+ unsigned shaderProgram() const { return m_shaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+ unsigned m_shaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ bool m_initialized;
+ };
+
+private:
+ PluginLayerChromium(GraphicsLayerChromium* owner);
+ unsigned m_textureId;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
new file mode 100644
index 0000000..e8b9a12
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "RenderSurfaceChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
+
+namespace WebCore {
+
+RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_shaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ // The following program composites layers whose contents are the results of a previous
+ // render operation and therefore doesn't perform any color swizzling. It is used
+ // in scrolling and for compositing offscreen textures.
+ char renderSurfaceVertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+ char renderSurfaceFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_shaderProgram = LayerChromium::createShaderProgram(m_context, renderSurfaceVertexShaderString, renderSurfaceFragmentShaderString);
+ if (!m_shaderProgram) {
+ LOG_ERROR("RenderSurfaceChromium: Failed to create shader program");
+ return;
+ }
+
+ GLC(m_context, m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture"));
+ GLC(m_context, m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix"));
+ GLC(m_context, m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha"));
+ if (m_shaderSamplerLocation == -1 || m_shaderMatrixLocation == -1 || m_shaderAlphaLocation == -1) {
+ LOG_ERROR("Failed to initialize texture layer shader.");
+ return;
+ }
+ m_initialized = true;
+}
+
+RenderSurfaceChromium::SharedValues::~SharedValues()
+{
+ if (m_shaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_shaderProgram));
+}
+
+RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer)
+ : m_owningLayer(owningLayer)
+ , m_skipsDraw(false)
+{
+}
+
+RenderSurfaceChromium::~RenderSurfaceChromium()
+{
+ cleanupResources();
+}
+
+void RenderSurfaceChromium::cleanupResources()
+{
+ if (!m_contentsTexture)
+ return;
+
+ ASSERT(layerRenderer());
+
+ m_contentsTexture.clear();
+}
+
+LayerRendererChromium* RenderSurfaceChromium::layerRenderer()
+{
+ ASSERT(m_owningLayer);
+ return m_owningLayer->layerRenderer();
+}
+
+bool RenderSurfaceChromium::prepareContentsTexture()
+{
+ IntSize requiredSize(m_contentRect.size());
+ TextureManager* textureManager = layerRenderer()->textureManager();
+
+ if (!m_contentsTexture)
+ m_contentsTexture = LayerTexture::create(layerRenderer()->context(), textureManager);
+
+ if (!m_contentsTexture->reserve(requiredSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ return false;
+ }
+
+ m_skipsDraw = false;
+ return true;
+}
+
+void RenderSurfaceChromium::draw()
+{
+ if (m_skipsDraw || !m_contentsTexture)
+ return;
+
+ m_contentsTexture->bindTexture();
+
+ const RenderSurfaceChromium::SharedValues* sv = layerRenderer()->renderSurfaceSharedValues();
+ ASSERT(sv && sv->initialized());
+
+ layerRenderer()->useShader(sv->shaderProgram());
+ layerRenderer()->setScissorToRect(m_scissorRect);
+
+ LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), m_drawTransform,
+ m_contentRect.width(), m_contentRect.height(), m_drawOpacity,
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+
+ m_contentsTexture->unreserve();
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
new file mode 100644
index 0000000..a93218f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 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 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 RenderSurfaceChromium_h
+#define RenderSurfaceChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatRect.h"
+#include "IntRect.h"
+#include "TextureManager.h"
+#include "TransformationMatrix.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class LayerChromium;
+class LayerRendererChromium;
+class LayerTexture;
+
+class RenderSurfaceChromium : public Noncopyable {
+ friend class LayerRendererChromium;
+public:
+ explicit RenderSurfaceChromium(LayerChromium*);
+ ~RenderSurfaceChromium();
+
+ bool prepareContentsTexture();
+ void cleanupResources();
+ void draw();
+
+ FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); }
+ IntRect contentRect() const { return m_contentRect; }
+
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+
+ unsigned shaderProgram() const { return m_shaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+
+ unsigned m_shaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ bool m_initialized;
+ };
+
+private:
+ LayerRendererChromium* layerRenderer();
+
+ LayerChromium* m_owningLayer;
+ IntRect m_contentRect;
+ bool m_skipsDraw;
+ OwnPtr<LayerTexture> m_contentsTexture;
+ float m_drawOpacity;
+ TransformationMatrix m_drawTransform;
+ TransformationMatrix m_originTransform;
+ IntRect m_scissorRect;
+ Vector<LayerChromium*> m_layerList;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
new file mode 100644
index 0000000..204c565
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SimpleFontData.h"
+
+#include "ChromiumBridge.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 <objidl.h>
+#include <mlang.h>
+
+namespace WebCore {
+
+static inline float scaleEmToUnits(float x, int unitsPerEm)
+{
+ return unitsPerEm ? x / static_cast<float>(unitsPerEm) : x;
+}
+
+void SimpleFontData::platformInit()
+{
+ if (!m_platformData.size()) {
+ m_ascent = 0;
+ m_descent = 0;
+ m_lineGap = 0;
+ m_lineSpacing = 0;
+ m_avgCharWidth = 0;
+ m_maxCharWidth = 0;
+ m_xHeight = 0;
+ m_unitsPerEm = 0;
+ return;
+ }
+
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
+
+ TEXTMETRIC textMetric = {0};
+ if (!GetTextMetrics(dc, &textMetric)) {
+ if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
+ // Retry GetTextMetrics.
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401.
+ if (!GetTextMetrics(dc, &textMetric))
+ LOG_ERROR("Unable to get the text metrics after second attempt");
+ }
+ }
+
+ m_avgCharWidth = textMetric.tmAveCharWidth;
+ m_maxCharWidth = textMetric.tmMaxCharWidth;
+
+ m_ascent = textMetric.tmAscent;
+ m_descent = textMetric.tmDescent;
+ m_lineGap = textMetric.tmExternalLeading;
+ m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
+
+ OUTLINETEXTMETRIC outlineTextMetric;
+ if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
+ // This is a TrueType font. We might be able to get an accurate xHeight.
+ GLYPHMETRICS glyphMetrics = {0};
+ MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
+ DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
+ if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
+ m_xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
+ }
+
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ // charwidths are set in platformInit.
+}
+
+void SimpleFontData::platformDestroy()
+{
+}
+
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ LOGFONT winFont;
+ GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
+ float scaledSize = scaleFactor * fontDescription.computedSize();
+ winFont.lfHeight = -lroundf(scaledSize);
+ HFONT hfont = CreateFontIndirect(&winFont);
+ return new SimpleFontData(FontPlatformData(hfont, scaledSize), isCustomFont(), false);
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ // This used to be implemented with IMLangFontLink2, but since that code has
+ // been disabled, this would always return false anyway.
+ return false;
+}
+
+void SimpleFontData::determinePitch()
+{
+ // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
+
+ // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
+ // is *not* fixed pitch. Unbelievable but true.
+ TEXTMETRIC textMetric = {0};
+ if (!GetTextMetrics(dc, &textMetric)) {
+ if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
+ // Retry GetTextMetrics.
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401.
+ if (!GetTextMetrics(dc, &textMetric))
+ LOG_ERROR("Unable to get the text metrics after second attempt");
+ }
+ }
+
+ m_treatAsFixedPitch = ((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+}
+
+FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const
+{
+ return FloatRect();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ if (!m_platformData.size())
+ return 0;
+
+ HDC dc = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
+
+ int width = 0;
+ if (!GetCharWidthI(dc, glyph, 1, 0, &width)) {
+ // Ask the browser to preload the font and retry.
+ if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
+ // FIXME: Handle gracefully the error if this call also fails.
+ // See http://crbug.com/6401.
+ if (!GetCharWidthI(dc, glyph, 1, 0, &width))
+ LOG_ERROR("Unable to get the char width after second attempt");
+ }
+ }
+
+ SelectObject(dc, oldFont);
+ ReleaseDC(0, dc);
+
+ return static_cast<float>(width);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
new file mode 100644
index 0000000..355d837
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SimpleFontData.h"
+
+#include "Font.h"
+#include "FontCache.h"
+#include "FloatRect.h"
+#include "FontDescription.h"
+#include "Logging.h"
+#include "VDMXParser.h"
+
+#include "SkFontHost.h"
+#include "SkPaint.h"
+#include "SkTime.h"
+#include "SkTypeface.h"
+#include "SkTypes.h"
+
+namespace WebCore {
+
+// Smallcaps versions of fonts are 70% the size of the normal font.
+static const float smallCapsFraction = 0.7f;
+static const float emphasisMarkFraction = .5;
+// This is the largest VDMX table which we'll try to load and parse.
+static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB
+
+void SimpleFontData::platformInit()
+{
+ if (!m_platformData.size()) {
+ m_ascent = 0;
+ m_descent = 0;
+ m_lineGap = 0;
+ m_lineSpacing = 0;
+ m_avgCharWidth = 0;
+ m_maxCharWidth = 0;
+ m_xHeight = 0;
+ m_unitsPerEm = 0;
+ return;
+ }
+
+ SkPaint paint;
+ SkPaint::FontMetrics metrics;
+
+ m_platformData.setupPaint(&paint);
+ paint.getFontMetrics(&metrics);
+ const SkFontID fontID = m_platformData.uniqueID();
+
+ static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
+ int pixelSize = m_platformData.size() + 0.5;
+ int vdmxAscent, vdmxDescent;
+ bool isVDMXValid = false;
+
+ size_t vdmxSize = SkFontHost::GetTableSize(fontID, vdmxTag);
+ if (vdmxSize && vdmxSize < maxVDMXTableSize) {
+ uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
+ if (vdmxTable
+ && SkFontHost::GetTableData(fontID, vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
+ && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
+ isVDMXValid = true;
+ fastFree(vdmxTable);
+ }
+
+ // Beware those who step here: This code is designed to match Win32 font
+ // metrics *exactly*.
+ if (isVDMXValid) {
+ m_ascent = vdmxAscent;
+ m_descent = -vdmxDescent;
+ } else {
+ SkScalar height = -metrics.fAscent + metrics.fDescent + metrics.fLeading;
+ m_ascent = SkScalarRound(-metrics.fAscent);
+ m_descent = SkScalarRound(height) - m_ascent;
+ }
+
+ if (metrics.fXHeight)
+ m_xHeight = metrics.fXHeight;
+ else {
+ // hack taken from the Windows port
+ m_xHeight = static_cast<float>(m_ascent) * 0.56;
+ }
+
+ m_lineGap = SkScalarRound(metrics.fLeading);
+ m_lineSpacing = m_ascent + m_descent + m_lineGap;
+
+ if (m_orientation == Vertical) {
+ static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
+ static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
+ size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag);
+ size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag);
+ if ((vheaSize <= 0) && (vorgSize <= 0))
+ m_orientation = Horizontal;
+ }
+
+ // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
+ // calculated for us, but we need to calculate m_maxCharWidth and
+ // m_avgCharWidth in order for text entry widgets to be sized correctly.
+
+ SkScalar xRange = metrics.fXMax - metrics.fXMin;
+ m_maxCharWidth = SkScalarRound(xRange * SkScalarRound(m_platformData.size()));
+
+ if (metrics.fAvgCharWidth)
+ m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
+ else {
+ m_avgCharWidth = m_xHeight;
+
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+
+ if (glyphPageZero) {
+ static const UChar32 x_char = 'x';
+ const Glyph xGlyph = glyphPageZero->glyphDataForCharacter(x_char).glyph;
+
+ if (xGlyph)
+ m_avgCharWidth = widthForGlyph(xGlyph);
+ }
+ }
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ // charwidths are set in platformInit.
+}
+
+void SimpleFontData::platformDestroy()
+{
+}
+
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
+ return new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false);
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, smallCapsFraction);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, emphasisMarkFraction);
+
+ return m_derivedFontData->emphasisMark.get();
+}
+
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
+{
+ SkPaint paint;
+ static const unsigned maxBufferCount = 64;
+ uint16_t glyphs[maxBufferCount];
+
+ m_platformData.setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ while (length > 0) {
+ int n = SkMin32(length, SK_ARRAY_COUNT(glyphs));
+
+ // textToGlyphs takes a byte count so we double the character count.
+ int count = paint.textToGlyphs(characters, n * 2, glyphs);
+ for (int i = 0; i < count; i++) {
+ if (0 == glyphs[i])
+ return false; // missing glyph
+ }
+
+ characters += n;
+ length -= n;
+ }
+
+ return true;
+}
+
+void SimpleFontData::determinePitch()
+{
+ m_treatAsFixedPitch = platformData().isFixedPitch();
+}
+
+FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const
+{
+ return FloatRect();
+}
+
+float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
+{
+ if (!m_platformData.size())
+ return 0;
+
+ SkASSERT(sizeof(glyph) == 2); // compile-time assert
+
+ SkPaint paint;
+
+ m_platformData.setupPaint(&paint);
+
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ SkScalar width = paint.measureText(&glyph, 2);
+
+ // Though WebKit supports non-integral advances, Skia only supports them
+ // for "subpixel" (distinct from LCD subpixel antialiasing) text, which
+ // we don't use.
+ return round(SkScalarToFloat(width));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp
new file mode 100644
index 0000000..9579ef9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "TextureManager.h"
+
+#include "LayerRendererChromium.h"
+
+namespace WebCore {
+
+static size_t memoryUseBytes(IntSize size, unsigned textureFormat)
+{
+ // FIXME: This assumes all textures are 4 bytes/pixel, like RGBA.
+ return size.width() * size.height() * 4;
+}
+
+TextureManager::TextureManager(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize)
+ : m_context(context)
+ , m_memoryLimitBytes(memoryLimitBytes)
+ , m_memoryUseBytes(0)
+ , m_maxTextureSize(maxTextureSize)
+ , m_nextToken(1)
+{
+}
+
+TextureToken TextureManager::getToken()
+{
+ return m_nextToken++;
+}
+
+void TextureManager::releaseToken(TextureToken token)
+{
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end())
+ removeTexture(token, it->second);
+}
+
+bool TextureManager::hasTexture(TextureToken token)
+{
+ if (m_textures.contains(token)) {
+ // If someone asks about a texture put it at the end of the LRU list.
+ m_textureLRUSet.remove(token);
+ m_textureLRUSet.add(token);
+ return true;
+ }
+ return false;
+}
+
+void TextureManager::protectTexture(TextureToken token)
+{
+ ASSERT(hasTexture(token));
+ ASSERT(!m_textures.get(token).isProtected);
+ TextureInfo info = m_textures.take(token);
+ info.isProtected = true;
+ m_textures.add(token, info);
+}
+
+void TextureManager::unprotectTexture(TextureToken token)
+{
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end()) {
+ TextureInfo info = it->second;
+ if (info.isProtected) {
+ info.isProtected = false;
+ m_textures.remove(it);
+ m_textures.add(token, info);
+ }
+ }
+}
+
+bool TextureManager::reduceMemoryToLimit(size_t limit)
+{
+ while (m_memoryUseBytes > limit) {
+ ASSERT(!m_textureLRUSet.isEmpty());
+ bool foundCandidate = false;
+ for (ListHashSet<TextureToken>::iterator lruIt = m_textureLRUSet.begin(); lruIt != m_textureLRUSet.end(); ++lruIt) {
+ TextureToken token = *lruIt;
+ TextureInfo info = m_textures.get(token);
+ if (info.isProtected)
+ continue;
+ removeTexture(token, info);
+ foundCandidate = true;
+ break;
+ }
+ if (!foundCandidate)
+ return false;
+ }
+ return true;
+}
+
+void TextureManager::addTexture(TextureToken token, TextureInfo info)
+{
+ ASSERT(!m_textureLRUSet.contains(token));
+ ASSERT(!m_textures.contains(token));
+ m_memoryUseBytes += memoryUseBytes(info.size, info.format);
+ m_textures.set(token, info);
+ m_textureLRUSet.add(token);
+}
+
+void TextureManager::removeTexture(TextureToken token, TextureInfo info)
+{
+ ASSERT(m_textureLRUSet.contains(token));
+ ASSERT(m_textures.contains(token));
+ m_memoryUseBytes -= memoryUseBytes(info.size, info.format);
+ m_textures.remove(token);
+ ASSERT(m_textureLRUSet.contains(token));
+ m_textureLRUSet.remove(token);
+ GLC(m_context.get(), m_context->deleteTexture(info.textureId));
+}
+
+unsigned TextureManager::requestTexture(TextureToken token, IntSize size, unsigned format, bool* newTexture)
+{
+ if (size.width() > m_maxTextureSize || size.height() > m_maxTextureSize)
+ return 0;
+
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end()) {
+ ASSERT(it->second.size != size || it->second.format != format);
+ removeTexture(token, it->second);
+ }
+
+ size_t memoryRequiredBytes = memoryUseBytes(size, format);
+ if (memoryRequiredBytes > m_memoryLimitBytes || !reduceMemoryToLimit(m_memoryLimitBytes - memoryRequiredBytes))
+ return 0;
+
+ unsigned textureId = m_context->createTexture();
+ GLC(m_context.get(), textureId = m_context->createTexture());
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ // Do basic linear filtering on resize.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE));
+ TextureInfo info;
+ info.size = size;
+ info.format = format;
+ info.textureId = textureId;
+ info.isProtected = true;
+ addTexture(token, info);
+ return textureId;
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.h b/Source/WebCore/platform/graphics/chromium/TextureManager.h
new file mode 100644
index 0000000..1e850cd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TextureManager.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextureManager_h
+#define TextureManager_h
+
+#include "GraphicsContext3D.h"
+#include "IntRect.h"
+#include "IntSize.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/ListHashSet.h>
+
+namespace WebCore {
+
+typedef int TextureToken;
+
+class TextureManager : public Noncopyable {
+public:
+ static PassOwnPtr<TextureManager> create(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize)
+ {
+ return adoptPtr(new TextureManager(context, memoryLimitBytes, maxTextureSize));
+ }
+
+ TextureToken getToken();
+ void releaseToken(TextureToken);
+ bool hasTexture(TextureToken);
+
+ unsigned requestTexture(TextureToken, IntSize, unsigned textureFormat, bool* newTexture = 0);
+
+ void protectTexture(TextureToken);
+ void unprotectTexture(TextureToken);
+
+private:
+ TextureManager(GraphicsContext3D*, size_t memoryLimitBytes, int maxTextureSize);
+
+ struct TextureInfo {
+ IntSize size;
+ unsigned format;
+ unsigned textureId;
+ bool isProtected;
+ };
+
+ bool reduceMemoryToLimit(size_t);
+ void addTexture(TextureToken, TextureInfo);
+ void removeTexture(TextureToken, TextureInfo);
+
+ RefPtr<GraphicsContext3D> m_context;
+
+ typedef HashMap<TextureToken, TextureInfo> TextureMap;
+ TextureMap m_textures;
+ ListHashSet<TextureToken> m_textureLRUSet;
+
+ size_t m_memoryLimitBytes;
+ size_t m_memoryUseBytes;
+ int m_maxTextureSize;
+ TextureToken m_nextToken;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
new file mode 100644
index 0000000..4dc2157
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.cpp
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include <windows.h>
+
+#include "AffineTransform.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "PlatformContextSkia.h"
+#include "SimpleFontData.h"
+#include "TransparencyWin.h"
+
+#include "SkColorPriv.h"
+#include "skia/ext/platform_canvas.h"
+
+namespace WebCore {
+
+namespace {
+
+// The maximum size in pixels of the buffer we'll keep around for drawing text
+// into. Buffers larger than this will be destroyed when we're done with them.
+const int maxCachedBufferPixelSize = 65536;
+
+inline skia::PlatformCanvas* canvasForContext(const GraphicsContext& context)
+{
+ return context.platformContext()->canvas();
+}
+
+inline const SkBitmap& bitmapForContext(const GraphicsContext& context)
+{
+ return canvasForContext(context)->getTopPlatformDevice().accessBitmap(false);
+}
+
+void compositeToCopy(const GraphicsContext& sourceLayers,
+ GraphicsContext& destContext,
+ const AffineTransform& matrix)
+{
+ // Make a list of all devices. The iterator goes top-down, and we want
+ // bottom-up. Note that each layer can also have an offset in canvas
+ // coordinates, which is the (x, y) position.
+ struct DeviceInfo {
+ DeviceInfo(SkDevice* d, int lx, int ly)
+ : device(d)
+ , x(lx)
+ , y(ly) {}
+ SkDevice* device;
+ int x;
+ int y;
+ };
+ Vector<DeviceInfo> devices;
+ SkCanvas* sourceCanvas = canvasForContext(sourceLayers);
+ SkCanvas::LayerIter iter(sourceCanvas, false);
+ while (!iter.done()) {
+ devices.append(DeviceInfo(iter.device(), iter.x(), iter.y()));
+ iter.next();
+ }
+
+ // Create a temporary canvas for the compositing into the destination.
+ SkBitmap* destBmp = const_cast<SkBitmap*>(&bitmapForContext(destContext));
+ SkCanvas destCanvas(*destBmp);
+ destCanvas.setMatrix(matrix);
+
+ for (int i = devices.size() - 1; i >= 0; i--) {
+ const SkBitmap& srcBmp = devices[i].device->accessBitmap(false);
+
+ SkRect destRect;
+ destRect.fLeft = devices[i].x;
+ destRect.fTop = devices[i].y;
+ destRect.fRight = destRect.fLeft + srcBmp.width();
+ destRect.fBottom = destRect.fTop + srcBmp.height();
+
+ destCanvas.drawBitmapRect(srcBmp, 0, destRect);
+ }
+}
+
+} // namespace
+
+// If either of these pointers is non-null, both must be valid and point to
+// bitmaps of the same size.
+class TransparencyWin::OwnedBuffers {
+public:
+ OwnedBuffers(const IntSize& size, bool needReferenceBuffer)
+ {
+ m_destBitmap = ImageBuffer::create(size);
+
+ if (needReferenceBuffer) {
+ m_referenceBitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
+ m_referenceBitmap.allocPixels();
+ m_referenceBitmap.eraseARGB(0, 0, 0, 0);
+ }
+ }
+
+ ImageBuffer* destBitmap() { return m_destBitmap.get(); }
+
+ // This bitmap will be empty if you don't specify needReferenceBuffer to the
+ // constructor.
+ SkBitmap* referenceBitmap() { return &m_referenceBitmap; }
+
+ // Returns whether the current layer will fix a buffer of the given size.
+ bool canHandleSize(const IntSize& size) const
+ {
+ return m_destBitmap->size().width() >= size.width() && m_destBitmap->size().height() >= size.height();
+ }
+
+private:
+ // The destination bitmap we're drawing into.
+ OwnPtr<ImageBuffer> m_destBitmap;
+
+ // This could be an ImageBuffer but this is an optimization. Since this is
+ // only ever used as a reference, we don't need to make a full
+ // PlatformCanvas using Skia on Windows. Just allocating a regular SkBitmap
+ // is much faster since it's just a Malloc rather than a GDI call.
+ SkBitmap m_referenceBitmap;
+};
+
+TransparencyWin::OwnedBuffers* TransparencyWin::m_cachedBuffers = 0;
+
+TransparencyWin::TransparencyWin()
+ : m_destContext(0)
+ , m_orgTransform()
+ , m_layerMode(NoLayer)
+ , m_transformMode(KeepTransform)
+ , m_drawContext(0)
+ , m_savedOnDrawContext(false)
+ , m_layerBuffer(0)
+ , m_referenceBitmap(0)
+ , m_validLayer(false)
+{
+}
+
+TransparencyWin::~TransparencyWin()
+{
+ // This should be false, since calling composite() is mandatory.
+ ASSERT(!m_savedOnDrawContext);
+}
+
+void TransparencyWin::composite()
+{
+ // Matches the save() in initializeNewTextContext (or the constructor for
+ // SCALE) to put the context back into the same state we found it.
+ if (m_savedOnDrawContext) {
+ m_drawContext->restore();
+ m_savedOnDrawContext = false;
+ }
+
+ switch (m_layerMode) {
+ case NoLayer:
+ break;
+ case OpaqueCompositeLayer:
+ case WhiteLayer:
+ compositeOpaqueComposite();
+ break;
+ case TextComposite:
+ compositeTextComposite();
+ break;
+ }
+}
+
+void TransparencyWin::init(GraphicsContext* dest,
+ LayerMode layerMode,
+ TransformMode transformMode,
+ const IntRect& region)
+{
+ m_destContext = dest;
+ m_orgTransform = dest->getCTM();
+ m_layerMode = layerMode;
+ m_transformMode = transformMode;
+ m_sourceRect = region;
+
+ computeLayerSize();
+ setupLayer();
+ setupTransform(region);
+}
+
+void TransparencyWin::computeLayerSize()
+{
+ if (m_transformMode == Untransform) {
+ // The meaning of the "transformed" source rect is a little ambigous
+ // here. The rest of the code doesn't care about it in the Untransform
+ // case since we're using our own happy coordinate system. So we set it
+ // to be the source rect since that matches how the code below actually
+ // uses the variable: to determine how to translate things to account
+ // for the offset of the layer.
+ m_transformedSourceRect = m_sourceRect;
+ m_layerSize = IntSize(m_sourceRect.width(), m_sourceRect.height());
+ } else {
+ m_transformedSourceRect = m_orgTransform.mapRect(m_sourceRect);
+ m_layerSize = IntSize(m_transformedSourceRect.width(), m_transformedSourceRect.height());
+ }
+}
+
+void TransparencyWin::setupLayer()
+{
+ switch (m_layerMode) {
+ case NoLayer:
+ setupLayerForNoLayer();
+ break;
+ case OpaqueCompositeLayer:
+ setupLayerForOpaqueCompositeLayer();
+ break;
+ case TextComposite:
+ setupLayerForTextComposite();
+ break;
+ case WhiteLayer:
+ setupLayerForWhiteLayer();
+ break;
+ }
+}
+
+void TransparencyWin::setupLayerForNoLayer()
+{
+ m_drawContext = m_destContext; // Draw to the source context.
+ m_validLayer = true;
+}
+
+void TransparencyWin::setupLayerForOpaqueCompositeLayer()
+{
+ initializeNewContext();
+ if (!m_validLayer)
+ return;
+
+ AffineTransform mapping;
+ mapping.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y());
+ if (m_transformMode == Untransform){
+ // Compute the inverse mapping from the canvas space to the
+ // coordinate space of our bitmap.
+ mapping = m_orgTransform.inverse() * mapping;
+ }
+ compositeToCopy(*m_destContext, *m_drawContext, mapping);
+
+ // Save the reference layer so we can tell what changed.
+ SkCanvas referenceCanvas(*m_referenceBitmap);
+ referenceCanvas.drawBitmap(bitmapForContext(*m_drawContext), 0, 0);
+ // Layer rect represents the part of the original layer.
+}
+
+void TransparencyWin::setupLayerForTextComposite()
+{
+ ASSERT(m_transformMode == KeepTransform);
+ // Fall through to filling with white.
+ setupLayerForWhiteLayer();
+}
+
+void TransparencyWin::setupLayerForWhiteLayer()
+{
+ initializeNewContext();
+ if (!m_validLayer)
+ return;
+
+ m_drawContext->fillRect(IntRect(IntPoint(0, 0), m_layerSize), Color::white, ColorSpaceDeviceRGB);
+ // Layer rect represents the part of the original layer.
+}
+
+void TransparencyWin::setupTransform(const IntRect& region)
+{
+ switch (m_transformMode) {
+ case KeepTransform:
+ setupTransformForKeepTransform(region);
+ break;
+ case Untransform:
+ setupTransformForUntransform();
+ break;
+ case ScaleTransform:
+ setupTransformForScaleTransform();
+ break;
+ }
+}
+
+void TransparencyWin::setupTransformForKeepTransform(const IntRect& region)
+{
+ if (!m_validLayer)
+ return;
+
+ if (m_layerMode != NoLayer) {
+ // Need to save things since we're modifying the transform.
+ m_drawContext->save();
+ m_savedOnDrawContext = true;
+
+ // Account for the fact that the layer may be offset from the
+ // original. This only happens when we create a layer that has the
+ // same coordinate space as the parent.
+ AffineTransform xform;
+ xform.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y());
+
+ // We're making a layer, so apply the old transform to the new one
+ // so it's maintained. We know the new layer has the identity
+ // transform now, we we can just multiply it.
+ xform = m_orgTransform * xform;
+ m_drawContext->concatCTM(xform);
+ }
+ m_drawRect = m_sourceRect;
+}
+
+void TransparencyWin::setupTransformForUntransform()
+{
+ ASSERT(m_layerMode != NoLayer);
+ // We now have a new layer with the identity transform, which is the
+ // Untransformed space we'll use for drawing.
+ m_drawRect = IntRect(IntPoint(0, 0), m_layerSize);
+}
+
+void TransparencyWin::setupTransformForScaleTransform()
+{
+ if (!m_validLayer)
+ return;
+
+ if (m_layerMode == NoLayer) {
+ // Need to save things since we're modifying the layer.
+ m_drawContext->save();
+ m_savedOnDrawContext = true;
+
+ // Undo the transform on the current layer when we're re-using the
+ // current one.
+ m_drawContext->concatCTM(m_drawContext->getCTM().inverse());
+
+ // We're drawing to the original layer with just a different size.
+ m_drawRect = m_transformedSourceRect;
+ } else {
+ // Just go ahead and use the layer's coordinate space to draw into.
+ // It will have the scaled size, and an identity transform loaded.
+ m_drawRect = IntRect(IntPoint(0, 0), m_layerSize);
+ }
+}
+
+void TransparencyWin::setTextCompositeColor(Color color)
+{
+ m_textCompositeColor = color;
+}
+
+void TransparencyWin::initializeNewContext()
+{
+ int pixelSize = m_layerSize.width() * m_layerSize.height();
+ if (pixelSize <= 0)
+ return;
+
+ if (pixelSize > maxCachedBufferPixelSize) {
+ // Create a 1-off buffer for drawing into. We only need the reference
+ // buffer if we're making an OpaqueCompositeLayer.
+ bool needReferenceBitmap = m_layerMode == OpaqueCompositeLayer;
+ m_ownedBuffers.set(new OwnedBuffers(m_layerSize, needReferenceBitmap));
+ m_layerBuffer = m_ownedBuffers->destBitmap();
+ if (!m_layerBuffer)
+ return;
+
+ m_drawContext = m_layerBuffer->context();
+ if (needReferenceBitmap) {
+ m_referenceBitmap = m_ownedBuffers->referenceBitmap();
+ if (!m_referenceBitmap || !m_referenceBitmap->getPixels())
+ return;
+ }
+ m_validLayer = true;
+ return;
+ }
+
+ if (m_cachedBuffers && m_cachedBuffers->canHandleSize(m_layerSize)) {
+ // We can re-use the existing buffer. We don't need to clear it since
+ // all layer modes will clear it in their initialization.
+ m_layerBuffer = m_cachedBuffers->destBitmap();
+ m_drawContext = m_cachedBuffers->destBitmap()->context();
+ bitmapForContext(*m_drawContext).eraseARGB(0, 0, 0, 0);
+ m_referenceBitmap = m_cachedBuffers->referenceBitmap();
+ m_referenceBitmap->eraseARGB(0, 0, 0, 0);
+ m_validLayer = true;
+ return;
+ }
+
+ // Create a new cached buffer.
+ if (m_cachedBuffers)
+ delete m_cachedBuffers;
+ m_cachedBuffers = new OwnedBuffers(m_layerSize, true);
+
+ m_layerBuffer = m_cachedBuffers->destBitmap();
+ m_drawContext = m_cachedBuffers->destBitmap()->context();
+ m_referenceBitmap = m_cachedBuffers->referenceBitmap();
+ m_validLayer = true;
+}
+
+void TransparencyWin::compositeOpaqueComposite()
+{
+ if (!m_validLayer)
+ return;
+
+ SkCanvas* destCanvas = canvasForContext(*m_destContext);
+ destCanvas->save();
+
+ SkBitmap* bitmap = const_cast<SkBitmap*>(
+ &bitmapForContext(*m_layerBuffer->context()));
+
+ // This function will be called for WhiteLayer as well, which we don't want
+ // to change.
+ if (m_layerMode == OpaqueCompositeLayer) {
+ // Fix up our bitmap, making it contain only the pixels which changed
+ // and transparent everywhere else.
+ SkAutoLockPixels sourceLock(*m_referenceBitmap);
+ SkAutoLockPixels lock(*bitmap);
+ for (int y = 0; y < bitmap->height(); y++) {
+ uint32_t* source = m_referenceBitmap->getAddr32(0, y);
+ uint32_t* dest = bitmap->getAddr32(0, y);
+ for (int x = 0; x < bitmap->width(); x++) {
+ // Clear out any pixels that were untouched.
+ if (dest[x] == source[x])
+ dest[x] = 0;
+ else
+ dest[x] |= (0xFF << SK_A32_SHIFT);
+ }
+ }
+ } else
+ makeLayerOpaque();
+
+ SkRect destRect;
+ if (m_transformMode != Untransform) {
+ // We want to use Untransformed space.
+ //
+ // Note that we DON'T call m_layerBuffer->image() here. This actually
+ // makes a copy of the image, which is unnecessary and slow. Instead, we
+ // just draw the image from inside the destination context.
+ SkMatrix identity;
+ identity.reset();
+ destCanvas->setMatrix(identity);
+
+ destRect.set(m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.right(), m_transformedSourceRect.bottom());
+ } else
+ destRect.set(m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.right(), m_sourceRect.bottom());
+
+ SkPaint paint;
+ paint.setFilterBitmap(true);
+ paint.setAntiAlias(true);
+
+ // Note that we need to specify the source layer subset, since the bitmap
+ // may have been cached and it could be larger than what we're using.
+ SkIRect sourceRect = { 0, 0, m_layerSize.width(), m_layerSize.height() };
+ destCanvas->drawBitmapRect(*bitmap, &sourceRect, destRect, &paint);
+ destCanvas->restore();
+}
+
+void TransparencyWin::compositeTextComposite()
+{
+ if (!m_validLayer)
+ return;
+
+ const SkBitmap& bitmap = m_layerBuffer->context()->platformContext()->canvas()->getTopPlatformDevice().accessBitmap(true);
+ SkColor textColor = m_textCompositeColor.rgb();
+ for (int y = 0; y < m_layerSize.height(); y++) {
+ uint32_t* row = bitmap.getAddr32(0, y);
+ for (int x = 0; x < m_layerSize.width(); x++) {
+ // The alpha is the average of the R, G, and B channels.
+ int alpha = (SkGetPackedR32(row[x]) + SkGetPackedG32(row[x]) + SkGetPackedB32(row[x])) / 3;
+
+ // Apply that alpha to the text color and write the result.
+ row[x] = SkAlphaMulQ(textColor, SkAlpha255To256(255 - alpha));
+ }
+ }
+
+ // Now the layer has text with the proper color and opacity.
+ SkCanvas* destCanvas = canvasForContext(*m_destContext);
+ destCanvas->save();
+
+ // We want to use Untransformed space (see above)
+ SkMatrix identity;
+ identity.reset();
+ destCanvas->setMatrix(identity);
+ SkRect destRect = { m_transformedSourceRect.x(), m_transformedSourceRect.y(), m_transformedSourceRect.right(), m_transformedSourceRect.bottom() };
+
+ // Note that we need to specify the source layer subset, since the bitmap
+ // may have been cached and it could be larger than what we're using.
+ SkIRect sourceRect = { 0, 0, m_layerSize.width(), m_layerSize.height() };
+ destCanvas->drawBitmapRect(bitmap, &sourceRect, destRect, 0);
+ destCanvas->restore();
+}
+
+void TransparencyWin::makeLayerOpaque()
+{
+ if (!m_validLayer)
+ return;
+
+ SkBitmap& bitmap = const_cast<SkBitmap&>(m_drawContext->platformContext()->
+ canvas()->getTopPlatformDevice().accessBitmap(true));
+ for (int y = 0; y < m_layerSize.height(); y++) {
+ uint32_t* row = bitmap.getAddr32(0, y);
+ for (int x = 0; x < m_layerSize.width(); x++)
+ row[x] |= 0xFF000000;
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/TransparencyWin.h b/Source/WebCore/platform/graphics/chromium/TransparencyWin.h
new file mode 100644
index 0000000..b6bef91
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/TransparencyWin.h
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TransparencyWin_h
+#define TransparencyWin_h
+
+#include <windows.h>
+
+#include "AffineTransform.h"
+#include "ImageBuffer.h"
+#include "Noncopyable.h"
+#include "wtf/OwnPtr.h"
+
+class SkBitmap;
+class SkCanvas;
+
+namespace WebCore {
+
+class GraphicsContext;
+class TransparencyWin_NoLayer_Test;
+class TransparencyWin_WhiteLayer_Test;
+class TransparencyWin_TextComposite_Test;
+class TransparencyWin_OpaqueCompositeLayer_Test;
+
+// Helper class that abstracts away drawing ClearType text and Windows form
+// controls either to the original context directly, or to an offscreen context
+// that is composited later manually. This is to get around Windows' inability
+// to handle the alpha channel, semitransparent text, and transformed form
+// controls.
+class TransparencyWin : public Noncopyable {
+public:
+ enum LayerMode {
+ // No extra layer is created. Drawing will happen to the source.
+ // Valid only with KeepTransform and ScaleTransform. The region being
+ // drawn onto must be opaque, since the modified region will be forced
+ // to opaque when drawing is complete.
+ NoLayer,
+
+ // Makes a temporary layer consisting of the composited layers below
+ // it. This result must be opaque. When complete, the result will be
+ // compared to the original, and the difference will be added to a thee
+ // destination layer.
+ //
+ // This mode only works if the lower layers are opque (normally the
+ // case for a web page) and layers are only drawn in the stack order,
+ // meaning you can never draw underneath a layer.
+ //
+ // This doesn't technically produce the correct answer in all cases. If
+ // you have an opaque base, a transparency layer, than a semitransparent
+ // drawing on top, the result will actually be blended in twice. But
+ // this isn't a very important case. This mode is used for form
+ // controls which are always opaque except for occationally some
+ // antialiasing. It means form control antialiasing will be too light in
+ // some cases, but only if you have extra layers.
+ OpaqueCompositeLayer,
+
+ // Allows semitransparent text to be drawn on any background (even if it
+ // is itself semitransparent), but disables ClearType.
+ //
+ // It makes a trmporary layer filled with white. This is composited with
+ // the lower layer with a custom color applied to produce the result.
+ // The caller must draw the text in black, and set the desired final
+ // text color by calling setTextCompositeColor().
+ //
+ // Only valid with KeepTransform, which is the only mode where drawing
+ // text in this fashion makes sense.
+ TextComposite,
+
+ // Makes a temporary layer filled with white. When complete, the layer
+ // will be forced to be opqaue (since Windows may have messed up the
+ // alpha channel) and composited down. Any areas not drawn into will
+ // remain white.
+ //
+ // This is the mode of last resort. If the opacity of the final image
+ // is unknown and we can't do the text trick (since we know its color),
+ // then we have to live with potential white halos. This is used for
+ // form control drawing, for example.
+ WhiteLayer,
+ };
+
+ enum TransformMode {
+ // There are no changes to the transform. Use this when drawing
+ // horizontal text. The current transform must not have rotation.
+ KeepTransform,
+
+ // Drawing happens in an Untransformed space, and then that bitmap is
+ // transformed according to the current context when it is copied down.
+ // Requires that a layer be created (layer mode is not NoLayer).
+ Untransform,
+
+ // When the current transform only has a scaling factor applied and
+ // you're drawing form elements, use this parameter. This will unscale
+ // the coordinate space, so the OS will just draw the form controls
+ // larger or smaller depending on the destination size.
+ ScaleTransform,
+ };
+
+ // You MUST call init() below.
+ // |region| is expressed relative to the current transformation.
+ TransparencyWin();
+ ~TransparencyWin();
+
+ // Initializes the members if you use the 0-argument constructor. Don't call
+ // this if you use the multiple-argument constructor.
+ void init(GraphicsContext* dest,
+ LayerMode layerMode,
+ TransformMode transformMode,
+ const IntRect& region);
+
+ // Combines the source and destination bitmaps using the given mode.
+ // Calling this function before the destructor runs is mandatory in most
+ // cases, and harmless otherwise. The mandatory cases are:
+ // (m_layerMode != NoLayer) || (m_transformMode == ScaleTransform)
+ void composite();
+
+ // Returns the context for drawing into, which may be the destination
+ // context, or a temporary one.
+ GraphicsContext* context() const { return m_drawContext; }
+
+ PlatformGraphicsContext* platformContext() const { return m_drawContext ? m_drawContext->platformContext() : 0; }
+
+ // When the mode is TextComposite, this sets the color that the text will
+ // get. See the enum above for more.
+ void setTextCompositeColor(Color color);
+
+ // Returns the input bounds translated into the destination space. This is
+ // not necessary for KeepTransform since the rectangle will be unchanged.
+ const IntRect& drawRect() { return m_drawRect; }
+
+private:
+ friend TransparencyWin_NoLayer_Test;
+ friend TransparencyWin_WhiteLayer_Test;
+ friend TransparencyWin_TextComposite_Test;
+ friend TransparencyWin_OpaqueCompositeLayer_Test;
+
+ class OwnedBuffers;
+
+ void computeLayerSize();
+
+ // Sets up a new layer, if any. setupLayer() will call the appopriate layer-
+ // specific helper. Must be called after computeLayerSize();
+ void setupLayer();
+ void setupLayerForNoLayer();
+ void setupLayerForOpaqueCompositeLayer();
+ void setupLayerForTextComposite();
+ void setupLayerForWhiteLayer();
+
+ // Sets up the transformation on the newly created layer. setupTransform()
+ // will call the appropriate transform-specific helper. Must be called after
+ // setupLayer().
+ void setupTransform(const IntRect& region);
+ void setupTransformForKeepTransform(const IntRect& region);
+ void setupTransformForUntransform();
+ void setupTransformForScaleTransform();
+
+ void initializeNewContext();
+
+ void compositeOpaqueComposite();
+ void compositeTextComposite();
+
+ // Fixes the alpha channel to make the region inside m_transformedRect
+ // opaque.
+ void makeLayerOpaque();
+
+ // The context our drawing will eventually end up in.
+ GraphicsContext* m_destContext;
+
+ // The original transform from the destination context.
+ AffineTransform m_orgTransform;
+
+ LayerMode m_layerMode;
+ TransformMode m_transformMode;
+
+ // The rectangle we're drawing in the destination's coordinate space
+ IntRect m_sourceRect;
+
+ // The source rectangle transformed into pixels in the final image. For
+ // Untransform this has no meaning, since the destination might not be a
+ // rectangle.
+ IntRect m_transformedSourceRect;
+
+ // The size of the layer we created. If there's no layer, this is the size
+ // of the region we're using in the source.
+ IntSize m_layerSize;
+
+ // The rectangle we're drawing to in the draw context's coordinate space.
+ // This will be the same as the source rectangle except for ScaleTransform
+ // where we create a new virtual coordinate space for the layer.
+ IntRect m_drawRect;
+
+ // Points to the graphics context to draw text to, which will either be
+ // the original context or the copy, depending on our mode.
+ GraphicsContext* m_drawContext;
+
+ // This flag is set when we call save() on the draw context during
+ // initialization. It allows us to avoid doing an extra save()/restore()
+ // when one is unnecessary.
+ bool m_savedOnDrawContext;
+
+ // Used only when m_mode = TextComposite, this is the color that the text
+ // will end up being once we figure out the transparency.
+ Color m_textCompositeColor;
+
+ // Layer we're drawing to.
+ ImageBuffer* m_layerBuffer;
+
+ // When the layer type is OpaqueCompositeLayer, this will contain a copy
+ // of the original contents of the m_layerBuffer before Windows drew on it.
+ // It allows us to re-create what Windows did to the layer. It is an
+ // SkBitmap instead of an ImageBuffer because an SkBitmap is lighter-weight
+ // (ImageBuffers are also GDI surfaces, which we don't need here).
+ SkBitmap* m_referenceBitmap;
+
+ // If the given size of bitmap can be cached, they will be stored here. Both
+ // the bitmap and the reference are guaranteed to be allocated if this
+ // member is non-null.
+ static OwnedBuffers* m_cachedBuffers;
+
+ // If a buffer was too big to be cached, it will be created temporarily, and
+ // this member tracks its scope to make sure it gets deleted. Always use
+ // m_layerBuffer, which will either point to this object, or the statically
+ // cached one. Don't access directly.
+ OwnPtr<OwnedBuffers> m_ownedBuffers;
+
+ // Sometimes we're asked to create layers that have negative dimensions.
+ // This API is not designed to fail to initialize, so we hide the fact
+ // that they are illegal and can't be rendered (failing silently, drawing
+ // nothing).
+ bool m_validLayer;
+};
+
+} // namespace WebCore
+
+#endif // TransaprencyWin_h
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
new file mode 100644
index 0000000..dda84a9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -0,0 +1,932 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "UniscribeHelper.h"
+
+#include <windows.h>
+
+#include "FontUtilsChromiumWin.h"
+#include "PlatformContextSkia.h"
+#include "SkiaFontWin.h"
+#include "SkPoint.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+// This function is used to see where word spacing should be applied inside
+// runs. Note that this must match Font::treatAsSpace so we all agree where
+// and how much space this is, so we don't want to do more general Unicode
+// "is this a word break" thing.
+static bool treatAsSpace(UChar c)
+{
+ return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0;
+}
+
+// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
+// and blank glyphs. Just because ScriptShape succeeds does not mean
+// that a text run is rendered correctly. Some characters may be rendered
+// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
+// array returned by ScriptShape contains any of those glyphs to make
+// sure that the text run is rendered successfully.
+static bool containsMissingGlyphs(WORD *glyphs,
+ int length,
+ SCRIPT_FONTPROPERTIES* properties)
+{
+ for (int i = 0; i < length; ++i) {
+ if (glyphs[i] == properties->wgDefault
+ || (glyphs[i] == properties->wgInvalid
+ && glyphs[i] != properties->wgBlank))
+ return true;
+ }
+
+ return false;
+}
+
+// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque
+// handle and we can't directly query it to make a new HFONT sharing
+// its characteristics (height, style, etc) except for family name.
+// This function uses GetObject to convert HFONT back to LOGFONT,
+// resets the fields of LOGFONT and calculates style to use later
+// for the creation of a font identical to HFONT other than family name.
+static void setLogFontAndStyle(HFONT hfont, LOGFONT *logfont, int *style)
+{
+ ASSERT(hfont && logfont);
+ if (!hfont || !logfont)
+ return;
+
+ GetObject(hfont, sizeof(LOGFONT), logfont);
+ // We reset these fields to values appropriate for CreateFontIndirect.
+ // while keeping lfHeight, which is the most important value in creating
+ // a new font similar to hfont.
+ logfont->lfWidth = 0;
+ logfont->lfEscapement = 0;
+ logfont->lfOrientation = 0;
+ logfont->lfCharSet = DEFAULT_CHARSET;
+ logfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ logfont->lfQuality = DEFAULT_QUALITY; // Honor user's desktop settings.
+ logfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ if (style)
+ *style = getStyleFromLogfont(logfont);
+}
+
+UniscribeHelper::UniscribeHelper(const UChar* input,
+ int inputLength,
+ bool isRtl,
+ HFONT hfont,
+ SCRIPT_CACHE* scriptCache,
+ SCRIPT_FONTPROPERTIES* fontProperties)
+ : m_input(input)
+ , m_inputLength(inputLength)
+ , m_isRtl(isRtl)
+ , m_hfont(hfont)
+ , m_scriptCache(scriptCache)
+ , m_fontProperties(fontProperties)
+ , m_directionalOverride(false)
+ , m_inhibitLigate(false)
+ , m_letterSpacing(0)
+ , m_spaceWidth(0)
+ , m_wordSpacing(0)
+ , m_ascent(0)
+ , m_disableFontFallback(false)
+
+{
+ m_logfont.lfFaceName[0] = 0;
+}
+
+UniscribeHelper::~UniscribeHelper()
+{
+}
+
+void UniscribeHelper::initWithOptionalLengthProtection(bool lengthProtection)
+{
+ // We cap the input length and just don't do anything. We'll allocate a lot
+ // of things of the size of the number of characters, so the allocated
+ // memory will be several times the input length. Plus shaping such a large
+ // buffer may be a form of denial of service. No legitimate text should be
+ // this long. It also appears that Uniscribe flatly rejects very long
+ // strings, so we don't lose anything by doing this.
+ //
+ // The input length protection may be disabled by the unit tests to cause
+ // an error condition.
+ static const int kMaxInputLength = 65535;
+ if (m_inputLength == 0 || (lengthProtection && m_inputLength > kMaxInputLength))
+ return;
+
+ fillRuns();
+ fillShapes();
+ fillScreenOrder();
+}
+
+int UniscribeHelper::width() const
+{
+ int width = 0;
+ for (int itemIndex = 0; itemIndex < static_cast<int>(m_runs.size()); itemIndex++)
+ width += advanceForItem(itemIndex);
+ return width;
+}
+
+void UniscribeHelper::justify(int additionalSpace)
+{
+ // Count the total number of glyphs we have so we know how big to make the
+ // buffers below.
+ int totalGlyphs = 0;
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ int runIndex = m_screenOrder[run];
+ totalGlyphs += static_cast<int>(m_shapes[runIndex].glyphLength());
+ }
+ if (totalGlyphs == 0)
+ return; // Nothing to do.
+
+ // We make one big buffer in screen order of all the glyphs we are drawing
+ // across runs so that the justification function will adjust evenly across
+ // all glyphs.
+ Vector<SCRIPT_VISATTR, 64> visualAttributes;
+ visualAttributes.resize(totalGlyphs);
+ Vector<int, 64> advances;
+ advances.resize(totalGlyphs);
+ Vector<int, 64> justify;
+ justify.resize(totalGlyphs);
+
+ // Build the packed input.
+ int destIndex = 0;
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ int runIndex = m_screenOrder[run];
+ const Shaping& shaping = m_shapes[runIndex];
+
+ for (int i = 0; i < shaping.glyphLength(); i++, destIndex++) {
+ memcpy(&visualAttributes[destIndex], &shaping.m_visualAttributes[i],
+ sizeof(SCRIPT_VISATTR));
+ advances[destIndex] = shaping.m_advance[i];
+ }
+ }
+
+ // The documentation for Scriptjustify is wrong, the parameter is the space
+ // to add and not the width of the column you want.
+ const int minKashida = 1; // How do we decide what this should be?
+ ScriptJustify(&visualAttributes[0], &advances[0], totalGlyphs,
+ additionalSpace, minKashida, &justify[0]);
+
+ // Now we have to unpack the justification amounts back into the runs so
+ // the glyph indices match.
+ int globalGlyphIndex = 0;
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ int runIndex = m_screenOrder[run];
+ Shaping& shaping = m_shapes[runIndex];
+
+ shaping.m_justify.resize(shaping.glyphLength());
+ for (int i = 0; i < shaping.glyphLength(); i++, globalGlyphIndex++)
+ shaping.m_justify[i] = justify[globalGlyphIndex];
+ }
+}
+
+int UniscribeHelper::characterToX(int offset) const
+{
+ HRESULT hr;
+ ASSERT(offset <= m_inputLength);
+
+ // Our algorithm is to traverse the items in screen order from left to
+ // right, adding in each item's screen width until we find the item with
+ // the requested character in it.
+ int width = 0;
+ for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
+ // Compute the length of this run.
+ int itemIndex = m_screenOrder[screenIndex];
+ const SCRIPT_ITEM& item = m_runs[itemIndex];
+ const Shaping& shaping = m_shapes[itemIndex];
+ int itemLength = shaping.charLength();
+
+ if (offset >= item.iCharPos && offset <= item.iCharPos + itemLength) {
+ // Character offset is in this run.
+ int charLength = offset - item.iCharPos;
+
+ int curX = 0;
+ hr = ScriptCPtoX(charLength, FALSE, itemLength,
+ shaping.glyphLength(),
+ &shaping.m_logs[0], &shaping.m_visualAttributes[0],
+ shaping.effectiveAdvances(), &item.a, &curX);
+ if (FAILED(hr))
+ return 0;
+
+ width += curX + shaping.m_prePadding;
+ ASSERT(width >= 0);
+ return width;
+ }
+
+ // Move to the next item.
+ width += advanceForItem(itemIndex);
+ }
+ ASSERT(width >= 0);
+ return width;
+}
+
+int UniscribeHelper::xToCharacter(int x) const
+{
+ // We iterate in screen order until we find the item with the given pixel
+ // position in it. When we find that guy, we ask Uniscribe for the
+ // character index.
+ HRESULT hr;
+ for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
+ int itemIndex = m_screenOrder[screenIndex];
+ int itemAdvance = advanceForItem(itemIndex);
+
+ // Note that the run may be empty if shaping failed, so we want to skip
+ // over it.
+ const Shaping& shaping = m_shapes[itemIndex];
+ int itemLength = shaping.charLength();
+ if (x <= itemAdvance && itemLength > 0) {
+ // The requested offset is within this item.
+ const SCRIPT_ITEM& item = m_runs[itemIndex];
+
+ // Account for the leading space we've added to this run that
+ // Uniscribe doesn't know about.
+ x -= shaping.m_prePadding;
+
+ int charX = 0;
+ int trailing;
+ hr = ScriptXtoCP(x, itemLength, shaping.glyphLength(),
+ &shaping.m_logs[0], &shaping.m_visualAttributes[0],
+ shaping.effectiveAdvances(), &item.a, &charX,
+ &trailing);
+
+ // The character offset is within the item. We need to add the
+ // item's offset to transform it into the space of the TextRun
+ return charX + item.iCharPos;
+ }
+
+ // The offset is beyond this item, account for its length and move on.
+ x -= itemAdvance;
+ }
+
+ // Error condition, we don't know what to do if we don't have that X
+ // position in any of our items.
+ return 0;
+}
+
+void UniscribeHelper::draw(GraphicsContext* graphicsContext,
+ HDC dc, int x, int y, int from, int to)
+{
+ HGDIOBJ oldFont = 0;
+ int curX = x;
+ bool firstRun = true;
+ bool useWindowsDrawing = windowsCanHandleTextDrawing(graphicsContext);
+
+ for (size_t screenIndex = 0; screenIndex < m_runs.size(); screenIndex++) {
+ int itemIndex = m_screenOrder[screenIndex];
+ const SCRIPT_ITEM& item = m_runs[itemIndex];
+ const Shaping& shaping = m_shapes[itemIndex];
+
+ // Character offsets within this run. THESE MAY NOT BE IN RANGE and may
+ // be negative, etc. The code below handles this.
+ int fromChar = from - item.iCharPos;
+ int toChar = to - item.iCharPos;
+
+ // See if we need to draw any characters in this item.
+ if (shaping.charLength() == 0 ||
+ fromChar >= shaping.charLength() || toChar <= 0) {
+ // No chars in this item to display.
+ curX += advanceForItem(itemIndex);
+ continue;
+ }
+
+ // Compute the starting glyph within this span. |from| and |to| are
+ // global offsets that may intersect arbitrarily with our local run.
+ int fromGlyph, afterGlyph;
+ if (item.a.fRTL) {
+ // To compute the first glyph when going RTL, we use |to|.
+ if (toChar >= shaping.charLength())
+ // The end of the text is after (to the left) of us.
+ fromGlyph = 0;
+ else {
+ // Since |to| is exclusive, the first character we draw on the
+ // left is actually the one right before (to the right) of
+ // |to|.
+ fromGlyph = shaping.m_logs[toChar - 1];
+ }
+
+ // The last glyph is actually the first character in the range.
+ if (fromChar <= 0) {
+ // The first character to draw is before (to the right) of this
+ // span, so draw all the way to the end.
+ afterGlyph = shaping.glyphLength();
+ } else {
+ // We want to draw everything up until the character to the
+ // right of |from|. To the right is - 1, so we look that up
+ // (remember our character could be more than one glyph, so we
+ // can't look up our glyph and add one).
+ afterGlyph = shaping.m_logs[fromChar - 1];
+ }
+ } else {
+ // Easy case, everybody agrees about directions. We only need to
+ // handle boundary conditions to get a range inclusive at the
+ // beginning, and exclusive at the ending. We have to do some
+ // computation to see the glyph one past the end.
+ fromGlyph = shaping.m_logs[fromChar < 0 ? 0 : fromChar];
+ if (toChar >= shaping.charLength())
+ afterGlyph = shaping.glyphLength();
+ else
+ afterGlyph = shaping.m_logs[toChar];
+ }
+
+ // Account for the characters that were skipped in this run. When
+ // WebKit asks us to draw a subset of the run, it actually tells us
+ // to draw at the X offset of the beginning of the run, since it
+ // doesn't know the internal position of any of our characters.
+ const int* effectiveAdvances = shaping.effectiveAdvances();
+ int innerOffset = 0;
+ for (int i = 0; i < fromGlyph; i++)
+ innerOffset += effectiveAdvances[i];
+
+ // Actually draw the glyphs we found.
+ int glyphCount = afterGlyph - fromGlyph;
+ if (fromGlyph >= 0 && glyphCount > 0) {
+ // Account for the preceding space we need to add to this run. We
+ // don't need to count for the following space because that will be
+ // counted in advanceForItem below when we move to the next run.
+ innerOffset += shaping.m_prePadding;
+
+ // Pass 0 in when there is no justification.
+ const int* justify = shaping.m_justify.size() == 0 ? 0 : &shaping.m_justify[fromGlyph];
+
+ if (useWindowsDrawing) {
+ if (firstRun) {
+ oldFont = SelectObject(dc, shaping.m_hfont);
+ firstRun = false;
+ } else
+ SelectObject(dc, shaping.m_hfont);
+ }
+
+ // Fonts with different ascents can be used to render different
+ // runs. 'Across-runs' y-coordinate correction needs to be
+ // adjusted for each font.
+ bool textOutOk = false;
+ for (int executions = 0; executions < 2; ++executions) {
+ if (useWindowsDrawing) {
+ HRESULT hr = ScriptTextOut(dc, shaping.m_scriptCache,
+ curX + innerOffset,
+ y - shaping.m_ascentOffset,
+ 0, 0, &item.a, 0, 0,
+ &shaping.m_glyphs[fromGlyph],
+ glyphCount,
+ &shaping.m_advance[fromGlyph],
+ justify,
+ &shaping.m_offsets[fromGlyph]);
+ textOutOk = (hr == S_OK);
+ } else {
+ SkPoint origin;
+ origin.fX = curX + + innerOffset;
+ origin.fY = y + m_ascent;
+ textOutOk = paintSkiaText(graphicsContext,
+ shaping.m_hfont,
+ glyphCount,
+ &shaping.m_glyphs[fromGlyph],
+ &shaping.m_advance[fromGlyph],
+ &shaping.m_offsets[fromGlyph],
+ &origin);
+ }
+
+ if (!textOutOk && 0 == executions) {
+ // If TextOut is called from the renderer it might fail
+ // because the sandbox is preventing it from opening the
+ // font files. If we are running in the renderer,
+ // TryToPreloadFont is overridden to ask the browser to
+ // preload the font for us so we can access it.
+ tryToPreloadFont(shaping.m_hfont);
+ continue;
+ }
+ break;
+ }
+ }
+
+ curX += advanceForItem(itemIndex);
+ }
+
+ if (oldFont)
+ SelectObject(dc, oldFont);
+}
+
+WORD UniscribeHelper::firstGlyphForCharacter(int charOffset) const
+{
+ // Find the run for the given character.
+ for (int i = 0; i < static_cast<int>(m_runs.size()); i++) {
+ int firstChar = m_runs[i].iCharPos;
+ const Shaping& shaping = m_shapes[i];
+ int localOffset = charOffset - firstChar;
+ if (localOffset >= 0 && localOffset < shaping.charLength()) {
+ // The character is in this run, return the first glyph for it
+ // (should generally be the only glyph). It seems Uniscribe gives
+ // glyph 0 for empty, which is what we want to return in the
+ // "missing" case.
+ size_t glyphIndex = shaping.m_logs[localOffset];
+ if (glyphIndex >= shaping.m_glyphs.size()) {
+ // The glyph should be in this run, but the run has too few
+ // actual characters. This can happen when shaping the run
+ // fails, in which case, we should have no data in the logs at
+ // all.
+ ASSERT(shaping.m_glyphs.size() == 0);
+ return 0;
+ }
+ return shaping.m_glyphs[glyphIndex];
+ }
+ }
+
+ return 0;
+}
+
+void UniscribeHelper::fillRuns()
+{
+ HRESULT hr;
+ m_runs.resize(UNISCRIBE_HELPER_STACK_RUNS);
+
+ SCRIPT_STATE inputState;
+ inputState.uBidiLevel = m_isRtl;
+ inputState.fOverrideDirection = m_directionalOverride;
+ inputState.fInhibitSymSwap = false;
+ inputState.fCharShape = false; // Not implemented in Uniscribe
+ inputState.fDigitSubstitute = false; // Do we want this for Arabic?
+ inputState.fInhibitLigate = m_inhibitLigate;
+ inputState.fDisplayZWG = false; // Don't draw control characters.
+ inputState.fArabicNumContext = m_isRtl; // Do we want this for Arabic?
+ inputState.fGcpClusters = false;
+ inputState.fReserved = 0;
+ inputState.fEngineReserved = 0;
+ // The psControl argument to ScriptItemize should be non-0 for RTL text,
+ // per http://msdn.microsoft.com/en-us/library/ms776532.aspx . So use a
+ // SCRIPT_CONTROL that is set to all zeros. Zero as a locale ID means the
+ // neutral locale per http://msdn.microsoft.com/en-us/library/ms776294.aspx
+ static SCRIPT_CONTROL inputControl = {0, // uDefaultLanguage :16;
+ 0, // fContextDigits :1;
+ 0, // fInvertPreBoundDir :1;
+ 0, // fInvertPostBoundDir :1;
+ 0, // fLinkStringBefore :1;
+ 0, // fLinkStringAfter :1;
+ 0, // fNeutralOverride :1;
+ 0, // fNumericOverride :1;
+ 0, // fLegacyBidiClass :1;
+ 0, // fMergeNeutralItems :1;
+ 0};// fReserved :7;
+ // Calling ScriptApplyDigitSubstitution( 0, &inputControl, &inputState)
+ // here would be appropriate if we wanted to set the language ID, and get
+ // local digit substitution behavior. For now, don't do it.
+
+ while (true) {
+ int numberOfItems = 0;
+
+ // Ideally, we would have a way to know the runs before and after this
+ // one, and put them into the control parameter of ScriptItemize. This
+ // would allow us to shape characters properly that cross style
+ // boundaries (WebKit bug 6148).
+ //
+ // We tell ScriptItemize that the output list of items is one smaller
+ // than it actually is. According to Mozilla bug 366643, if there is
+ // not enough room in the array on pre-SP2 systems, ScriptItemize will
+ // write one past the end of the buffer.
+ //
+ // ScriptItemize is very strange. It will often require a much larger
+ // ITEM buffer internally than it will give us as output. For example,
+ // it will say a 16-item buffer is not big enough, and will write
+ // interesting numbers into all those items. But when we give it a 32
+ // item buffer and it succeeds, it only has one item output.
+ //
+ // It seems to be doing at least two passes, the first where it puts a
+ // lot of intermediate data into our items, and the second where it
+ // collates them.
+ hr = ScriptItemize(m_input, m_inputLength,
+ static_cast<int>(m_runs.size()) - 1, &inputControl,
+ &inputState,
+ &m_runs[0], &numberOfItems);
+ if (SUCCEEDED(hr)) {
+ m_runs.resize(numberOfItems);
+ break;
+ }
+ if (hr != E_OUTOFMEMORY) {
+ // Some kind of unexpected error.
+ m_runs.resize(0);
+ break;
+ }
+ // There was not enough items for it to write into, expand.
+ m_runs.resize(m_runs.size() * 2);
+ }
+}
+
+bool UniscribeHelper::shape(const UChar* input,
+ int itemLength,
+ int numGlyphs,
+ SCRIPT_ITEM& run,
+ Shaping& shaping)
+{
+ HFONT hfont = m_hfont;
+ SCRIPT_CACHE* scriptCache = m_scriptCache;
+ SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;
+ int ascent = m_ascent;
+ HDC tempDC = 0;
+ HGDIOBJ oldFont = 0;
+ HRESULT hr;
+ // When used to fill up glyph pages for simple scripts in non-BMP,
+ // we don't want any font fallback in this class. The simple script
+ // font path can take care of font fallback.
+ bool lastFallbackTried = m_disableFontFallback;
+ bool result;
+
+ int generatedGlyphs = 0;
+
+ // In case HFONT passed in ctor cannot render this run, we have to scan
+ // other fonts from the beginning of the font list.
+ resetFontIndex();
+
+ // Compute shapes.
+ while (true) {
+ shaping.m_logs.resize(itemLength);
+ shaping.m_glyphs.resize(numGlyphs);
+ shaping.m_visualAttributes.resize(numGlyphs);
+
+#ifdef PURIFY
+ // http://code.google.com/p/chromium/issues/detail?id=5309
+ // Purify isn't able to track the assignments that ScriptShape makes to
+ // shaping.m_glyphs. Consequently, any bytes with value 0xCD that it
+ // writes, will be considered un-initialized data.
+ //
+ // This hack avoid the false-positive UMRs by marking the buffer as
+ // initialized.
+ //
+ // FIXME: A better solution would be to use Purify's API and mark only
+ // the populated range as initialized:
+ //
+ // PurifyMarkAsInitialized(
+ // &shaping.m_glyphs[0],
+ // sizeof(shaping.m_glyphs[0] * generatedGlyphs);
+
+ ZeroMemory(&shaping.m_glyphs[0],
+ sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size());
+#endif
+
+ // Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true
+ // here. Is that what we want? It will display control characters.
+ hr = ScriptShape(tempDC, scriptCache, input, itemLength,
+ numGlyphs, &run.a,
+ &shaping.m_glyphs[0], &shaping.m_logs[0],
+ &shaping.m_visualAttributes[0], &generatedGlyphs);
+ if (hr == E_PENDING) {
+ // Allocate the DC.
+ tempDC = GetDC(0);
+ oldFont = SelectObject(tempDC, hfont);
+ continue;
+ } else if (hr == E_OUTOFMEMORY) {
+ numGlyphs *= 2;
+ continue;
+ } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(&shaping.m_glyphs[0], generatedGlyphs, fontProperties)))
+ break;
+
+ // The current font can't render this run. clear DC and try
+ // next font.
+ if (tempDC) {
+ SelectObject(tempDC, oldFont);
+ ReleaseDC(0, tempDC);
+ tempDC = 0;
+ }
+
+ if (!m_disableFontFallback &&
+ nextWinFontData(&hfont, &scriptCache, &fontProperties, &ascent)) {
+ // The primary font does not support this run. Try next font.
+ // In case of web page rendering, they come from fonts specified in
+ // CSS stylesheets.
+ continue;
+ } else if (!lastFallbackTried) {
+ lastFallbackTried = true;
+
+ // Generate a last fallback font based on the script of
+ // a character to draw while inheriting size and styles
+ // from the primary font
+ if (!m_logfont.lfFaceName[0])
+ setLogFontAndStyle(m_hfont, &m_logfont, &m_style);
+
+ // TODO(jungshik): generic type should come from webkit for
+ // UniscribeHelperTextRun (a derived class used in webkit).
+ const UChar *family = getFallbackFamily(input, itemLength,
+ FontDescription::StandardFamily, 0, 0);
+ bool fontOk = getDerivedFontData(family, m_style, &m_logfont,
+ &ascent, &hfont, &scriptCache);
+
+ if (!fontOk) {
+ // If this GetDerivedFontData is called from the renderer it
+ // might fail because the sandbox is preventing it from opening
+ // the font files. If we are running in the renderer,
+ // TryToPreloadFont is overridden to ask the browser to preload
+ // the font for us so we can access it.
+ tryToPreloadFont(hfont);
+
+ // Try again.
+ fontOk = getDerivedFontData(family, m_style, &m_logfont,
+ &ascent, &hfont, &scriptCache);
+ ASSERT(fontOk);
+ }
+
+ // TODO(jungshik) : Currently GetDerivedHFont always returns a
+ // a valid HFONT, but in the future, I may change it to return 0.
+ ASSERT(hfont);
+
+ // We don't need a font_properties for the last resort fallback font
+ // because we don't have anything more to try and are forced to
+ // accept empty glyph boxes. If we tried a series of fonts as
+ // 'last-resort fallback', we'd need it, but currently, we don't.
+ continue;
+ } else if (hr == USP_E_SCRIPT_NOT_IN_FONT) {
+ run.a.eScript = SCRIPT_UNDEFINED;
+ continue;
+ } else if (FAILED(hr)) {
+ // Error shaping.
+ generatedGlyphs = 0;
+ result = false;
+ goto cleanup;
+ }
+ }
+
+ // Sets Windows font data for this run to those corresponding to
+ // a font supporting this run. we don't need to store font_properties
+ // because it's not used elsewhere.
+ shaping.m_hfont = hfont;
+ shaping.m_scriptCache = scriptCache;
+
+ // The ascent of a font for this run can be different from
+ // that of the primary font so that we need to keep track of
+ // the difference per run and take that into account when calling
+ // ScriptTextOut in |draw|. Otherwise, different runs rendered by
+ // different fonts would not be aligned vertically.
+ shaping.m_ascentOffset = m_ascent ? ascent - m_ascent : 0;
+ result = true;
+
+ cleanup:
+ shaping.m_glyphs.resize(generatedGlyphs);
+ shaping.m_visualAttributes.resize(generatedGlyphs);
+ shaping.m_advance.resize(generatedGlyphs);
+ shaping.m_offsets.resize(generatedGlyphs);
+ if (tempDC) {
+ SelectObject(tempDC, oldFont);
+ ReleaseDC(0, tempDC);
+ }
+ // On failure, our logs don't mean anything, so zero those out.
+ if (!result)
+ shaping.m_logs.clear();
+
+ return result;
+}
+
+void UniscribeHelper::fillShapes()
+{
+ m_shapes.resize(m_runs.size());
+ for (size_t i = 0; i < m_runs.size(); i++) {
+ int startItem = m_runs[i].iCharPos;
+ int itemLength = m_inputLength - startItem;
+ if (i < m_runs.size() - 1)
+ itemLength = m_runs[i + 1].iCharPos - startItem;
+
+ int numGlyphs;
+ if (itemLength < UNISCRIBE_HELPER_STACK_CHARS) {
+ // We'll start our buffer sizes with the current stack space
+ // available in our buffers if the current input fits. As long as
+ // it doesn't expand past that we'll save a lot of time mallocing.
+ numGlyphs = UNISCRIBE_HELPER_STACK_CHARS;
+ } else {
+ // When the input doesn't fit, give up with the stack since it will
+ // almost surely not be enough room (unless the input actually
+ // shrinks, which is unlikely) and just start with the length
+ // recommended by the Uniscribe documentation as a "usually fits"
+ // size.
+ numGlyphs = itemLength * 3 / 2 + 16;
+ }
+
+ // Convert a string to a glyph string trying the primary font, fonts in
+ // the fallback list and then script-specific last resort font.
+ Shaping& shaping = m_shapes[i];
+ if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], shaping))
+ continue;
+
+ // At the moment, the only time m_disableFontFallback is set is
+ // when we look up glyph indices for non-BMP code ranges. So,
+ // we can skip the glyph placement. When that becomes not the case
+ // any more, we have to add a new flag to control glyph placement.
+ if (m_disableFontFallback)
+ continue;
+
+ // Compute placements. Note that offsets is documented incorrectly
+ // and is actually an array.
+
+ // DC that we lazily create if Uniscribe commands us to.
+ // (this does not happen often because scriptCache is already
+ // updated when calling ScriptShape).
+ HDC tempDC = 0;
+ HGDIOBJ oldFont = 0;
+ HRESULT hr;
+ while (true) {
+ shaping.m_prePadding = 0;
+ hr = ScriptPlace(tempDC, shaping.m_scriptCache,
+ &shaping.m_glyphs[0],
+ static_cast<int>(shaping.m_glyphs.size()),
+ &shaping.m_visualAttributes[0], &m_runs[i].a,
+ &shaping.m_advance[0], &shaping.m_offsets[0],
+ &shaping.m_abc);
+ if (hr != E_PENDING)
+ break;
+
+ // Allocate the DC and run the loop again.
+ tempDC = GetDC(0);
+ oldFont = SelectObject(tempDC, shaping.m_hfont);
+ }
+
+ if (FAILED(hr)) {
+ // Some error we don't know how to handle. Nuke all of our data
+ // since we can't deal with partially valid data later.
+ m_runs.clear();
+ m_shapes.clear();
+ m_screenOrder.clear();
+ }
+
+ if (tempDC) {
+ SelectObject(tempDC, oldFont);
+ ReleaseDC(0, tempDC);
+ }
+ }
+
+ adjustSpaceAdvances();
+
+ if (m_letterSpacing != 0 || m_wordSpacing != 0)
+ applySpacing();
+}
+
+void UniscribeHelper::fillScreenOrder()
+{
+ m_screenOrder.resize(m_runs.size());
+
+ // We assume that the input has only one text direction in it.
+ // TODO(brettw) are we sure we want to keep this restriction?
+ if (m_isRtl) {
+ for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)
+ m_screenOrder[static_cast<int>(m_screenOrder.size()) - i - 1] = i;
+ } else {
+ for (int i = 0; i < static_cast<int>(m_screenOrder.size()); i++)
+ m_screenOrder[i] = i;
+ }
+}
+
+void UniscribeHelper::adjustSpaceAdvances()
+{
+ if (m_spaceWidth == 0)
+ return;
+
+ int spaceWidthWithoutLetterSpacing = m_spaceWidth - m_letterSpacing;
+
+ // This mostly matches what WebKit's UniscribeController::shapeAndPlaceItem.
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ Shaping& shaping = m_shapes[run];
+
+ for (int i = 0; i < shaping.charLength(); i++) {
+ if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ continue;
+
+ int glyphIndex = shaping.m_logs[i];
+ int currentAdvance = shaping.m_advance[glyphIndex];
+
+ // currentAdvance does not include additional letter-spacing, but
+ // space_width does. Here we find out how off we are from the
+ // correct width for the space not including letter-spacing, then
+ // just subtract that diff.
+ int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
+ // The shaping can consist of a run of text, so only subtract the
+ // difference in the width of the glyph.
+ shaping.m_advance[glyphIndex] -= diff;
+ shaping.m_abc.abcB -= diff;
+ }
+ }
+}
+
+void UniscribeHelper::applySpacing()
+{
+ for (size_t run = 0; run < m_runs.size(); run++) {
+ Shaping& shaping = m_shapes[run];
+ bool isRtl = m_runs[run].a.fRTL;
+
+ if (m_letterSpacing != 0) {
+ // RTL text gets padded to the left of each character. We increment
+ // the run's advance to make this happen. This will be balanced out
+ // by NOT adding additional advance to the last glyph in the run.
+ if (isRtl)
+ shaping.m_prePadding += m_letterSpacing;
+
+ // Go through all the glyphs in this run and increase the "advance"
+ // to account for letter spacing. We adjust letter spacing only on
+ // cluster boundaries.
+ //
+ // This works for most scripts, but may have problems with some
+ // indic scripts. This behavior is better than Firefox or IE for
+ // Hebrew.
+ for (int i = 0; i < shaping.glyphLength(); i++) {
+ if (shaping.m_visualAttributes[i].fClusterStart) {
+ // Ick, we need to assign the extra space so that the glyph
+ // comes first, then is followed by the space. This is
+ // opposite for RTL.
+ if (isRtl) {
+ if (i != shaping.glyphLength() - 1) {
+ // All but the last character just get the spacing
+ // applied to their advance. The last character
+ // doesn't get anything,
+ shaping.m_advance[i] += m_letterSpacing;
+ shaping.m_abc.abcB += m_letterSpacing;
+ }
+ } else {
+ // LTR case is easier, we just add to the advance.
+ shaping.m_advance[i] += m_letterSpacing;
+ shaping.m_abc.abcB += m_letterSpacing;
+ }
+ }
+ }
+ }
+
+ // Go through all the characters to find whitespace and insert the
+ // extra wordspacing amount for the glyphs they correspond to.
+ if (m_wordSpacing != 0) {
+ for (int i = 0; i < shaping.charLength(); i++) {
+ if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ continue;
+
+ // The char in question is a word separator...
+ int glyphIndex = shaping.m_logs[i];
+
+ // Spaces will not have a glyph in Uniscribe, it will just add
+ // additional advance to the character to the left of the
+ // space. The space's corresponding glyph will be the character
+ // following it in reading order.
+ if (isRtl) {
+ // In RTL, the glyph to the left of the space is the same
+ // as the first glyph of the following character, so we can
+ // just increment it.
+ shaping.m_advance[glyphIndex] += m_wordSpacing;
+ shaping.m_abc.abcB += m_wordSpacing;
+ } else {
+ // LTR is actually more complex here, we apply it to the
+ // previous character if there is one, otherwise we have to
+ // apply it to the leading space of the run.
+ if (glyphIndex == 0)
+ shaping.m_prePadding += m_wordSpacing;
+ else {
+ shaping.m_advance[glyphIndex - 1] += m_wordSpacing;
+ shaping.m_abc.abcB += m_wordSpacing;
+ }
+ }
+ }
+ } // m_wordSpacing != 0
+
+ // Loop for next run...
+ }
+}
+
+// The advance is the ABC width of the run
+int UniscribeHelper::advanceForItem(int itemIndex) const
+{
+ int accum = 0;
+ const Shaping& shaping = m_shapes[itemIndex];
+
+ if (shaping.m_justify.size() == 0) {
+ // Easy case with no justification, the width is just the ABC width of
+ // the run. (The ABC width is the sum of the advances).
+ return shaping.m_abc.abcA + shaping.m_abc.abcB +
+ shaping.m_abc.abcC + shaping.m_prePadding;
+ }
+
+ // With justification, we use the justified amounts instead. The
+ // justification array contains both the advance and the extra space
+ // added for justification, so is the width we want.
+ int justification = 0;
+ for (size_t i = 0; i < shaping.m_justify.size(); i++)
+ justification += shaping.m_justify[i];
+
+ return shaping.m_prePadding + justification;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h
new file mode 100644
index 0000000..ffd57db
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.h
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// A wrapper around Uniscribe that provides a reasonable API.
+
+#ifndef UniscribeHelper_h
+#define UniscribeHelper_h
+
+#include <windows.h>
+#include <usp10.h>
+#include <map>
+
+#include <unicode/uchar.h>
+#include <wtf/Vector.h>
+
+class UniscribeTest_TooBig_Test; // A gunit test for UniscribeHelper.
+
+namespace WebCore {
+
+class GraphicsContext;
+
+#define UNISCRIBE_HELPER_STACK_RUNS 8
+#define UNISCRIBE_HELPER_STACK_CHARS 32
+
+// This object should be safe to create & destroy frequently, as long as the
+// caller preserves the script_cache when possible (this data may be slow to
+// compute).
+//
+// This object is "kind of large" (~1K) because it reserves a lot of space for
+// working with to avoid expensive heap operations. Therefore, not only should
+// you not worry about creating and destroying it, you should try to not keep
+// them around.
+class UniscribeHelper {
+public:
+ // Initializes this Uniscribe run with the text pointed to by |run| with
+ // |length|. The input is NOT null terminated.
+ //
+ // The is_rtl flag should be set if the input script is RTL. It is assumed
+ // that the caller has already divided up the input text (using ICU, for
+ // example) into runs of the same direction of script. This avoids
+ // disagreements between the caller and Uniscribe later (see FillItems).
+ //
+ // A script cache should be provided by the caller that is initialized to
+ // NULL. When the caller is done with the cache (it may be stored between
+ // runs as long as it is used consistently with the same HFONT), it should
+ // call ScriptFreeCache().
+ UniscribeHelper(const UChar* input,
+ int inputLength,
+ bool isRtl,
+ HFONT,
+ SCRIPT_CACHE*,
+ SCRIPT_FONTPROPERTIES*);
+
+ virtual ~UniscribeHelper();
+
+ // Sets Uniscribe's directional override flag. False by default.
+ bool directionalOverride() const
+ {
+ return m_directionalOverride;
+ }
+ void setDirectionalOverride(bool override)
+ {
+ m_directionalOverride = override;
+ }
+
+ // Set's Uniscribe's no-ligate override flag. False by default.
+ bool inhibitLigate() const
+ {
+ return m_inhibitLigate;
+ }
+ void setInhibitLigate(bool inhibit)
+ {
+ m_inhibitLigate = inhibit;
+ }
+
+ // Set letter spacing. We will try to insert this much space between
+ // graphemes (one or more glyphs perceived as a single unit by ordinary
+ // users of a script). Positive values increase letter spacing, negative
+ // values decrease it. 0 by default.
+ int letterSpacing() const
+ {
+ return m_letterSpacing;
+ }
+ void setLetterSpacing(int letterSpacing)
+ {
+ m_letterSpacing = letterSpacing;
+ }
+
+ // Set the width of a standard space character. We use this to normalize
+ // space widths. Windows will make spaces after Hindi characters larger than
+ // other spaces. A space_width of 0 means to use the default space width.
+ //
+ // Must be set before Init() is called.
+ int spaceWidth() const
+ {
+ return m_spaceWidth;
+ }
+ void setSpaceWidth(int spaceWidth)
+ {
+ m_spaceWidth = spaceWidth;
+ }
+
+ // Set word spacing. We will try to insert this much extra space between
+ // each word in the input (beyond whatever whitespace character separates
+ // words). Positive values lead to increased letter spacing, negative values
+ // decrease it. 0 by default.
+ //
+ // Must be set before Init() is called.
+ int wordSpacing() const
+ {
+ return m_wordSpacing;
+ }
+ void setWordSpacing(int wordSpacing)
+ {
+ m_wordSpacing = wordSpacing;
+ }
+
+ void setAscent(int ascent)
+ {
+ m_ascent = ascent;
+ }
+
+ // When set to true, this class is used only to look up glyph
+ // indices for a range of Unicode characters without glyph placement.
+ // By default, it's false. This should be set to true when this
+ // class is used for glyph index look-up for non-BMP characters
+ // in GlyphPageNodeChromiumWin.cpp.
+ void setDisableFontFallback(bool disableFontFallback)
+ {
+ m_disableFontFallback = true;
+ }
+
+ // You must call this after setting any options but before doing any
+ // other calls like asking for widths or drawing.
+ void init()
+ {
+ initWithOptionalLengthProtection(true);
+ }
+
+ // Returns the total width in pixels of the text run.
+ int width() const;
+
+ // Call to justify the text, with the amount of space that should be ADDED
+ // to get the desired width that the column should be justified to.
+ // Normally, spaces are inserted, but for Arabic there will be kashidas
+ // (extra strokes) inserted instead.
+ //
+ // This function MUST be called AFTER Init().
+ void justify(int additionalSpace);
+
+ // Computes the given character offset into a pixel offset of the beginning
+ // of that character.
+ int characterToX(int offset) const;
+
+ // Converts the given pixel X position into a logical character offset into
+ // the run. For positions appearing before the first character, this will
+ // return -1.
+ int xToCharacter(int x) const;
+
+ // Draws the given characters to (x, y) in the given DC. The font will be
+ // handled by this function, but the font color and other attributes should
+ // be pre-set.
+ //
+ // The y position is the upper left corner, NOT the baseline.
+ void draw(GraphicsContext* graphicsContext, HDC dc, int x, int y, int from,
+ int to);
+
+ // Returns the first glyph assigned to the character at the given offset.
+ // This function is used to retrieve glyph information when Uniscribe is
+ // being used to generate glyphs for non-complex, non-BMP (above U+FFFF)
+ // characters. These characters are not otherwise special and have no
+ // complex shaping rules, so we don't otherwise need Uniscribe, except
+ // Uniscribe is the only way to get glyphs for non-BMP characters.
+ //
+ // Returns 0 if there is no glyph for the given character.
+ WORD firstGlyphForCharacter(int charOffset) const;
+
+protected:
+ // Backend for init. The flag allows the unit test to specify whether we
+ // should fail early for very long strings like normal, or try to pass the
+ // long string to Uniscribe. The latter provides a way to force failure of
+ // shaping.
+ void initWithOptionalLengthProtection(bool lengthProtection);
+
+ // Tries to preload the font when the it is not accessible.
+ // This is the default implementation and it does not do anything.
+ virtual void tryToPreloadFont(HFONT) {}
+
+private:
+ friend class UniscribeTest_TooBig_Test;
+
+ // An array corresponding to each item in runs_ containing information
+ // on each of the glyphs that were generated. Like runs_, this is in
+ // reading order. However, for rtl text, the characters within each
+ // item will be reversed.
+ struct Shaping {
+ Shaping()
+ : m_prePadding(0)
+ , m_hfont(NULL)
+ , m_scriptCache(NULL)
+ , m_ascentOffset(0) {
+ m_abc.abcA = 0;
+ m_abc.abcB = 0;
+ m_abc.abcC = 0;
+ }
+
+ // Returns the number of glyphs (which will be drawn to the screen)
+ // in this run.
+ int glyphLength() const
+ {
+ return static_cast<int>(m_glyphs.size());
+ }
+
+ // Returns the number of characters (that we started with) in this run.
+ int charLength() const
+ {
+ return static_cast<int>(m_logs.size());
+ }
+
+ // Returns the advance array that should be used when measuring glyphs.
+ // The returned pointer will indicate an array with glyph_length()
+ // elements and the advance that should be used for each one. This is
+ // either the real advance, or the justified advances if there is one,
+ // and is the array we want to use for measurement.
+ const int* effectiveAdvances() const
+ {
+ if (m_advance.size() == 0)
+ return 0;
+ if (m_justify.size() == 0)
+ return &m_advance[0];
+ return &m_justify[0];
+ }
+
+ // This is the advance amount of space that we have added to the
+ // beginning of the run. It is like the ABC's |A| advance but one that
+ // we create and must handle internally whenever computing with pixel
+ // offsets.
+ int m_prePadding;
+
+ // Glyph indices in the font used to display this item. These indices
+ // are in screen order.
+ Vector<WORD, UNISCRIBE_HELPER_STACK_CHARS> m_glyphs;
+
+ // For each input character, this tells us the first glyph index it
+ // generated. This is the only array with size of the input chars.
+ //
+ // All offsets are from the beginning of this run. Multiple characters
+ // can generate one glyph, in which case there will be adjacent
+ // duplicates in this list. One character can also generate multiple
+ // glyphs, in which case there will be skipped indices in this list.
+ Vector<WORD, UNISCRIBE_HELPER_STACK_CHARS> m_logs;
+
+ // Flags and such for each glyph.
+ Vector<SCRIPT_VISATTR, UNISCRIBE_HELPER_STACK_CHARS> m_visualAttributes;
+
+ // Horizontal advances for each glyph listed above, this is basically
+ // how wide each glyph is.
+ Vector<int, UNISCRIBE_HELPER_STACK_CHARS> m_advance;
+
+ // This contains glyph offsets, from the nominal position of a glyph.
+ // It is used to adjust the positions of multiple combining characters
+ // around/above/below base characters in a context-sensitive manner so
+ // that they don't bump against each other and the base character.
+ Vector<GOFFSET, UNISCRIBE_HELPER_STACK_CHARS> m_offsets;
+
+ // Filled by a call to Justify, this is empty for nonjustified text.
+ // If nonempty, this contains the array of justify characters for each
+ // character as returned by ScriptJustify.
+ //
+ // This is the same as the advance array, but with extra space added
+ // for some characters. The difference between a glyph's |justify|
+ // width and it's |advance| width is the extra space added.
+ Vector<int, UNISCRIBE_HELPER_STACK_CHARS> m_justify;
+
+ // Sizing information for this run. This treats the entire run as a
+ // character with a preceeding advance, width, and ending advance. The
+ // B width is the sum of the |advance| array, and the A and C widths
+ // are any extra spacing applied to each end.
+ //
+ // It is unclear from the documentation what this actually means. From
+ // experimentation, it seems that the sum of the character advances is
+ // always the sum of the ABC values, and I'm not sure what you're
+ // supposed to do with the ABC values.
+ ABC m_abc;
+
+ // Pointers to windows font data used to render this run.
+ HFONT m_hfont;
+ SCRIPT_CACHE* m_scriptCache;
+
+ // Ascent offset between the ascent of the primary font
+ // and that of the fallback font. The offset needs to be applied,
+ // when drawing a string, to align multiple runs rendered with
+ // different fonts.
+ int m_ascentOffset;
+ };
+
+ // Computes the runs_ array from the text run.
+ void fillRuns();
+
+ // Computes the shapes_ array given an runs_ array already filled in.
+ void fillShapes();
+
+ // Fills in the screen_order_ array (see below).
+ void fillScreenOrder();
+
+ // Called to update the glyph positions based on the current spacing
+ // options that are set.
+ void applySpacing();
+
+ // Normalizes all advances for spaces to the same width. This keeps windows
+ // from making spaces after Hindi characters larger, which is then
+ // inconsistent with our meaure of the width since WebKit doesn't include
+ // spaces in text-runs sent to uniscribe unless white-space:pre.
+ void adjustSpaceAdvances();
+
+ // Returns the total width of a single item.
+ int advanceForItem(int) const;
+
+ // Shapes a run (pointed to by |input|) using |hfont| first.
+ // Tries a series of fonts specified retrieved with NextWinFontData
+ // and finally a font covering characters in |*input|. A string pointed
+ // by |input| comes from ScriptItemize and is supposed to contain
+ // characters belonging to a single script aside from characters common to
+ // all scripts (e.g. space).
+ bool shape(const UChar* input, int itemLength, int numGlyphs, SCRIPT_ITEM& run, Shaping&);
+
+ // Gets Windows font data for the next best font to try in the list
+ // of fonts. When there's no more font available, returns false
+ // without touching any of out params. Need to call ResetFontIndex
+ // to start scanning of the font list from the beginning.
+ virtual bool nextWinFontData(HFONT*, SCRIPT_CACHE**, SCRIPT_FONTPROPERTIES**, int* ascent)
+ {
+ return false;
+ }
+
+ // Resets the font index to the first in the list of fonts to try after the
+ // primaryFont turns out not to work. With fontIndex reset,
+ // NextWinFontData scans fallback fonts from the beginning.
+ virtual void resetFontIndex() {}
+
+ // The input data for this run of Uniscribe. See the constructor.
+ const UChar* m_input;
+ const int m_inputLength;
+ const bool m_isRtl;
+
+ // Windows font data for the primary font. In a sense, m_logfont and m_style
+ // are redundant because m_hfont contains all the information. However,
+ // invoking GetObject, everytime we need the height and the style, is rather
+ // expensive so that we cache them. Would it be better to add getter and
+ // (virtual) setter for the height and the style of the primary font,
+ // instead of m_logfont? Then, a derived class ctor can set m_ascent,
+ // m_height and m_style if they're known. Getters for them would have to
+ // 'infer' their values from m_hfont ONLY when they're not set.
+ HFONT m_hfont;
+ SCRIPT_CACHE* m_scriptCache;
+ SCRIPT_FONTPROPERTIES* m_fontProperties;
+ int m_ascent;
+ LOGFONT m_logfont;
+ int m_style;
+
+ // Options, see the getters/setters above.
+ bool m_directionalOverride;
+ bool m_inhibitLigate;
+ int m_letterSpacing;
+ int m_spaceWidth;
+ int m_wordSpacing;
+ bool m_disableFontFallback;
+
+ // Uniscribe breaks the text into Runs. These are one length of text that is
+ // in one script and one direction. This array is in reading order.
+ Vector<SCRIPT_ITEM, UNISCRIBE_HELPER_STACK_RUNS> m_runs;
+
+ Vector<Shaping, UNISCRIBE_HELPER_STACK_RUNS> m_shapes;
+
+ // This is a mapping between reading order and screen order for the items.
+ // Uniscribe's items array are in reading order. For right-to-left text,
+ // or mixed (although WebKit's |TextRun| should really be only one
+ // direction), this makes it very difficult to compute character offsets
+ // and positions. This list is in screen order from left to right, and
+ // gives the index into the |m_runs| and |m_shapes| arrays of each
+ // subsequent item.
+ Vector<int, UNISCRIBE_HELPER_STACK_RUNS> m_screenOrder;
+};
+
+} // namespace WebCore
+
+#endif // UniscribeHelper_h
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
new file mode 100644
index 0000000..f801c13
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "UniscribeHelperTextRun.h"
+
+#include "ChromiumBridge.h"
+#include "Font.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
+ const Font& font)
+ : UniscribeHelper(run.characters(), run.length(), run.rtl(),
+ font.primaryFont()->platformData().hfont(),
+ font.primaryFont()->platformData().scriptCache(),
+ font.primaryFont()->platformData().scriptFontProperties())
+ , m_font(&font)
+ , m_fontIndex(0)
+{
+ setDirectionalOverride(run.directionalOverride());
+ setLetterSpacing(font.letterSpacing());
+ setSpaceWidth(font.spaceWidth());
+ setWordSpacing(font.wordSpacing());
+ setAscent(font.primaryFont()->ascent());
+
+ init();
+
+ // Padding is the amount to add to make justification happen. This
+ // should be done after Init() so all the runs are already measured.
+ if (run.padding() > 0)
+ justify(run.padding());
+}
+
+UniscribeHelperTextRun::UniscribeHelperTextRun(
+ const wchar_t* input,
+ int inputLength,
+ bool isRtl,
+ HFONT hfont,
+ SCRIPT_CACHE* scriptCache,
+ SCRIPT_FONTPROPERTIES* fontProperties)
+ : UniscribeHelper(input, inputLength, isRtl, hfont,
+ scriptCache, fontProperties)
+ , m_font(0)
+ , m_fontIndex(-1)
+{
+}
+
+void UniscribeHelperTextRun::tryToPreloadFont(HFONT font)
+{
+ // Ask the browser to get the font metrics for this font.
+ // That will preload the font and it should now be accessible
+ // from the renderer.
+ ChromiumBridge::ensureFontLoaded(font);
+}
+
+bool UniscribeHelperTextRun::nextWinFontData(
+ HFONT* hfont,
+ SCRIPT_CACHE** scriptCache,
+ SCRIPT_FONTPROPERTIES** fontProperties,
+ int* ascent)
+{
+ // This check is necessary because NextWinFontData can be called again
+ // after we already ran out of fonts. fontDataAt behaves in a strange
+ // manner when the difference between param passed and # of fonts stored in
+ // WebKit::Font is larger than one. We can avoid this check by setting
+ // font_index_ to # of elements in hfonts_ when we run out of font. In that
+ // case, we'd have to go through a couple of more checks before returning
+ // false.
+ if (m_fontIndex == -1 || !m_font)
+ return false;
+
+ // If the font data for a fallback font requested is not yet retrieved, add
+ // them to our vectors. Note that '>' rather than '>=' is used to test that
+ // condition. primaryFont is not stored in hfonts_, and friends so that
+ // indices for fontDataAt and our vectors for font data are 1 off from each
+ // other. That is, when fully populated, hfonts_ and friends have one font
+ // fewer than what's contained in font_.
+ if (static_cast<size_t>(++m_fontIndex) > m_hfonts.size()) {
+ const FontData *fontData = m_font->fontDataAt(m_fontIndex);
+ if (!fontData) {
+ // Ran out of fonts.
+ m_fontIndex = -1;
+ return false;
+ }
+
+ // FIXME: this won't work for SegmentedFontData
+ // http://crbug.com/6425
+ const SimpleFontData* simpleFontData =
+ fontData->fontDataForCharacter(' ');
+
+ m_hfonts.append(simpleFontData->platformData().hfont());
+ m_scriptCaches.append(simpleFontData->platformData().scriptCache());
+ m_fontProperties.append(simpleFontData->platformData().scriptFontProperties());
+ m_ascents.append(simpleFontData->ascent());
+ }
+
+ *hfont = m_hfonts[m_fontIndex - 1];
+ *scriptCache = m_scriptCaches[m_fontIndex - 1];
+ *fontProperties = m_fontProperties[m_fontIndex - 1];
+ *ascent = m_ascents[m_fontIndex - 1];
+ return true;
+}
+
+void UniscribeHelperTextRun::resetFontIndex()
+{
+ m_fontIndex = 0;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h
new file mode 100644
index 0000000..b5c54a0
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UniscribeHelperTextRun_h
+#define UniscribeHelperTextRun_h
+
+#include "UniscribeHelper.h"
+
+namespace WebCore {
+
+class Font;
+class TextRun;
+
+// Wrapper around the Uniscribe helper that automatically sets it up with the
+// WebKit types we supply.
+class UniscribeHelperTextRun : public UniscribeHelper {
+public:
+ // Regular constructor used for WebCore text run processing.
+ UniscribeHelperTextRun(const TextRun&, const Font&);
+
+ // Constructor with the same interface as the gfx::UniscribeState. Using
+ // this constructor will not give you font fallback, but it will provide
+ // the ability to load fonts that may not be in the OS cache
+ // ("TryToPreloadFont") if the caller does not have a TextRun/Font.
+ UniscribeHelperTextRun(const wchar_t* input,
+ int inputLength,
+ bool isRtl,
+ HFONT hfont,
+ SCRIPT_CACHE*,
+ SCRIPT_FONTPROPERTIES*);
+
+protected:
+ virtual void tryToPreloadFont(HFONT);
+
+private:
+ // This function retrieves the Windows font data (HFONT, etc) for the next
+ // WebKit font in the list. If the font data corresponding to font_index_
+ // has been obtained before, returns the values stored in our internal
+ // vectors (hfonts_, etc). Otherwise, it gets next SimpleFontData from
+ // WebKit and adds them to in hfonts_ and friends so that font data can be
+ // returned quickly next time they're requested.
+ virtual bool nextWinFontData(HFONT*, SCRIPT_CACHE**, SCRIPT_FONTPROPERTIES**, int* ascent);
+ virtual void resetFontIndex();
+
+ // Reference to WebKit::Font that contains all the information about fonts
+ // we can use to render this input run of text. It is used in
+ // NextWinFontData to retrieve Windows font data for a series of
+ // non-primary fonts.
+ //
+ // This pointer can be NULL for no font fallback handling.
+ const Font* m_font;
+
+ // It's rare that many fonts are listed in stylesheets.
+ // Four would be large enough in most cases.
+ const static size_t kNumberOfFonts = 4;
+
+ // These vectors are used to store Windows font data for non-primary fonts.
+ Vector<HFONT, kNumberOfFonts> m_hfonts;
+ Vector<SCRIPT_CACHE*, kNumberOfFonts> m_scriptCaches;
+ Vector<SCRIPT_FONTPROPERTIES*, kNumberOfFonts> m_fontProperties;
+ Vector<int, kNumberOfFonts> m_ascents;
+
+ // Index of the fallback font we're currently using for NextWinFontData.
+ int m_fontIndex;
+};
+
+} // namespace WebCore
+
+#endif // UniscribeHelperTextRun_h
diff --git a/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp b/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp
new file mode 100644
index 0000000..bd30a97
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+// For htons/ntohs
+#include <arpa/inet.h>
+
+// Buffer helper class
+//
+// This class perform some trival buffer operations while checking for
+// out-of-bounds errors. As a family they return false if anything is amiss,
+// updating the current offset otherwise.
+class Buffer {
+public:
+ Buffer(const uint8_t* buffer, size_t length)
+ : m_buffer(buffer)
+ , m_length(length)
+ , m_offset(0) { }
+
+ bool skip(size_t numBytes)
+ {
+ if (m_offset + numBytes > m_length)
+ return false;
+ m_offset += numBytes;
+ return true;
+ }
+
+ bool readU8(uint8_t* value)
+ {
+ if (m_offset + sizeof(uint8_t) > m_length)
+ return false;
+ *value = m_buffer[m_offset];
+ m_offset += sizeof(uint8_t);
+ return true;
+ }
+
+ bool readU16(uint16_t* value)
+ {
+ if (m_offset + sizeof(uint16_t) > m_length)
+ return false;
+ memcpy(value, m_buffer + m_offset, sizeof(uint16_t));
+ *value = ntohs(*value);
+ m_offset += sizeof(uint16_t);
+ return true;
+ }
+
+ bool readS16(int16_t* value)
+ {
+ return readU16(reinterpret_cast<uint16_t*>(value));
+ }
+
+ size_t offset() const
+ {
+ return m_offset;
+ }
+
+ void setOffset(size_t newoffset)
+ {
+ m_offset = newoffset;
+ }
+
+private:
+ const uint8_t *const m_buffer;
+ const size_t m_length;
+ size_t m_offset;
+};
+
+// VDMX parsing code.
+//
+// VDMX tables are found in some TrueType/OpenType fonts and contain
+// ascender/descender overrides for certain (usually small) sizes. This is
+// needed in order to match font metrics on Windows.
+//
+// Freetype does not parse these tables so we do so here.
+
+namespace WebCore {
+
+// Parse a TrueType VDMX table.
+// yMax: (output) the ascender value from the table
+// yMin: (output) the descender value from the table (negative!)
+// vdmx: the table bytes
+// vdmxLength: length of @vdmx, in bytes
+// targetPixelSize: the pixel size of the font (e.g. 16)
+//
+// Returns true iff a suitable match are found. Otherwise, *yMax and *yMin are
+// untouched. size_t must be 32-bits to avoid overflow.
+//
+// See http://www.microsoft.com/opentype/otspec/vdmx.htm
+bool parseVDMX(int* yMax, int* yMin,
+ const uint8_t* vdmx, size_t vdmxLength,
+ unsigned targetPixelSize)
+{
+ Buffer buf(vdmx, vdmxLength);
+
+ // We ignore the version. Future tables should be backwards compatible with
+ // this layout.
+ uint16_t numRatios;
+ if (!buf.skip(4) || !buf.readU16(&numRatios))
+ return false;
+
+ // Now we have two tables. Firstly we have @numRatios Ratio records, then a
+ // matching array of @numRatios offsets. We save the offset of the beginning
+ // of this second table.
+ //
+ // Range 6 <= x <= 262146
+ unsigned long offsetTableOffset =
+ buf.offset() + 4 /* sizeof struct ratio */ * numRatios;
+
+ unsigned desiredRatio = 0xffffffff;
+ // We read 4 bytes per record, so the offset range is
+ // 6 <= x <= 524286
+ for (unsigned i = 0; i < numRatios; ++i) {
+ uint8_t xRatio, yRatio1, yRatio2;
+
+ if (!buf.skip(1)
+ || !buf.readU8(&xRatio)
+ || !buf.readU8(&yRatio1)
+ || !buf.readU8(&yRatio2))
+ return false;
+
+ // This either covers 1:1, or this is the default entry (0, 0, 0)
+ if ((xRatio == 1 && yRatio1 <= 1 && yRatio2 >= 1)
+ || (xRatio == 0 && yRatio1 == 0 && yRatio2 == 0)) {
+ desiredRatio = i;
+ break;
+ }
+ }
+
+ if (desiredRatio == 0xffffffff) // no ratio found
+ return false;
+
+ // Range 10 <= x <= 393216
+ buf.setOffset(offsetTableOffset + sizeof(uint16_t) * desiredRatio);
+
+ // Now we read from the offset table to get the offset of another array
+ uint16_t groupOffset;
+ if (!buf.readU16(&groupOffset))
+ return false;
+ // Range 0 <= x <= 65535
+ buf.setOffset(groupOffset);
+
+ uint16_t numRecords;
+ if (!buf.readU16(&numRecords) || !buf.skip(sizeof(uint16_t)))
+ return false;
+
+ // We read 6 bytes per record, so the offset range is
+ // 4 <= x <= 458749
+ for (unsigned i = 0; i < numRecords; ++i) {
+ uint16_t pixelSize;
+ if (!buf.readU16(&pixelSize))
+ return false;
+ // the entries are sorted, so we can abort early if need be
+ if (pixelSize > targetPixelSize)
+ return false;
+
+ if (pixelSize == targetPixelSize) {
+ int16_t tempYMax, tempYMin;
+ if (!buf.readS16(&tempYMax)
+ || !buf.readS16(&tempYMin))
+ return false;
+ *yMin = tempYMin;
+ *yMax = tempYMax;
+ return true;
+ }
+ if (!buf.skip(2 * sizeof(int16_t)))
+ return false;
+ }
+
+ return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/chromium/VDMXParser.h b/Source/WebCore/platform/graphics/chromium/VDMXParser.h
new file mode 100644
index 0000000..ef625b7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VDMXParser.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VDMXParser_h
+#define VDMXParser_h
+
+namespace WebCore {
+ bool parseVDMX(int* ymax, int* ymin,
+ const uint8_t* vdmx, size_t vdmxLength,
+ unsigned targetPixelSize);
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp
new file mode 100644
index 0000000..43b40e2
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "VideoFrameChromium.h"
+
+namespace WebCore {
+
+const unsigned VideoFrameChromium::maxPlanes = 3;
+const unsigned VideoFrameChromium::numRGBPlanes = 1;
+const unsigned VideoFrameChromium::rgbPlane = 0;
+const unsigned VideoFrameChromium::numYUVPlanes = 3;
+const unsigned VideoFrameChromium::yPlane = 0;
+const unsigned VideoFrameChromium::uPlane = 1;
+const unsigned VideoFrameChromium::vPlane = 2;
+
+} // namespace WebCore
+
+
diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h b/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h
new file mode 100644
index 0000000..e176b0c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VideoFrameChromium_h
+#define VideoFrameChromium_h
+
+#include "IntSize.h"
+
+namespace WebCore {
+
+// A class that represents a video frame in chromium.
+class VideoFrameChromium {
+public:
+ static const unsigned maxPlanes;
+ static const unsigned numRGBPlanes;
+ static const unsigned rgbPlane;
+ static const unsigned numYUVPlanes;
+ static const unsigned yPlane;
+ static const unsigned uPlane;
+ static const unsigned vPlane;
+
+ // These enums must be kept in sync with WebKit::WebVideoFrame.
+ enum Format {
+ Invalid,
+ RGB555,
+ RGB565,
+ RGB24,
+ RGB32,
+ RGBA,
+ YV12,
+ YV16,
+ NV12,
+ Empty,
+ ASCII,
+ };
+
+ enum SurfaceType {
+ TypeSystemMemory,
+ TypeTexture,
+ };
+
+ virtual SurfaceType surfaceType() const = 0;
+ virtual Format format() const = 0;
+ virtual unsigned width() const = 0;
+ virtual unsigned height() const = 0;
+ virtual unsigned planes() const = 0;
+ virtual int stride(unsigned plane) const = 0;
+ virtual const void* data(unsigned plane) const = 0;
+ virtual unsigned texture(unsigned plane) const = 0;
+ virtual const IntSize requiredTextureSize(unsigned plane) const = 0;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h b/Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h
new file mode 100644
index 0000000..c596f87
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VideoFrameProvider.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef VideoFrameProvider_h
+#define VideoFrameProvider_h
+
+#include "VideoFrameChromium.h"
+
+namespace WebCore {
+
+class VideoFrameProvider {
+public:
+ virtual ~VideoFrameProvider() { }
+
+ // This function returns a pointer to a VideoFrameChromium, which is
+ // the WebCore wrapper for a video frame in Chromium. getCurrentFrame()
+ // places a lock on the frame in Chromium. Calls to this method should
+ // always be followed with a call to putCurrentFrame().
+ // The ownership of the object is not transferred to the caller and
+ // the caller should not free the returned object.
+ virtual VideoFrameChromium* getCurrentFrame() = 0;
+ // This function releases the lock on the video frame in chromium. It should
+ // always be called after getCurrentFrame(). Frames passed into this method
+ // should no longer be referenced after the call is made.
+ virtual void putCurrentFrame(VideoFrameChromium*) = 0;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
new file mode 100644
index 0000000..81264b3
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "VideoLayerChromium.h"
+
+#include "Extensions3DChromium.h"
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+#include "NotImplemented.h"
+#include "RenderLayerBacking.h"
+#include "VideoFrameChromium.h"
+#include "VideoFrameProvider.h"
+
+namespace WebCore {
+
+// These values are magic numbers that are used in the transformation
+// from YUV to RGB color values.
+const float VideoLayerChromium::yuv2RGB[9] = {
+ 1.f, 1.f, 1.f,
+ 0.f, -.344f, 1.772f,
+ 1.403f, -.714f, 0.f,
+};
+
+VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_yuvShaderProgram(0)
+ , m_rgbaShaderProgram(0)
+ , m_yuvShaderMatrixLocation(0)
+ , m_yuvWidthScaleFactorLocation(0)
+ , m_rgbaShaderMatrixLocation(0)
+ , m_rgbaWidthScaleFactorLocation(0)
+ , m_ccMatrixLocation(0)
+ , m_yTextureLocation(0)
+ , m_uTextureLocation(0)
+ , m_vTextureLocation(0)
+ , m_rgbaTextureLocation(0)
+ , m_yuvAlphaLocation(0)
+ , m_rgbaAlphaLocation(0)
+ , m_initialized(false)
+{
+ // Frame textures are allocated based on stride width, not visible frame
+ // width, such that there is a guarantee that the frame rows line up
+ // properly and are not shifted by (stride - width) pixels. To hide the
+ // "padding" pixels between the edge of the visible frame width and the end
+ // of the stride, we give the shader a widthScaleFactor (<=1.0) of how much
+ // of the width of the texture should be shown when drawing the texture onto
+ // the vertices.
+ char vertexShaderString[] =
+ "precision mediump float; \n"
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform float widthScaleFactor; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = vec2(widthScaleFactor * a_texCoord.x, a_texCoord.y); \n"
+ "} \n";
+
+ char yuvFragmentShaderString[] =
+ "precision mediump float; \n"
+ "precision mediump int; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D y_texture; \n"
+ "uniform sampler2D u_texture; \n"
+ "uniform sampler2D v_texture; \n"
+ "uniform float alpha; \n"
+ "uniform mat3 cc_matrix; \n"
+ "void main() \n"
+ "{ \n"
+ " float y = texture2D(y_texture, v_texCoord).x; \n"
+ " float u = texture2D(u_texture, v_texCoord).r - .5; \n"
+ " float v = texture2D(v_texture, v_texCoord).r - .5; \n"
+ " vec3 rgb = cc_matrix * vec3(y, u, v); \n"
+ " gl_FragColor = vec4(rgb.x, rgb.y, rgb.z, 1.0) * alpha; \n"
+ "} \n";
+
+ char rgbaFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D rgba_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(rgba_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_rgbaShaderProgram = createShaderProgram(m_context, vertexShaderString, rgbaFragmentShaderString);
+ if (!m_rgbaShaderProgram) {
+ LOG_ERROR("VideoLayerChromium: Failed to create rgba shader program");
+ return;
+ }
+
+ m_yuvShaderProgram = createShaderProgram(m_context, vertexShaderString, yuvFragmentShaderString);
+ if (!m_yuvShaderProgram) {
+ LOG_ERROR("VideoLayerChromium: Failed to create yuv shader program");
+ return;
+ }
+
+ m_yuvShaderMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "matrix");
+ m_yuvWidthScaleFactorLocation = m_context->getUniformLocation(m_yuvShaderProgram, "widthScaleFactor");
+ m_yTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "y_texture");
+ m_uTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "u_texture");
+ m_vTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "v_texture");
+ m_ccMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "cc_matrix");
+ m_yuvAlphaLocation = m_context->getUniformLocation(m_yuvShaderProgram, "alpha");
+
+ ASSERT(m_yuvShaderMatrixLocation != -1);
+ ASSERT(m_yuvWidthScaleFactorLocation != -1);
+ ASSERT(m_yTextureLocation != -1);
+ ASSERT(m_uTextureLocation != -1);
+ ASSERT(m_vTextureLocation != -1);
+ ASSERT(m_ccMatrixLocation != -1);
+ ASSERT(m_yuvAlphaLocation != -1);
+
+ m_rgbaShaderMatrixLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "matrix");
+ m_rgbaTextureLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "rgba_texture");
+ m_rgbaWidthScaleFactorLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "widthScaleFactor");
+ m_rgbaAlphaLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "alpha");
+
+ ASSERT(m_rgbaShaderMatrixLocation != -1);
+ ASSERT(m_rgbaTextureLocation != -1);
+ ASSERT(m_rgbaWidthScaleFactorLocation != -1);
+ ASSERT(m_rgbaAlphaLocation != -1);
+
+ m_initialized = true;
+}
+
+VideoLayerChromium::SharedValues::~SharedValues()
+{
+ if (m_yuvShaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_yuvShaderProgram));
+ if (m_rgbaShaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_rgbaShaderProgram));
+}
+
+PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner,
+ VideoFrameProvider* provider)
+{
+ return adoptRef(new VideoLayerChromium(owner, provider));
+}
+
+VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider* provider)
+ : LayerChromium(owner)
+ , m_skipsDraw(true)
+ , m_frameFormat(VideoFrameChromium::Invalid)
+ , m_provider(provider)
+ , m_currentFrame(0)
+{
+ resetFrameParameters();
+}
+
+VideoLayerChromium::~VideoLayerChromium()
+{
+ cleanupResources();
+}
+
+void VideoLayerChromium::cleanupResources()
+{
+ LayerChromium::cleanupResources();
+ releaseCurrentFrame();
+ if (!layerRenderer())
+ return;
+
+ GraphicsContext3D* context = layerRendererContext();
+ for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
+ if (m_textures[plane])
+ GLC(context, context->deleteTexture(m_textures[plane]));
+ }
+}
+
+void VideoLayerChromium::updateContentsIfDirty()
+{
+ if (!m_contentsDirty)
+ return;
+
+ RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
+ if (!backing || backing->paintingGoesToWindow())
+ return;
+
+ ASSERT(drawsContent());
+
+ m_skipsDraw = false;
+ VideoFrameChromium* frame = m_provider->getCurrentFrame();
+ if (!frame) {
+ m_skipsDraw = true;
+ m_provider->putCurrentFrame(frame);
+ return;
+ }
+
+ m_frameFormat = frame->format();
+ unsigned textureFormat = determineTextureFormat(frame);
+ if (textureFormat == GraphicsContext3D::INVALID_VALUE) {
+ // FIXME: Implement other paths.
+ notImplemented();
+ m_skipsDraw = true;
+ m_provider->putCurrentFrame(frame);
+ return;
+ }
+
+ if (frame->surfaceType() == VideoFrameChromium::TypeTexture) {
+ releaseCurrentFrame();
+ saveCurrentFrame(frame);
+ m_dirtyRect.setSize(FloatSize());
+ m_contentsDirty = false;
+ return;
+ }
+
+ // Allocate textures for planes if they are not allocated already, or
+ // reallocate textures that are the wrong size for the frame.
+ GraphicsContext3D* context = layerRendererContext();
+ bool texturesAllocated = allocateTexturesIfNeeded(context, frame, textureFormat);
+ if (!texturesAllocated) {
+ m_skipsDraw = true;
+ m_provider->putCurrentFrame(frame);
+ return;
+ }
+
+ // Update texture planes.
+ for (unsigned plane = 0; plane < frame->planes(); plane++) {
+ ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]);
+ updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane));
+ }
+
+ m_dirtyRect.setSize(FloatSize());
+ m_contentsDirty = false;
+
+ m_provider->putCurrentFrame(frame);
+}
+
+unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame)
+{
+ switch (frame->format()) {
+ case VideoFrameChromium::YV12:
+ return GraphicsContext3D::LUMINANCE;
+ case VideoFrameChromium::RGBA:
+ return GraphicsContext3D::RGBA;
+ default:
+ break;
+ }
+ return GraphicsContext3D::INVALID_VALUE;
+}
+
+bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, VideoFrameChromium* frame, unsigned textureFormat)
+{
+ ASSERT(context);
+ ASSERT(frame);
+
+ for (unsigned plane = 0; plane < frame->planes(); plane++) {
+ IntSize planeTextureSize = frame->requiredTextureSize(plane);
+
+ // If the renderer cannot handle this large of a texture, return false.
+ // FIXME: Remove this test when tiled layers are implemented.
+ if (!layerRenderer()->checkTextureSize(planeTextureSize))
+ return false;
+
+ if (!m_textures[plane])
+ m_textures[plane] = layerRenderer()->createLayerTexture();
+
+ if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) {
+ allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat);
+ m_textureSizes[plane] = planeTextureSize;
+ m_frameSizes[plane] = IntSize(frame->width(), frame->height());
+ }
+ }
+ return true;
+}
+
+void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat)
+{
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE));
+}
+
+void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data)
+{
+ ASSERT(context);
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ void* mem = static_cast<Extensions3DChromium*>(context->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY);
+ if (mem) {
+ memcpy(mem, data, dimensions.width() * dimensions.height());
+ GLC(context, static_cast<Extensions3DChromium*>(context->getExtensions())->unmapTexSubImage2DCHROMIUM(mem));
+ } else {
+ // FIXME: We should have some sort of code to handle the case when
+ // mapTexSubImage2D fails.
+ m_skipsDraw = true;
+ }
+}
+
+void VideoLayerChromium::draw()
+{
+ if (m_skipsDraw)
+ return;
+
+ ASSERT(layerRenderer());
+ const VideoLayerChromium::SharedValues* sv = layerRenderer()->videoLayerSharedValues();
+ ASSERT(sv && sv->initialized());
+
+ switch (m_frameFormat) {
+ case VideoFrameChromium::YV12:
+ drawYUV(sv);
+ break;
+ case VideoFrameChromium::RGBA:
+ drawRGBA(sv);
+ break;
+ default:
+ // FIXME: Implement other paths.
+ notImplemented();
+ break;
+ }
+ releaseCurrentFrame();
+}
+
+void VideoLayerChromium::releaseCurrentFrame()
+{
+ if (!m_currentFrame)
+ return;
+
+ m_provider->putCurrentFrame(m_currentFrame);
+ m_currentFrame = 0;
+ resetFrameParameters();
+}
+
+void VideoLayerChromium::drawYUV(const SharedValues* sv)
+{
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane]));
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane]));
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane]));
+
+ layerRenderer()->useShader(sv->yuvShaderProgram());
+ unsigned frameWidth = m_frameSizes[VideoFrameChromium::yPlane].width();
+ unsigned textureWidth = m_textureSizes[VideoFrameChromium::yPlane].width();
+ float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth;
+ GLC(context, context->uniform1f(sv->yuvWidthScaleFactorLocation(), widthScaleFactor));
+
+ GLC(context, context->uniform1i(sv->yTextureLocation(), 1));
+ GLC(context, context->uniform1i(sv->uTextureLocation(), 2));
+ GLC(context, context->uniform1i(sv->vTextureLocation(), 3));
+
+ GLC(context, context->uniformMatrix3fv(sv->ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
+
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ sv->yuvShaderMatrixLocation(), sv->yuvAlphaLocation());
+
+ // Reset active texture back to texture 0.
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+}
+
+void VideoLayerChromium::drawRGBA(const SharedValues* sv)
+{
+ GraphicsContext3D* context = layerRendererContext();
+ GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
+ GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane]));
+
+ layerRenderer()->useShader(sv->rgbaShaderProgram());
+ unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width();
+ unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width();
+ float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth;
+ GLC(context, context->uniform1f(sv->rgbaWidthScaleFactorLocation(), widthScaleFactor));
+
+ GLC(context, context->uniform1i(sv->rgbaTextureLocation(), 0));
+
+ drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
+ bounds().width(), bounds().height(), drawOpacity(),
+ sv->rgbaShaderMatrixLocation(), sv->rgbaAlphaLocation());
+}
+
+void VideoLayerChromium::resetFrameParameters()
+{
+ for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) {
+ m_textures[plane] = 0;
+ m_textureSizes[plane] = IntSize();
+ m_frameSizes[plane] = IntSize();
+ }
+}
+
+void VideoLayerChromium::saveCurrentFrame(VideoFrameChromium* frame)
+{
+ ASSERT(!m_currentFrame);
+ m_currentFrame = frame;
+ for (unsigned plane = 0; plane < frame->planes(); plane++) {
+ m_textures[plane] = frame->texture(plane);
+ m_textureSizes[plane] = frame->requiredTextureSize(plane);
+ m_frameSizes[plane] = m_textureSizes[plane];
+ }
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
new file mode 100644
index 0000000..0992ab7
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef VideoLayerChromium_h
+#define VideoLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerChromium.h"
+#include "VideoFrameProvider.h"
+
+namespace WebCore {
+
+// A Layer that contains a Video element.
+class VideoLayerChromium : public LayerChromium {
+public:
+ static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0,
+ VideoFrameProvider* = 0);
+ virtual ~VideoLayerChromium();
+ virtual void updateContentsIfDirty();
+ virtual bool drawsContent() { return true; }
+ virtual void draw();
+
+ // This function is called by VideoFrameProvider. When this method is called
+ // putCurrentFrame() must be called to return the frame currently held.
+ void releaseCurrentFrame();
+
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+ unsigned yuvShaderProgram() const { return m_yuvShaderProgram; }
+ unsigned rgbaShaderProgram() const { return m_rgbaShaderProgram; }
+ int yuvShaderMatrixLocation() const { return m_yuvShaderMatrixLocation; }
+ int rgbaShaderMatrixLocation() const { return m_rgbaShaderMatrixLocation; }
+ int yuvWidthScaleFactorLocation() const { return m_yuvWidthScaleFactorLocation; }
+ int rgbaWidthScaleFactorLocation() const { return m_rgbaWidthScaleFactorLocation; }
+ int yTextureLocation() const { return m_yTextureLocation; }
+ int uTextureLocation() const { return m_uTextureLocation; }
+ int vTextureLocation() const { return m_vTextureLocation; }
+ int yuvAlphaLocation() const { return m_yuvAlphaLocation; }
+ int rgbaAlphaLocation() const { return m_rgbaAlphaLocation; }
+ int rgbaTextureLocation() const { return m_rgbaTextureLocation; }
+ int ccMatrixLocation() const { return m_ccMatrixLocation; }
+ bool initialized() const { return m_initialized; }
+ private:
+ GraphicsContext3D* m_context;
+ unsigned m_yuvShaderProgram;
+ unsigned m_rgbaShaderProgram;
+ int m_yuvShaderMatrixLocation;
+ int m_yuvWidthScaleFactorLocation;
+ int m_rgbaShaderMatrixLocation;
+ int m_rgbaWidthScaleFactorLocation;
+ int m_ccMatrixLocation;
+ int m_yTextureLocation;
+ int m_uTextureLocation;
+ int m_vTextureLocation;
+ int m_rgbaTextureLocation;
+ int m_yuvAlphaLocation;
+ int m_rgbaAlphaLocation;
+ bool m_initialized;
+ };
+
+protected:
+ virtual void cleanupResources();
+
+private:
+ VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*);
+
+ static unsigned determineTextureFormat(VideoFrameChromium*);
+ bool allocateTexturesIfNeeded(GraphicsContext3D*, VideoFrameChromium*, unsigned textureFormat);
+ void updateYUVContents(GraphicsContext3D*, const VideoFrameChromium*);
+ void updateRGBAContents(GraphicsContext3D*, const VideoFrameChromium*);
+ void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat);
+ void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data);
+ void drawYUV(const SharedValues*);
+ void drawRGBA(const SharedValues*);
+ void resetFrameParameters();
+ void saveCurrentFrame(VideoFrameChromium*);
+
+ static const float yuv2RGB[9];
+
+ bool m_skipsDraw;
+ VideoFrameChromium::Format m_frameFormat;
+ VideoFrameProvider* m_provider;
+ VideoFrameChromium* m_currentFrame;
+
+ unsigned m_textures[3];
+ IntSize m_textureSizes[3];
+ IntSize m_frameSizes[3];
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
new file mode 100644
index 0000000..5b34bb9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WebGLLayerChromium.h"
+
+#include "GraphicsContext3D.h"
+#include "LayerRendererChromium.h"
+
+namespace WebCore {
+
+PassRefPtr<WebGLLayerChromium> WebGLLayerChromium::create(GraphicsLayerChromium* owner)
+{
+ return adoptRef(new WebGLLayerChromium(owner));
+}
+
+WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner)
+ : CanvasLayerChromium(owner)
+ , m_context(0)
+{
+}
+
+void WebGLLayerChromium::updateContentsIfDirty()
+{
+ if (!m_contentsDirty)
+ return;
+
+ GraphicsContext3D* rendererContext = layerRendererContext();
+ ASSERT(m_context);
+ if (m_textureChanged) {
+ rendererContext->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
+ // Set the min-mag filters to linear and wrap modes to GL_CLAMP_TO_EDGE
+ // to get around NPOT texture limitations of GLES.
+ rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
+ rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR);
+ rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
+ rendererContext->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
+ m_textureChanged = false;
+ }
+ // Update the contents of the texture used by the compositor.
+ if (m_contentsDirty) {
+ m_context->prepareTexture();
+ m_contentsDirty = false;
+ }
+}
+
+void WebGLLayerChromium::setContext(const GraphicsContext3D* context)
+{
+ m_context = const_cast<GraphicsContext3D*>(context);
+
+ unsigned int textureId = m_context->platformTexture();
+ if (textureId != m_textureId)
+ m_textureChanged = true;
+ m_textureId = textureId;
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
new file mode 100644
index 0000000..c67cc2c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef WebGLLayerChromium_h
+#define WebGLLayerChromium_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "CanvasLayerChromium.h"
+
+namespace WebCore {
+
+class GraphicsContext3D;
+
+// A Layer containing a WebGL canvas
+class WebGLLayerChromium : public CanvasLayerChromium {
+public:
+ static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0);
+ virtual bool drawsContent() { return m_context; }
+ virtual void updateContentsIfDirty();
+
+ void setContext(const GraphicsContext3D* context);
+
+private:
+ explicit WebGLLayerChromium(GraphicsLayerChromium* owner);
+ GraphicsContext3D* m_context;
+};
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif