diff options
Diffstat (limited to 'WebCore/platform/graphics')
70 files changed, 1933 insertions, 1057 deletions
diff --git a/WebCore/platform/graphics/FloatPoint.cpp b/WebCore/platform/graphics/FloatPoint.cpp index cf3d548..7e85b52 100644 --- a/WebCore/platform/graphics/FloatPoint.cpp +++ b/WebCore/platform/graphics/FloatPoint.cpp @@ -30,6 +30,7 @@ #include "TransformationMatrix.h" #include "FloatConversion.h" #include "IntPoint.h" +#include <math.h> namespace WebCore { @@ -37,6 +38,21 @@ FloatPoint::FloatPoint(const IntPoint& p) : m_x(p.x()), m_y(p.y()) { } +void FloatPoint::normalize() +{ + float tempLength = length(); + + if (tempLength) { + m_x /= tempLength; + m_y /= tempLength; + } +} + +float FloatPoint::length() const +{ + return sqrtf(lengthSquared()); +} + FloatPoint FloatPoint::matrixTransform(const AffineTransform& transform) const { double newX, newY; diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h index 5018f1d..73a1bac 100644 --- a/WebCore/platform/graphics/FloatPoint.h +++ b/WebCore/platform/graphics/FloatPoint.h @@ -80,6 +80,11 @@ public: void setX(float x) { m_x = x; } void setY(float y) { m_y = y; } + void set(float x, float y) + { + m_x = x; + m_y = y; + } void move(float dx, float dy) { m_x += dx; @@ -91,6 +96,19 @@ public: m_y *= sy; } + void normalize(); + + float dot(const FloatPoint& a) const + { + return m_x * a.x() + m_y * a.y(); + } + + float length() const; + float lengthSquared() const + { + return m_x * m_x + m_y * m_y; + } + #if PLATFORM(CG) FloatPoint(const CGPoint&); operator CGPoint() const; @@ -173,6 +191,12 @@ inline bool operator!=(const FloatPoint& a, const FloatPoint& b) return a.x() != b.x() || a.y() != b.y(); } +inline float operator*(const FloatPoint& a, const FloatPoint& b) +{ + // dot product + return a.dot(b); +} + inline IntPoint roundedIntPoint(const FloatPoint& p) { return IntPoint(static_cast<int>(roundf(p.x())), static_cast<int>(roundf(p.y()))); diff --git a/WebCore/platform/graphics/FloatPoint3D.cpp b/WebCore/platform/graphics/FloatPoint3D.cpp index 3d37eea..bb05e7f 100644 --- a/WebCore/platform/graphics/FloatPoint3D.cpp +++ b/WebCore/platform/graphics/FloatPoint3D.cpp @@ -21,21 +21,27 @@ #include "config.h" -#include <math.h> #include "FloatPoint3D.h" +#include <math.h> + namespace WebCore { void FloatPoint3D::normalize() { - float length = sqrtf(m_x * m_x + m_y * m_y + m_z * m_z); + float tempLength = length(); - if (length != 0) { - m_x /= length; - m_y /= length; - m_z /= length; + if (tempLength) { + m_x /= tempLength; + m_y /= tempLength; + m_z /= tempLength; } } +float FloatPoint3D::length() const +{ + return sqrtf(lengthSquared()); +} + } // namespace WebCore diff --git a/WebCore/platform/graphics/FloatPoint3D.h b/WebCore/platform/graphics/FloatPoint3D.h index d10e3c1..9ee548d 100644 --- a/WebCore/platform/graphics/FloatPoint3D.h +++ b/WebCore/platform/graphics/FloatPoint3D.h @@ -65,15 +65,85 @@ public: float z() const { return m_z; } void setZ(float z) { m_z = z; } + void set(float x, float y, float z) + { + m_x = x; + m_y = y; + m_z = z; + } + void move(float dx, float dy, float dz) + { + m_x += dx; + m_y += dy; + m_z += dz; + } + void scale(float sx, float sy, float sz) + { + m_x *= sx; + m_y *= sy; + m_z *= sz; + } void normalize(); + float dot(const FloatPoint3D& a) const + { + return m_x * a.x() + m_y * a.y() + m_z * a.z(); + } + + // Sets this FloatPoint3D to the cross product of the passed two. + // It is safe for "this" to be the same as either or both of the + // arguments. + void cross(const FloatPoint3D& a, const FloatPoint3D& b) + { + float x = a.y() * b.z() - a.z() * b.y(); + float y = a.z() * b.x() - a.x() * b.z(); + float z = a.x() * b.y() - a.y() * b.x(); + m_x = x; + m_y = y; + m_z = z; + } + + // Convenience function returning "this cross point" as a + // stack-allocated result. + FloatPoint3D cross(const FloatPoint3D& point) const + { + FloatPoint3D result; + result.cross(*this, point); + return result; + } + + float length() const; + float lengthSquared() const { return this->dot(*this); } + private: float m_x; float m_y; float m_z; }; +inline FloatPoint3D& operator +=(FloatPoint3D& a, const FloatPoint3D& b) +{ + a.move(b.x(), b.y(), b.z()); + return a; +} + +inline FloatPoint3D& operator -=(FloatPoint3D& a, const FloatPoint3D& b) +{ + a.move(-b.x(), -b.y(), -b.z()); + return a; +} + +inline FloatPoint3D operator+(const FloatPoint3D& a, const FloatPoint3D& b) +{ + return FloatPoint3D(a.x() + b.x(), a.y() + b.y(), a.z() + b.z()); +} + +inline FloatPoint3D operator-(const FloatPoint3D& a, const FloatPoint3D& b) +{ + return FloatPoint3D(a.x() - b.x(), a.y() - b.y(), a.z() - b.z()); +} + inline bool operator==(const FloatPoint3D& a, const FloatPoint3D& b) { return a.x() == b.x() && a.y() == b.y() && a.z() == b.z(); @@ -87,7 +157,7 @@ inline bool operator!=(const FloatPoint3D& a, const FloatPoint3D& b) inline float operator*(const FloatPoint3D& a, const FloatPoint3D& b) { // dot product - return a.x() * b.x() + a.y() * b.y() + a.z() * b.z(); + return a.dot(b); } } // namespace WebCore diff --git a/WebCore/platform/graphics/FloatRect.cpp b/WebCore/platform/graphics/FloatRect.cpp index 6dfa808..0d8a24e 100644 --- a/WebCore/platform/graphics/FloatRect.cpp +++ b/WebCore/platform/graphics/FloatRect.cpp @@ -76,10 +76,7 @@ void FloatRect::intersect(const FloatRect& other) b = 0; } - m_location.setX(l); - m_location.setY(t); - m_size.setWidth(r - l); - m_size.setHeight(b - t); + setLocationAndSizeFromEdges(l, t, r, b); } void FloatRect::unite(const FloatRect& other) @@ -97,10 +94,7 @@ void FloatRect::unite(const FloatRect& other) float r = max(right(), other.right()); float b = max(bottom(), other.bottom()); - m_location.setX(l); - m_location.setY(t); - m_size.setWidth(r - l); - m_size.setHeight(b - t); + setLocationAndSizeFromEdges(l, t, r, b); } void FloatRect::scale(float sx, float sy) @@ -111,6 +105,65 @@ void FloatRect::scale(float sx, float sy) m_size.setHeight(height() * sy); } +void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1) +{ + float left = min(p0.x(), p1.x()); + float top = min(p0.y(), p1.y()); + float right = max(p0.x(), p1.x()); + float bottom = max(p0.y(), p1.y()); + + setLocationAndSizeFromEdges(left, top, right, bottom); +} + +namespace { +// Helpers for 3- and 4-way max and min. + +template <typename T> +T min3(const T& v1, const T& v2, const T& v3) +{ + return min(min(v1, v2), v3); +} + +template <typename T> +T max3(const T& v1, const T& v2, const T& v3) +{ + return max(max(v1, v2), v3); +} + +template <typename T> +T min4(const T& v1, const T& v2, const T& v3, const T& v4) +{ + return min(min(v1, v2), min(v3, v4)); +} + +template <typename T> +T max4(const T& v1, const T& v2, const T& v3, const T& v4) +{ + return max(max(v1, v2), max(v3, v4)); +} + +} // anonymous namespace + +void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2) +{ + float left = min3(p0.x(), p1.x(), p2.x()); + float top = min3(p0.y(), p1.y(), p2.y()); + float right = max3(p0.x(), p1.x(), p2.x()); + float bottom = max3(p0.y(), p1.y(), p2.y()); + + setLocationAndSizeFromEdges(left, top, right, bottom); +} + +void FloatRect::fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3) +{ + float left = min4(p0.x(), p1.x(), p2.x(), p3.x()); + float top = min4(p0.y(), p1.y(), p2.y(), p3.y()); + float right = max4(p0.x(), p1.x(), p2.x(), p3.x()); + float bottom = max4(p0.y(), p1.y(), p2.y(), p3.y()); + + setLocationAndSizeFromEdges(left, top, right, bottom); +} + static inline int safeFloatToInt(float x) { static const int s_intMax = std::numeric_limits<int>::max(); diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h index 2b23576..e387927 100644 --- a/WebCore/platform/graphics/FloatRect.h +++ b/WebCore/platform/graphics/FloatRect.h @@ -96,7 +96,9 @@ public: bool isEmpty() const { return m_size.isEmpty(); } + float left() const { return x(); } float right() const { return x() + width(); } + float top() const { return y(); } float bottom() const { return y() + height(); } FloatPoint center() const { return FloatPoint(x() + width() / 2, y() + height() / 2); } @@ -129,6 +131,11 @@ public: void scale(float s) { scale(s, s); } void scale(float sx, float sy); + // Re-initializes this rectangle to fit the sets of passed points. + void fitToPoints(const FloatPoint& p0, const FloatPoint& p1); + void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2); + void fitToPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& p3); + #if PLATFORM(CG) FloatRect(const CGRect&); operator CGRect() const; @@ -168,6 +175,13 @@ public: private: FloatPoint m_location; FloatSize m_size; + + void setLocationAndSizeFromEdges(float left, float top, float right, float bottom) + { + m_location.set(left, top); + m_size.setWidth(right - left); + m_size.setHeight(bottom - top); + } }; inline FloatRect intersection(const FloatRect& a, const FloatRect& b) diff --git a/WebCore/platform/graphics/FloatSize.cpp b/WebCore/platform/graphics/FloatSize.cpp index 86fa4c0..c199297 100644 --- a/WebCore/platform/graphics/FloatSize.cpp +++ b/WebCore/platform/graphics/FloatSize.cpp @@ -29,6 +29,7 @@ #include "FloatConversion.h" #include "IntSize.h" +#include <math.h> namespace WebCore { @@ -36,6 +37,11 @@ FloatSize::FloatSize(const IntSize& size) : m_width(size.width()), m_height(size { } +float FloatSize::diagonalLength() const +{ + return sqrtf(diagonalLengthSquared()); +} + FloatSize FloatSize::narrowPrecision(double width, double height) { return FloatSize(narrowPrecisionToFloat(width), narrowPrecisionToFloat(height)); diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index ff3d4de..160fc9a 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -83,6 +83,12 @@ public: m_height < other.m_height ? m_height : other.m_height); } + float diagonalLength() const; + float diagonalLengthSquared() const + { + return m_width * m_width + m_height * m_height; + } + #if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) explicit FloatSize(const CGSize&); // don't do this implicitly since it's lossy operator CGSize() const; diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp index bb4f858..94f3424 100644 --- a/WebCore/platform/graphics/GraphicsContext.cpp +++ b/WebCore/platform/graphics/GraphicsContext.cpp @@ -130,29 +130,29 @@ void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace) setPlatformStrokeColor(color, colorSpace); } -void GraphicsContext::setShadow(const FloatSize& size, float blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace) { - m_common->state.shadowSize = size; + m_common->state.shadowOffset = offset; m_common->state.shadowBlur = blur; m_common->state.shadowColor = color; - setPlatformShadow(size, blur, color, colorSpace); + setPlatformShadow(offset, blur, color, colorSpace); } void GraphicsContext::clearShadow() { - m_common->state.shadowSize = IntSize(); + m_common->state.shadowOffset = FloatSize(); m_common->state.shadowBlur = 0; m_common->state.shadowColor = Color(); clearPlatformShadow(); } -bool GraphicsContext::getShadow(FloatSize& size, float& blur, Color& color) const +bool GraphicsContext::getShadow(FloatSize& offset, float& blur, Color& color) const { - size = m_common->state.shadowSize; + offset = m_common->state.shadowOffset; blur = m_common->state.shadowBlur; color = m_common->state.shadowColor; - return color.isValid() && color.alpha() && (blur || size.width() || size.height()); + return color.isValid() && color.alpha() && (blur || offset.width() || offset.height()); } float GraphicsContext::strokeThickness() const diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index 1056d81..c5440f3 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -40,6 +40,7 @@ #if PLATFORM(CG) typedef struct CGContext PlatformGraphicsContext; #elif PLATFORM(CAIRO) +#include "PlatformRefPtrCairo.h" typedef struct _cairo PlatformGraphicsContext; #elif PLATFORM(OPENVG) namespace WebCore { @@ -306,7 +307,12 @@ namespace WebCore { FloatRect roundToDevicePixels(const FloatRect&); void drawLineForText(const IntPoint&, int width, bool printing); - void drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar); + enum TextCheckingLineStyle { + TextCheckingSpellingLineStyle, + TextCheckingGrammarLineStyle, + TextCheckingReplacementLineStyle + }; + void drawLineForTextChecking(const IntPoint&, int width, TextCheckingLineStyle); bool paintingDisabled() const; void setPaintingDisabled(bool); @@ -332,8 +338,11 @@ namespace WebCore { void setAlpha(float); #if PLATFORM(CAIRO) float getAlpha(); - void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius); - static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur); + void applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius); + PlatformRefPtr<cairo_surface_t> createShadowMask(PassOwnPtr<ImageBuffer>, const FloatRect&, float radius); + + static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur); + void drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace); #endif void setCompositeOperation(CompositeOperator); diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h index 6bf465b..903c7e3 100644 --- a/WebCore/platform/graphics/GraphicsContextPrivate.h +++ b/WebCore/platform/graphics/GraphicsContextPrivate.h @@ -72,7 +72,7 @@ namespace WebCore { bool paintingDisabled; - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 87060a4..a5db85f 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -564,17 +564,10 @@ MediaPlayer::SupportsType MediaPlayer::supportsType(ContentType contentType) String type = contentType.type().lower(); String typeCodecs = contentType.parameter(codecs()); - // 4.8.10.3 MIME types - In the absence of a specification to the contrary, the MIME type "application/octet-stream" - // when used with parameters, e.g. "application/octet-stream;codecs=theora", is a type that the user agent knows - // it cannot render. - if (type == applicationOctetStream()) { - if (!typeCodecs.isEmpty()) - return IsNotSupported; - - // The MIME type "application/octet-stream" with no parameters is never a type that the user agent knows it - // cannot render. - return MayBeSupported; - } + // 4.8.10.3 MIME types - The canPlayType(type) method must return the empty string if type is a type that the + // user agent knows it cannot render or is the type "application/octet-stream" + if (type == applicationOctetStream()) + return IsNotSupported; MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, typeCodecs); if (!engine) diff --git a/WebCore/platform/graphics/PathTraversalState.cpp b/WebCore/platform/graphics/PathTraversalState.cpp index d202649..ecdcb1b 100644 --- a/WebCore/platform/graphics/PathTraversalState.cpp +++ b/WebCore/platform/graphics/PathTraversalState.cpp @@ -160,7 +160,7 @@ PathTraversalState::PathTraversalState(PathTraversalAction action) float PathTraversalState::closeSubpath() { float distance = distanceLine(m_current, m_start); - m_start = m_control1 = m_control2 = m_current; + m_current = m_control1 = m_control2 = m_start; return distance; } diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index f6d8f3d..cd5d362 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -70,11 +70,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons } // Text shadow, inspired by FontMac - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() & cTextFill - && context->getShadow(shadowSize, shadowBlur, shadowColor); + && context->getShadow(shadowOffset, shadowBlur, shadowColor); // TODO: Blur support if (hasShadow) { @@ -95,7 +95,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; - context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowSize, shadowBlur); + context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur); // Draw shadow into a new ImageBuffer OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); @@ -113,9 +113,9 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons cairo_restore(shadowCr); } cairo_translate(cr, 0.0, -extents.height); - context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); + context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); #else - cairo_translate(cr, shadowSize.width(), shadowSize.height()); + cairo_translate(cr, shadowOffset.width(), shadowOffset.height()); cairo_show_glyphs(cr, glyphs, numGlyphs); if (font->syntheticBoldOffset()) { cairo_save(cr); @@ -195,7 +195,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons // Re-enable the platform shadow we disabled earlier if (hasShadow) - context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace); + context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace); cairo_restore(cr); } diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 3a667ac..19cc518 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -44,6 +44,7 @@ #include "NotImplemented.h" #include "Path.h" #include "Pattern.h" +#include "PlatformRefPtrCairo.h" #include "SimpleFontData.h" #include "SourceGraphic.h" @@ -175,7 +176,7 @@ static void addConvexPolygonToContext(cairo_t* context, size_t numPoints, const cairo_close_path(context); } -void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur) +void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& radius, const FloatRect& sourceRect, const FloatSize& shadowOffset, float shadowBlur) { #if ENABLE(FILTERS) // limit radius to 128 @@ -185,17 +186,17 @@ void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, // determine dimensions of shadow rect shadowRect = FloatRect(sourceRect.location(), shadowBufferSize); - shadowRect.move(shadowSize.width() - radius, shadowSize.height() - radius); + shadowRect.move(shadowOffset.width() - radius, shadowOffset.height() - radius); #endif } static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow) { #if ENABLE(FILTERS) - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) + if (!context->getShadow(shadowOffset, shadowBlur, shadowColor)) return; // Calculate filter values to create appropriate shadow. @@ -211,7 +212,7 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; - GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowSize, shadowBlur); + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur); // Create suitably-sized ImageBuffer to hold the shadow. OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); @@ -228,7 +229,7 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva if (strokeShadow) setPlatformStroke(context, shadowContext, gcp); - context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); + context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); #endif } @@ -623,24 +624,38 @@ void GraphicsContext::fillRect(const FloatRect& rect) static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor) { #if ENABLE(FILTERS) - FloatSize shadowSize; + AffineTransform transform = context->getCTM(); + // drawTiledShadow still does not work with rotations. + if ((transform.isIdentityOrTranslationOrFlipped())) { + cairo_t* cr = context->platformContext(); + cairo_save(cr); + appendWebCorePathToCairoContext(cr, Path::createRectangle(rect)); + FloatSize corner; + IntRect shadowRect(rect); + context->drawTiledShadow(shadowRect, corner, corner, corner, corner, DeviceColorSpace); + cairo_restore(cr); + + return; + } + + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) + if (!context->getShadow(shadowOffset, shadowBlur, shadowColor)) return; IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; - GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowSize, shadowBlur); + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, rect, shadowOffset, shadowBlur); // Draw shadow into a new ImageBuffer OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); GraphicsContext* shadowContext = shadowBuffer->context(); shadowContext->fillRect(FloatRect(FloatPoint(radius, radius), rect.size()), rectColor, DeviceColorSpace); - context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); + context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); #endif } @@ -759,7 +774,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr #include "DrawErrorUnderline.h" #endif -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width, TextCheckingLineStyle style) { if (paintingDisabled()) return; @@ -767,12 +782,17 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, cairo_t* cr = m_data->cr; cairo_save(cr); - // Convention is green for grammar, red for spelling - // These need to become configurable - if (grammar) - cairo_set_source_rgb(cr, 0, 1, 0); - else + switch (style) { + case TextCheckingSpellingLineStyle: cairo_set_source_rgb(cr, 1, 0, 0); + break; + case TextCheckingGrammarLineStyle: + cairo_set_source_rgb(cr, 0, 1, 0); + break; + default: + cairo_restore(cr); + return; + } #if PLATFORM(GTK) // We ignore most of the provided constants in favour of the platform style @@ -917,24 +937,29 @@ void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color cons if (m_common->state.shadowsIgnoreTransforms) { // Meaning that this graphics context is associated with a CanvasRenderingContext // We flip the height since CG and HTML5 Canvas have opposite Y axis - m_common->state.shadowSize = FloatSize(size.width(), -size.height()); + m_common->state.shadowOffset = FloatSize(size.width(), -size.height()); } } -void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius) +void GraphicsContext::applyPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float radius) { #if ENABLE(FILTERS) - cairo_t* cr = m_data->cr; + setColor(m_data->cr, shadowColor); + PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(buffer, shadowRect, radius)); + cairo_mask_surface(m_data->cr, shadowMask.get(), shadowRect.x(), shadowRect.y()); +#endif +} - // calculate the standard deviation - float sd = FEGaussianBlur::calculateStdDeviation(radius); +PlatformRefPtr<cairo_surface_t> GraphicsContext::createShadowMask(PassOwnPtr<ImageBuffer> buffer, const FloatRect& shadowRect, float radius) +{ +#if ENABLE(FILTERS) + if (!radius) + return buffer->m_data.m_surface; - // draw the shadow without blurring, if radius is zero - if (!radius || !sd) { - setColor(cr, shadowColor); - cairo_mask_surface(cr, buffer->m_data.m_surface, shadowRect.x(), shadowRect.y()); - return; - } + FloatPoint blurRadius = FloatPoint(radius, radius); + float sd = FEGaussianBlur::calculateStdDeviation(radius); + if (!sd) + return buffer->m_data.m_surface; // create filter RefPtr<Filter> filter = ImageBufferFilter::create(); @@ -945,14 +970,11 @@ void GraphicsContext::createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const RefPtr<FilterEffect> blur = FEGaussianBlur::create(source.get(), sd, sd); blur->setScaledSubRegion(FloatRect(FloatPoint(), shadowRect.size())); blur->apply(filter.get()); - - // Mask the filter with the shadow color and draw it to the context. - // Masking makes it possible to just blur the alpha channel. - setColor(cr, shadowColor); - cairo_mask_surface(cr, blur->resultImage()->m_data.m_surface, shadowRect.x(), shadowRect.y()); + return blur->resultImage()->m_data.m_surface; #endif } + void GraphicsContext::clearPlatformShadow() { notImplemented(); @@ -1218,6 +1240,200 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& r) clipOut(p); } +static inline FloatPoint getPhase(const FloatRect& dest, const FloatRect& tile) +{ + FloatPoint phase = dest.location(); + phase.move(-tile.x(), -tile.y()); + + return phase; +} + +/* + This function uses tiling to improve the performance of the shadow + drawing of rounded rectangles. The code basically does the following + steps: + + 1. Calculate the minimum rectangle size required to create the + tiles + + 2. If that size is smaller than the real rectangle render the new + small rectangle and its shadow in a new surface, in other case + render the shadow of the real rectangle in the destination + surface. + + 3. Calculate the sizes and positions of the tiles and their + destinations and use drawPattern to render the final shadow. The + code divides the rendering in 8 tiles: + + 1 | 2 | 3 + ----------- + 4 | | 5 + ----------- + 6 | 7 | 8 + + The corners are directly copied from the small rectangle to the + real one and the side tiles are 1 pixel width, we use them as + + tiles to cover the destination side. The corner tiles are bigger + than just the side of the rounded corner, we need to increase it + because the modifications caused by the corner over the blur + effect. We fill the central part with solid color to complete the + shadow. + */ +void GraphicsContext::drawTiledShadow(const IntRect& rect, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius, ColorSpace colorSpace) +{ +#if ENABLE(FILTERS) + FloatSize shadowSize; + float shadowBlur; + Color shadowColor; + if (!getShadow(shadowSize, shadowBlur, shadowColor)) + return; + + // Calculate filter values to create appropriate shadow. + cairo_t* cr = m_data->cr; + + IntSize shadowBufferSize; + FloatRect shadowRect; + float blurRadius = 0; + GraphicsContext::calculateShadowBufferDimensions(shadowBufferSize, shadowRect, blurRadius, rect, shadowSize, shadowBlur); + + // Size of the tiling side. + int sideTileWidth = 1; + float radiusTwice = blurRadius * 2; + + // Find the extra space needed from the curve of the corners. + int extraWidthFromCornerRadii = radiusTwice + max(topLeftRadius.width(), bottomLeftRadius.width()) + + radiusTwice + max(topRightRadius.width(), bottomRightRadius.width()); + int extraHeightFromCornerRadii = radiusTwice + max(topLeftRadius.height(), topRightRadius.height()) + + radiusTwice + max(bottomLeftRadius.height(), bottomRightRadius.height()); + + // The length of a side of the buffer is the enough space for four blur radii, + // the radii of the corners, and then 1 pixel to draw the side tiles. + IntSize smallBufferSize = IntSize(sideTileWidth + extraWidthFromCornerRadii, + sideTileWidth + extraHeightFromCornerRadii); + + if ((smallBufferSize.width() > shadowBufferSize.width()) || (smallBufferSize.height() > shadowBufferSize.height()) || (blurRadius <= 0)) { + // Create suitably-sized ImageBuffer to hold the shadow. + OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); + if (!shadowBuffer) + return; + + // Draw shadow into a new ImageBuffer. + cairo_t* shadowContext = shadowBuffer->context()->platformContext(); + copyContextProperties(cr, shadowContext); + cairo_translate(shadowContext, -rect.x() + blurRadius, -rect.y() + blurRadius); + cairo_new_path(shadowContext); + cairo_path_t* path = cairo_copy_path(cr); + cairo_append_path(shadowContext, path); + cairo_path_destroy(path); + + setPlatformFill(this, shadowContext, m_common); + + applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, blurRadius); + + return; + } + + OwnPtr<ImageBuffer> smallBuffer = ImageBuffer::create(smallBufferSize); + if (!smallBuffer) + return; + + IntRect smallRect = IntRect(blurRadius, blurRadius, smallBufferSize.width() - radiusTwice, smallBufferSize.height() - radiusTwice); + + // Draw shadow into a new ImageBuffer. + cairo_t* smallBufferContext = smallBuffer->context()->platformContext(); + copyContextProperties(cr, smallBufferContext); + appendWebCorePathToCairoContext(smallBuffer->context()->platformContext(), Path::createRoundedRectangle(smallRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius)); + setPlatformFill(this, smallBufferContext, m_common); + + OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(smallBufferSize); + if (!shadowBuffer) + return; + + smallRect.setSize(smallBufferSize); + + PlatformRefPtr<cairo_surface_t> shadowMask(createShadowMask(smallBuffer.release(), smallRect, blurRadius)); + + cairo_t* shadowContext = shadowBuffer->context()->platformContext(); + setColor(shadowContext, shadowColor); + cairo_mask_surface(shadowContext, shadowMask.get(), 0, 0); + + // Fill the internal part of the shadow. + shadowRect.inflate(-radiusTwice); + if (!shadowRect.isEmpty()) { + cairo_save(cr); + appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(shadowRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius)); + setColor(cr, shadowColor); + cairo_fill(cr); + cairo_restore(cr); + } + shadowRect.inflate(radiusTwice); + + // Draw top side. + FloatRect tileRect = FloatRect(radiusTwice + topLeftRadius.width(), 0, sideTileWidth, radiusTwice); + FloatRect destRect = tileRect; + destRect.move(shadowRect.x(), shadowRect.y()); + destRect.setWidth(shadowRect.width() - topLeftRadius.width() - topRightRadius.width() - blurRadius * 4); + FloatPoint phase = getPhase(destRect, tileRect); + AffineTransform patternTransform; + patternTransform.makeIdentity(); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the bottom side. + tileRect = FloatRect(radiusTwice + bottomLeftRadius.width(), smallBufferSize.height() - radiusTwice, sideTileWidth, radiusTwice); + destRect = tileRect; + destRect.move(shadowRect.x(), shadowRect.y() + radiusTwice + rect.height() - smallBufferSize.height()); + destRect.setWidth(shadowRect.width() - bottomLeftRadius.width() - bottomRightRadius.width() - blurRadius * 4); + phase = getPhase(destRect, tileRect); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the right side. + tileRect = FloatRect(smallBufferSize.width() - radiusTwice, radiusTwice + topRightRadius.height(), radiusTwice, sideTileWidth); + destRect = tileRect; + destRect.move(shadowRect.x() + radiusTwice + rect.width() - smallBufferSize.width(), shadowRect.y()); + destRect.setHeight(shadowRect.height() - topRightRadius.height() - bottomRightRadius.height() - blurRadius * 4); + phase = getPhase(destRect, tileRect); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the left side. + tileRect = FloatRect(0, radiusTwice + topLeftRadius.height(), radiusTwice, sideTileWidth); + destRect = tileRect; + destRect.move(shadowRect.x(), shadowRect.y()); + destRect.setHeight(shadowRect.height() - topLeftRadius.height() - bottomLeftRadius.height() - blurRadius * 4); + phase = FloatPoint(destRect.x() - tileRect.x(), destRect.y() - tileRect.y()); + shadowBuffer->drawPattern(this, tileRect, patternTransform, + phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the top left corner. + tileRect = FloatRect(0, 0, radiusTwice + topLeftRadius.width(), radiusTwice + topLeftRadius.height()); + destRect = tileRect; + destRect.move(shadowRect.x(), shadowRect.y()); + phase = getPhase(destRect, tileRect); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the top right corner. + tileRect = FloatRect(smallBufferSize.width() - radiusTwice - topRightRadius.width(), 0, radiusTwice + topRightRadius.width(), radiusTwice + topRightRadius.height()); + destRect = tileRect; + destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y()); + phase = getPhase(destRect, tileRect); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the bottom right corner. + tileRect = FloatRect(smallBufferSize.width() - radiusTwice - bottomRightRadius.width(), smallBufferSize.height() - radiusTwice - bottomRightRadius.height(), radiusTwice + bottomRightRadius.width(), radiusTwice + bottomRightRadius.height()); + destRect = tileRect; + destRect.move(shadowRect.x() + rect.width() - smallBufferSize.width() + radiusTwice, shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice); + phase = getPhase(destRect, tileRect); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); + + // Draw the bottom left corner. + tileRect = FloatRect(0, smallBufferSize.height() - radiusTwice - bottomLeftRadius.height(), radiusTwice + bottomLeftRadius.width(), radiusTwice + bottomLeftRadius.height()); + destRect = tileRect; + destRect.move(shadowRect.x(), shadowRect.y() + rect.height() - smallBufferSize.height() + radiusTwice); + phase = getPhase(destRect, tileRect); + shadowBuffer->drawPattern(this, tileRect, patternTransform, phase, colorSpace, CompositeSourceOver, destRect); +#endif +} + void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) @@ -1227,7 +1443,12 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft, cairo_save(cr); appendWebCorePathToCairoContext(cr, Path::createRoundedRectangle(r, topLeft, topRight, bottomLeft, bottomRight)); setColor(cr, color); - drawPathShadow(this, m_common, true, false); + AffineTransform transform = this->getCTM(); + // drawTiledShadow still does not work with rotations. + if (transform.isIdentityOrTranslationOrFlipped()) + drawTiledShadow(r, topLeft, topRight, bottomLeft, bottomRight, colorSpace); + else + drawPathShadow(this, m_common, true, false); cairo_fill(cr); cairo_restore(cr); } diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index d9eb5e6..904e819 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -135,14 +135,14 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo // Draw the shadow #if ENABLE(FILTERS) - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { + if (context->getShadow(shadowOffset, shadowBlur, shadowColor)) { IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; - context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowSize, shadowBlur); + context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowOffset, shadowBlur); shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f); //draw shadow into a new ImageBuffer @@ -153,7 +153,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height()); cairo_fill(shadowContext); - context->createPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); + context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); } #endif diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index df14f9d..c4008cc 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -34,6 +34,7 @@ #include <CoreGraphics/CGBitmapContext.h> #include <CoreGraphics/CGContext.h> +#include <CoreGraphics/CGDataProvider.h> #include <CoreGraphics/CGImage.h> #include <wtf/RetainPtr.h> @@ -48,62 +49,108 @@ bool GraphicsContext3D::getImageData(Image* image, { if (!image) return false; - CGImageRef cgImage = image->nativeImageForCurrentFrame(); + CGImageRef cgImage; + RetainPtr<CGImageRef> decodedImage; + if (image->data()) { + ImageSource decoder(false); + decoder.setData(image->data(), true); + if (!decoder.frameCount()) + return false; + decodedImage = decoder.createFrameAtIndex(0); + cgImage = decodedImage.get(); + } else + cgImage = image->nativeImageForCurrentFrame(); if (!cgImage) return false; - int width = CGImageGetWidth(cgImage); - int height = CGImageGetHeight(cgImage); - // FIXME: we should get rid of this temporary copy where possible. - int tempRowBytes = width * 4; - Vector<uint8_t> tempVector; - tempVector.resize(height * tempRowBytes); - // 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. - CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage); - bool releaseColorSpace = false; - CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); - switch (colorSpaceModel) { - case kCGColorSpaceModelMonochrome: - case kCGColorSpaceModelRGB: - case kCGColorSpaceModelCMYK: - case kCGColorSpaceModelLab: - case kCGColorSpaceModelDeviceN: + size_t width = CGImageGetWidth(cgImage); + size_t height = CGImageGetHeight(cgImage); + if (!width || !height || CGImageGetBitsPerComponent(cgImage) != 8) + return false; + size_t componentsPerPixel = CGImageGetBitsPerPixel(cgImage) / 8; + SourceDataFormat srcDataFormat = kSourceFormatRGBA8; + AlphaOp neededAlphaOp = kAlphaDoNothing; + switch (CGImageGetAlphaInfo(cgImage)) { + case kCGImageAlphaPremultipliedFirst: + case kCGImageAlphaFirst: + case kCGImageAlphaNoneSkipFirst: + return false; + case kCGImageAlphaPremultipliedLast: + // This is a special case for texImage2D with HTMLCanvasElement input, + // in which case image->data() should be null. + ASSERT(!image->data()); + if (!premultiplyAlpha) + neededAlphaOp = kAlphaDoUnmultiply; + switch (componentsPerPixel) { + case 2: + srcDataFormat = kSourceFormatRA8; + break; + case 4: + srcDataFormat = kSourceFormatRGBA8; + break; + default: + return false; + } break; - default: - colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear); - releaseColorSpace = true; + case kCGImageAlphaLast: + if (premultiplyAlpha) + neededAlphaOp = kAlphaDoPremultiply; + switch (componentsPerPixel) { + case 1: + srcDataFormat = kSourceFormatA8; + break; + case 2: + srcDataFormat = kSourceFormatRA8; + break; + case 4: + srcDataFormat = kSourceFormatRGBA8; + break; + default: + return false; + } break; - } - CGContextRef tempContext = CGBitmapContextCreate(tempVector.data(), - width, height, 8, tempRowBytes, - colorSpace, - // FIXME: change this! - kCGImageAlphaPremultipliedLast); - if (releaseColorSpace) - CGColorSpaceRelease(colorSpace); - if (!tempContext) + case kCGImageAlphaNoneSkipLast: + switch (componentsPerPixel) { + case 2: + srcDataFormat = kSourceFormatRA8; + break; + case 4: + srcDataFormat = kSourceFormatRGBA8; + break; + default: + return false; + } + case kCGImageAlphaNone: + switch (componentsPerPixel) { + case 1: + srcDataFormat = kSourceFormatR8; + break; + case 3: + srcDataFormat = kSourceFormatRGB8; + break; + default: + return false; + } + break; + default: return false; - CGContextSetBlendMode(tempContext, kCGBlendModeCopy); - CGContextDrawImage(tempContext, - CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), - cgImage); - CGContextRelease(tempContext); - // Pack the pixel data into the output vector. - unsigned long componentsPerPixel, bytesPerComponent; - if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) + } + RetainPtr<CFDataRef> pixelData; + pixelData.adoptCF(CGDataProviderCopyData(CGImageGetDataProvider(cgImage))); + if (!pixelData) return false; - int rowBytes = width * componentsPerPixel * bytesPerComponent; - outputVector.resize(height * rowBytes); - CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage); - bool hasAlphaChannel = (info != kCGImageAlphaNone - && info != kCGImageAlphaNoneSkipLast - && info != kCGImageAlphaNoneSkipFirst); - AlphaOp neededAlphaOp = kAlphaDoNothing; - if (!premultiplyAlpha && hasAlphaChannel) - // FIXME: must fetch the image data before the premultiplication step. - neededAlphaOp = kAlphaDoUnmultiply; - return packPixels(tempVector.data(), kSourceFormatRGBA8, width, height, 0, - format, type, neededAlphaOp, outputVector.data()); + const UInt8* rgba = CFDataGetBytePtr(pixelData.get()); + outputVector.resize(width * height * 4); + unsigned int srcUnpackAlignment = 0; + size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); + unsigned int padding = bytesPerRow - componentsPerPixel * width; + if (padding) { + srcUnpackAlignment = padding + 1; + while (bytesPerRow % srcUnpackAlignment) + ++srcUnpackAlignment; + } + bool rt = packPixels(rgba, srcDataFormat, width, height, srcUnpackAlignment, + format, type, neededAlphaOp, outputVector.data()); + return rt; } void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context) diff --git a/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h new file mode 100644 index 0000000..e1fb740 --- /dev/null +++ b/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/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm new file mode 100644 index 0000000..a7ec03a --- /dev/null +++ b/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -0,0 +1,217 @@ +/* + * 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, ATSUFontID& fontID) +{ + outNSFont = nsFont; + cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); + MemoryActivatedFont* memFont = 0; + if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortFont(cgFont)) { + // Release old CGFontRef since it points at the LastResort font which we don't want. + CFRelease(cgFont); + cgFont = 0; + + // Font loading was blocked by the Sandbox. + 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); + } + } + + if (memFont) { + fontID = m_inMemoryFont->atsFontRef(); + } else { + fontID = CTFontGetPlatformFont(toCTFontRef(outNSFont), 0); + } +} + +} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index 5b8bad3..78b7517 100644 --- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -273,10 +273,10 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, // If there is a non-blur shadow and both the fill color and shadow color // are opaque, handle without skia. - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (m_graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor)) { + if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor)) { // 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); @@ -285,7 +285,7 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, 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 + shadowSize.width(), y + shadowSize.height(), ETO_GLYPH_INDEX, 0, reinterpret_cast<const wchar_t*>(&glyphs[0]), numGlyphs, &advances[0]); + 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); } @@ -483,15 +483,15 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, // If there is a non-blur shadow and both the fill color and shadow color // are opaque, handle without skia. - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) { + if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor) && 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()) + shadowSize.width(), - static_cast<int>(point.y() - ascent()) + shadowSize.height(), from, to); + state.draw(graphicsContext, hdc, static_cast<int>(point.x()) + shadowOffset.width(), + static_cast<int>(point.y() - ascent()) + shadowOffset.height(), from, to); SetTextColor(hdc, savedTextColor); } diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm deleted file mode 100644 index ad7ebba..0000000 --- a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumMac.mm +++ /dev/null @@ -1,458 +0,0 @@ -/* - * This file is part of the internal font implementation. - * - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (c) 2010 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -// This file is a clone of platform/graphics/mac/FontPlatformDataMac.mm. -// Because we want to support loading fonts between processes in the face of -// font loading being blocked by the sandbox, we must maintain a fork. -// Please maintain this file by performing parallel changes to it. -// -// The only changes from FontPlatformDataMac should be: -// - The functions at the top of this file for loading and caching fonts -// cross-process. -// - Changes to FontPlatformData::FontPlatformData(NSFont,bool,bool) -// - Changes to FontPlatformData::setFont() -// - Changes to FontPlatformData::~FontPlatformData() -// - Calls to refMemoryFont() in FontPlatformData::operator= and copy -// constructor. -// -// All changes are marked with "Start/End Chromium Change" -// -// For all other differences, if it was introduced in this file, then the -// maintainer forgot to include it in the list; otherwise it is an update that -// should have been applied to this file but was not. - - -// Start Chromium Change -#import "config.h" -#import "../graphics/mac/FontPlatformData.h" - -#import "ChromiumBridge.h" -#import "PlatformString.h" -#import "WebCoreSystemInterface.h" -#import <AppKit/NSFont.h> -#import <wtf/HashMap.h> -#import <wtf/RefCounted.h> -#import <wtf/RetainPtr.h> -#import <wtf/Vector.h> - -namespace WebCore { - -namespace { - -class MemoryActivatedFont; -typedef HashMap<ATSFontRef, MemoryActivatedFont*> FontRefMemoryFontHash; -typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash; - -// On 10.5, font loading is not blocked by the sandbox and thus there is no -// need for the cross-process font loading mechanim. -// On system versions >=10.6 cross-process font loading is required. -bool OutOfProcessFontLoadingEnabled() -{ - static SInt32 systemVersion = 0; - if (!systemVersion) { - if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr) - return false; - } - - return systemVersion >= 0x1060; -} - -FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef() -{ - DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ()); - return srcFontRefCache; -} - -FontRefMemoryFontHash& fontCacheByActualFontRef() -{ - DEFINE_STATIC_LOCAL(FontRefMemoryFontHash, realFontRefCache, ()); - return realFontRefCache; -} - -ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont) -{ - ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0); - if (!fontRef) - return kATSFontContainerRefUnspecified; - ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified; - if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr) - return kATSFontContainerRefUnspecified; - return fontContainer; -} - -// MemoryActivatedFont encapsulates a font loaded from another process and -// activated from memory. -// -// Responsibilities: -// * Holder for the CGFontRef & ATSFontRef belonging to the activated font. -// * Responsible for unloading the font container when done. -// -// Memory Management: -// The class is reference counted, with each instance of FontPlatformData that -// uses this class holding a reference to it. -// Entries in 2 hashes are maintained internally to allow quick lookup -// of existing instances for reuse: -// - fontCacheBySrcFontContainerRef() - key is the ATSFontContainerRef -// corresponding to the *original in-process NSFont* whose loading was blocked -// by the sandbox. -// This is needed to allow lookup of a pre-existing MemoryActivatedFont when -// creating a new FontPlatformData object. -// - fontCacheByActualFontRef() - key is the ATSFontRef corresponding to the -// *new in-memory font* that we got from the browser process. -// This is needed so that a FontPlatformData object can refer back to the -// MemoryActivatedFont it's using. Currently this is only needed to release -// the font on FontPlatformData destruction. -// -// Assumptions: -// This code assumes that an ATSFontRef is a unique identifier tied to an -// activated font. i.e. After we activate a font, its ATSFontRef doesn't -// change. -// It also assumes that the ATSFoncontainerRef for two in-memory NSFonts that -// correspond to the same on-disk font file are always the same and don't change -// with time. -// -// Flushing caches: -// When the system notifies us of a system font cache flush, all FontDataCache -// objects are destroyed. This should in turn dereference all -// MemoryActivatedFonts and thus unload all in-memory fonts. -class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> { -public: - // srcFontRef - ATSFontRef belonging to the NSFont object that failed to - // load in-process. - // container - a font container corresponding to an identical font that - // we loaded cross-process. - MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container) - : m_fontContainer(container) - , m_atsFontRef(kATSFontRefUnspecified) - , m_srcFontContainerRef(srcFontContainerRef) - { - if (!container) - return; - - // Count the number of fonts in the container. - ItemCount fontCount = 0; - OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0, 0, &fontCount); - if (err != noErr || fontCount < 1) - return; - - // For now always assume that we want the first font in the container. - ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef, 0); - - if (!m_atsFontRef) - return; - - // Cache CGFont representation of the font. - m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef)); - - if (!m_cgFont.get()) - return; - - // Add ourselves to caches. - fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this); - fontCacheByActualFontRef().add(m_atsFontRef, this); - } - - // Get cached CGFontRef corresponding to the in-memory font. - CGFontRef cgFont() - { - return m_cgFont.get(); - } - - // Get cached ATSFontRef corresponding to the in-memory font. - ATSFontRef atsFontRef() - { - return m_atsFontRef; - } - - // Destructor - Unload font container from memory and remove ourselves - // from hashes. - ~MemoryActivatedFont() - { - if (m_cgFont.get()) { // Object construction succeeded. - // First remove ourselves from the caches. - ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef)); - ASSERT(fontCacheByActualFontRef().contains(m_atsFontRef)); - - fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef); - fontCacheByActualFontRef().remove(m_atsFontRef); - - // Make sure the CGFont is destroyed before its font container. - m_cgFont.releaseRef(); - } - - if (m_fontContainer != kATSFontContainerRefUnspecified) - ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault); - } - -private: - ATSFontContainerRef m_fontContainer; - WTF::RetainPtr<CGFontRef> m_cgFont; - ATSFontRef m_atsFontRef; - ATSFontContainerRef m_srcFontContainerRef; -}; - -// The only way we can tell that an in-process font has failed to load -// is if CTFontCopyGraphicsFont() returns the LastResort font. -bool isLastResortFont(CGFontRef cgFont) -{ - NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont); - return [fontName isEqualToString:@"LastResort"]; -} - -// Given an in-process font which has failed to load, return a -// MemoryActivatedFont* corresponding to an in-memory representation of the -// same font loaded from the browser process. -// The caller is responsbile for calling derefMemoryFont() on the ATSFontRef -// of the returned font. -// On failure this function returns 0, in which case the caller doesn't need -// to perform any additional cleanup. -MemoryActivatedFont* loadFontFromBrowserProcess(NSFont* nsFont) -{ - ATSFontContainerRef container; - // Send cross-process request to load font. - if (!ChromiumBridge::loadFont(nsFont, &container)) - return 0; - - ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont); - if (!srcFontContainerRef) { - ATSFontDeactivate(container, 0, kATSOptionFlagsDefault); - return 0; - } - - MemoryActivatedFont* font = fontCacheBySrcFontContainerRef().get(srcFontContainerRef); - if (!font) { - font = new MemoryActivatedFont(srcFontContainerRef, container); - if (!font->cgFont()) { - delete font; - return 0; - } - } else { - font->ref(); - } - - return font; -} - -// deref() the MemoryActivatedFont corresponding to the given ATSFontRef. If no -// corresponding MemoryActivatedFont object exists, no action is performed. -void derefMemoryFont(ATSFontRef fontRef) -{ - if (fontRef == kATSFontRefUnspecified) - return; - MemoryActivatedFont* font = fontCacheByActualFontRef().get(fontRef); - if (font) - font->deref(); -} - -// ref() the MemoryActivatedFont corresponding to the given ATSFontRef. If no -// corresponding MemoryActivatedFont object exists, no action is performed. -void refMemoryFont(ATSFontRef fontRef) -{ - if (fontRef == kATSFontRefUnspecified) - return; - MemoryActivatedFont* font = fontCacheByActualFontRef().get(fontRef); - if (font) - font->ref(); -} - -// Given an NSFont, try to load a representation of that font into the cgFont -// parameter. If loading is blocked by the sandbox, the font may be loaded -// cross-process. -// If sandbox loading also fails, a fallback font is loaded. -// -// Considerations: -// * cgFont must be CFReleas()ed by the caller when done. -// -// Parameters: -// * nsFont - The font we wish to load. -// * fontSize - point size of the font we wish to load. -// * outNSFont - The font that was actually loaded, may be different from nsFont -// if a fallback font was used. -// * cgFont - on output this contains the CGFontRef corresponding to the NSFont -// that was picked in the end. The caller is responsible for calling -// CFRelease() on this parameter when done with it. -// * fontID - on output, the ID corresponding to nsFont. -void loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont, ATSUFontID& fontID) -{ - outNSFont = nsFont; - cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); - MemoryActivatedFont* memFont = 0; - if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortFont(cgFont)) { - // Release old CGFontRef since it points at the LastResort font which we don't want. - CFRelease(cgFont); - cgFont = 0; - - // Font loading was blocked by the Sandbox. - memFont = loadFontFromBrowserProcess(outNSFont); - if (memFont) { - cgFont = memFont->cgFont(); - - // Need to add an extra retain so output semantics of this function - // are consistent. - CFRetain(cgFont); - } else { - // If we still can't load the font, then return Times, - // rather than the LastResort font. - outNSFont = [NSFont fontWithName:@"Times" size:fontSize]; - cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); - } - } - - if (memFont) { - fontID = memFont->atsFontRef(); - } else { - fontID = CTFontGetPlatformFont(toCTFontRef(outNSFont), 0); - } -} - -} // namespace -// End Chromium Change - -FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool syntheticOblique) - : m_syntheticBold(syntheticBold) - , m_syntheticOblique(syntheticOblique) - , m_font(nsFont) -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait) -#else - , m_isColorBitmapFont(false) -#endif -{ -// Start Chromium Change - m_size = nsFont ? [nsFont pointSize] : 0.0f; - CGFontRef cgFont = 0; - NSFont* loadedFont = 0; - loadFont(nsFont, m_size, loadedFont, cgFont, m_atsuFontID); - m_font = loadedFont; - if (m_font) - CFRetain(m_font); - m_cgFont.adoptCF(cgFont); -// End Chromium Change -} - -FontPlatformData::FontPlatformData(const FontPlatformData& f) -{ - m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font; - - m_syntheticBold = f.m_syntheticBold; - m_syntheticOblique = f.m_syntheticOblique; - m_size = f.m_size; - m_cgFont = f.m_cgFont; - m_atsuFontID = f.m_atsuFontID; - m_isColorBitmapFont = f.m_isColorBitmapFont; - // Start Chromium Change - refMemoryFont(m_atsuFontID); - // End Chromium Change -} - -FontPlatformData::~FontPlatformData() -{ - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); - - // Start Chromium Change - derefMemoryFont(m_atsuFontID); - // End Chromium Change -} - -const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) -{ - m_syntheticBold = f.m_syntheticBold; - m_syntheticOblique = f.m_syntheticOblique; - m_size = f.m_size; - m_cgFont = f.m_cgFont; - m_atsuFontID = f.m_atsuFontID; - if (m_font == f.m_font) - return *this; - if (f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1)) - CFRetain(f.m_font); - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); - m_font = f.m_font; - m_isColorBitmapFont = f.m_isColorBitmapFont; - // Start Chromium Change - refMemoryFont(m_atsuFontID); - // End Chromium Change - return *this; -} - -void FontPlatformData::setFont(NSFont *font) -{ - if (m_font == font) - return; - if (font) - CFRetain(font); - if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) - CFRelease(m_font); - m_font = font; - m_size = font ? [font pointSize] : 0.0f; - - // Start Chromium Change - CGFontRef cgFont = 0; - NSFont* loadedFont = 0; - loadFont(m_font, m_size, loadedFont, cgFont, m_atsuFontID); - - // If loadFont replaced m_font with a fallback font, then release the - // previous font to counter the retain above. Then retain the new font. - if (loadedFont != m_font) { - CFRelease(m_font); - m_font = loadedFont; - CFRetain(m_font); - } - m_cgFont.adoptCF(cgFont); -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait; -#endif - // End Chromium Change -} - -bool FontPlatformData::roundsGlyphAdvances() const -{ - return [m_font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode; -} - -bool FontPlatformData::allowsLigatures() const -{ - return ![[m_font coveredCharacterSet] characterIsMember:'a']; -} - -#if USE(CORE_TEXT) -CTFontRef FontPlatformData::ctFont() const -{ - if (m_font) - return toCTFontRef(m_font); - if (!m_CTFont) - m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0)); - return m_CTFont.get(); -} -#endif // USE(CORE_TEXT) - -#ifndef NDEBUG -String FontPlatformData::description() const -{ - RetainPtr<CFStringRef> cgFontDescription(AdoptCF, CFCopyDescription(cgFont())); - return String(cgFontDescription.get()) + " " + String::number(m_size) + (m_syntheticBold ? " synthetic bold" : "") + (m_syntheticOblique ? " synthetic oblique" : ""); -} -#endif - -} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index c0cb87c..82d4c0b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -30,15 +30,15 @@ #include "config.h" -#if USE(GLES2_RENDERING) - #include "GLES2Canvas.h" #include "FloatRect.h" -#include "GLES2Texture.h" #include "GraphicsContext3D.h" #include "IntRect.h" #include "PlatformString.h" +#include "SolidFillShader.h" +#include "TexShader.h" +#include "Texture.h" #define _USE_MATH_DEFINES #include <math.h> @@ -48,19 +48,6 @@ namespace WebCore { -static inline void affineTo3x3(const AffineTransform& transform, float mat[9]) -{ - mat[0] = transform.a(); - mat[1] = transform.b(); - mat[2] = 0.0f; - mat[3] = transform.c(); - mat[4] = transform.d(); - mat[5] = 0.0f; - mat[6] = transform.e(); - mat[7] = transform.f(); - mat[8] = 1.0f; -} - struct GLES2Canvas::State { State() : m_fillColor(0, 0, 0, 255) @@ -76,18 +63,10 @@ struct GLES2Canvas::State { GLES2Canvas::GLES2Canvas(GraphicsContext3D* context, const IntSize& size) : m_context(context) - , m_quadVertices(0) - , m_simpleProgram(0) - , m_texProgram(0) - , m_simpleMatrixLocation(-1) - , m_simpleColorLocation(-1) - , m_simplePositionLocation(-1) - , m_texMatrixLocation(-1) - , m_texTexMatrixLocation(-1) - , m_texSamplerLocation(-1) - , m_texAlphaLocation(-1) - , m_texPositionLocation(-1) , m_state(0) + , m_quadVertices(0) + , m_solidFillShader(SolidFillShader::create(context)) + , m_texShader(TexShader::create(context)) { m_flipMatrix.translate(-1.0f, 1.0f); m_flipMatrix.scale(2.0f / size.width(), -2.0f / size.height()); @@ -105,8 +84,6 @@ GLES2Canvas::GLES2Canvas(GraphicsContext3D* context, const IntSize& size) GLES2Canvas::~GLES2Canvas() { - m_context->deleteProgram(m_simpleProgram); - m_context->deleteProgram(m_texProgram); m_context->deleteBuffer(m_quadVertices); } @@ -131,23 +108,11 @@ void GLES2Canvas::fillRect(const FloatRect& rect, const Color& color, ColorSpace m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices()); - m_context->useProgram(getSimpleProgram()); - - float rgba[4]; - color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); - m_context->uniform4f(m_simpleColorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]); - AffineTransform matrix(m_flipMatrix); matrix.multLeft(m_state->m_ctm); matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); - float mat[9]; - affineTo3x3(matrix, mat); - m_context->uniformMatrix3fv(m_simpleMatrixLocation, false /*transpose*/, mat, 1 /*count*/); - - m_context->vertexAttribPointer(m_simplePositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); - - m_context->enableVertexAttribArray(m_simplePositionLocation); + m_solidFillShader->use(matrix, color); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); } @@ -200,49 +165,35 @@ void GLES2Canvas::restore() m_state = &m_stateStack.last(); } -void GLES2Canvas::drawTexturedRect(GLES2Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace colorSpace, CompositeOperator compositeOp) +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(GLES2Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp) +void GLES2Canvas::drawTexturedRect(Texture* texture, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform, float alpha, ColorSpace colorSpace, CompositeOperator compositeOp) { applyCompositeOperator(compositeOp); m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, getQuadVertices()); checkGLError("glBindBuffer"); - m_context->useProgram(getTexProgram()); - checkGLError("glUseProgram"); - - m_context->activeTexture(GraphicsContext3D::TEXTURE0); - - m_context->uniform1i(m_texSamplerLocation, 0); - checkGLError("glUniform1i"); - - m_context->uniform1f(m_texAlphaLocation, alpha); - checkGLError("glUniform1f for alpha"); - - m_context->vertexAttribPointer(m_texPositionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); - - m_context->enableVertexAttribArray(m_texPositionLocation); - const TilingData& tiles = texture->tiles(); IntRect tileIdxRect = tiles.overlappedTileIndices(srcRect); 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); + drawTexturedRectTile(texture, tiles.tileIndex(x, y), srcRect, dstRect, transform, alpha); } } -void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform& transform) +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(); + m_context->activeTexture(GraphicsContext3D::TEXTURE0); texture->bindTile(tile); FloatRect srcRectClippedInTileSpace; @@ -255,19 +206,13 @@ void GLES2Canvas::drawTexturedRectTile(GLES2Texture* texture, int tile, const Fl matrix.multLeft(transform); matrix.translate(dstRectIntersected.x(), dstRectIntersected.y()); matrix.scale(dstRectIntersected.width(), dstRectIntersected.height()); - float mat[9]; - affineTo3x3(matrix, mat); - m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, mat, 1 /*count*/); - checkGLError("glUniformMatrix3fv"); AffineTransform texMatrix; texMatrix.scale(1.0f / tileBoundsWithBorder.width(), 1.0f / tileBoundsWithBorder.height()); texMatrix.translate(srcRectClippedInTileSpace.x(), srcRectClippedInTileSpace.y()); texMatrix.scale(srcRectClippedInTileSpace.width(), srcRectClippedInTileSpace.height()); - float texMat[9]; - affineTo3x3(texMatrix, texMat); - m_context->uniformMatrix3fv(m_texTexMatrixLocation, false /*transpose*/, texMat, 1 /*count*/); - checkGLError("glUniformMatrix3fv"); + + m_texShader->use(matrix, texMatrix, 0, alpha); m_context->drawArrays(GraphicsContext3D::TRIANGLE_STRIP, 0, 4); checkGLError("glDrawArrays"); @@ -354,131 +299,21 @@ unsigned GLES2Canvas::getQuadVertices() return m_quadVertices; } - -static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource) +Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height) { - unsigned shader = context->createShader(type); - if (!shader) - return 0; - - String shaderSourceStr(shaderSource); - context->shaderSource(shader, shaderSourceStr); - context->compileShader(shader); - int compileStatus; - context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compileStatus); - if (!compileStatus) { - String infoLog = context->getShaderInfoLog(shader); - LOG_ERROR(infoLog.utf8().data()); - context->deleteShader(shader); - return 0; - } - return shader; -} - -unsigned GLES2Canvas::getSimpleProgram() -{ - if (!m_simpleProgram) { - unsigned vertexShader = loadShader(m_context, GraphicsContext3D::VERTEX_SHADER, - "uniform mat3 matrix;\n" - "uniform vec4 color;\n" - "attribute vec3 position;\n" - "void main() {\n" - " gl_Position = vec4(matrix * position, 1.0);\n" - "}\n"); - if (!vertexShader) - return 0; - unsigned fragmentShader = loadShader(m_context, GraphicsContext3D::FRAGMENT_SHADER, - "precision mediump float;\n" - "uniform mat3 matrix;\n" - "uniform vec4 color;\n" - "void main() {\n" - " gl_FragColor = color;\n" - "}\n"); - if (!fragmentShader) - return 0; - m_simpleProgram = m_context->createProgram(); - if (!m_simpleProgram) - return 0; - m_context->attachShader(m_simpleProgram, vertexShader); - m_context->attachShader(m_simpleProgram, fragmentShader); - m_context->linkProgram(m_simpleProgram); - int linkStatus; - m_context->getProgramiv(m_simpleProgram, GraphicsContext3D::LINK_STATUS, &linkStatus); - if (!linkStatus) { - m_context->deleteProgram(m_simpleProgram); - m_simpleProgram = 0; - } - m_context->deleteShader(vertexShader); - m_context->deleteShader(fragmentShader); - m_simplePositionLocation = m_context->getAttribLocation(m_simpleProgram, "position"); - m_simpleMatrixLocation = m_context->getUniformLocation(m_simpleProgram, "matrix"); - m_simpleColorLocation = m_context->getUniformLocation(m_simpleProgram, "color"); - } - return m_simpleProgram; -} - -unsigned GLES2Canvas::getTexProgram() -{ - if (!m_texProgram) { - unsigned vertexShader = loadShader(m_context, GraphicsContext3D::VERTEX_SHADER, - "uniform mat3 matrix;\n" - "uniform mat3 texMatrix;\n" - "attribute vec3 position;\n" - "varying vec3 texCoord;\n" - "void main() {\n" - " texCoord = texMatrix * position;\n" - " gl_Position = vec4(matrix * position, 1.0);\n" - "}\n"); - if (!vertexShader) - return 0; - unsigned fragmentShader = loadShader(m_context, GraphicsContext3D::FRAGMENT_SHADER, - "precision mediump float;\n" - "uniform sampler2D sampler;\n" - "uniform float alpha;\n" - "varying vec3 texCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(sampler, texCoord.xy)* vec4(alpha);\n" - "}\n"); - if (!fragmentShader) - return 0; - m_texProgram = m_context->createProgram(); - if (!m_texProgram) - return 0; - m_context->attachShader(m_texProgram, vertexShader); - m_context->attachShader(m_texProgram, fragmentShader); - m_context->linkProgram(m_texProgram); - int linkStatus; - m_context->getProgramiv(m_texProgram, GraphicsContext3D::LINK_STATUS, &linkStatus); - if (!linkStatus) { - m_context->deleteProgram(m_texProgram); - m_texProgram = 0; - } - m_context->deleteShader(vertexShader); - m_context->deleteShader(fragmentShader); - m_texMatrixLocation = m_context->getUniformLocation(m_texProgram, "matrix"); - m_texSamplerLocation = m_context->getUniformLocation(m_texProgram, "sampler"); - m_texTexMatrixLocation = m_context->getUniformLocation(m_texProgram, "texMatrix"); - m_texPositionLocation = m_context->getAttribLocation(m_texProgram, "position"); - m_texAlphaLocation = m_context->getUniformLocation(m_texProgram, "alpha"); - } - return m_texProgram; -} - -GLES2Texture* GLES2Canvas::createTexture(NativeImagePtr ptr, GLES2Texture::Format format, int width, int height) -{ - PassRefPtr<GLES2Texture> texture = m_textures.get(ptr); + PassRefPtr<Texture> texture = m_textures.get(ptr); if (texture) return texture.get(); - texture = GLES2Texture::create(m_context, format, width, height); - GLES2Texture* t = texture.get(); + texture = Texture::create(m_context, format, width, height); + Texture* t = texture.get(); m_textures.set(ptr, texture); return t; } -GLES2Texture* GLES2Canvas::getTexture(NativeImagePtr ptr) +Texture* GLES2Canvas::getTexture(NativeImagePtr ptr) { - PassRefPtr<GLES2Texture> texture = m_textures.get(ptr); + PassRefPtr<Texture> texture = m_textures.get(ptr); return texture ? texture.get() : 0; } @@ -515,4 +350,3 @@ void GLES2Canvas::checkGLError(const char* header) } -#endif diff --git a/WebCore/platform/graphics/chromium/GLES2Canvas.h b/WebCore/platform/graphics/chromium/GLES2Canvas.h index d00510a..f49ac8b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -31,14 +31,12 @@ #ifndef GLES2Canvas_h #define GLES2Canvas_h -#if USE(GLES2_RENDERING) - #include "AffineTransform.h" #include "Color.h" #include "ColorSpace.h" -#include "GLES2Texture.h" #include "GraphicsTypes.h" #include "ImageSource.h" +#include "Texture.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> @@ -49,8 +47,10 @@ namespace WebCore { class Color; class FloatRect; class GraphicsContext3D; +class SolidFillShader; +class TexShader; -typedef HashMap<NativeImagePtr, RefPtr<GLES2Texture> > TextureHashMap; +typedef HashMap<NativeImagePtr, RefPtr<Texture> > TextureHashMap; class GLES2Canvas : public Noncopyable { public: @@ -74,35 +74,25 @@ public: // non-standard functions // These are not standard GraphicsContext functions, and should be pushed // down into a PlatformContextGLES2 at some point. - void drawTexturedRect(GLES2Texture*, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha, ColorSpace, CompositeOperator); - void drawTexturedRect(GLES2Texture*, 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); GraphicsContext3D* context() { return m_context; } - GLES2Texture* createTexture(NativeImagePtr, GLES2Texture::Format, int width, int height); - GLES2Texture* getTexture(NativeImagePtr); + Texture* createTexture(NativeImagePtr, Texture::Format, int width, int height); + Texture* getTexture(NativeImagePtr); private: - void drawTexturedRectTile(GLES2Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&); + void drawTexturedRectTile(Texture* texture, int tile, const FloatRect& srcRect, const FloatRect& dstRect, const AffineTransform&, float alpha); void applyCompositeOperator(CompositeOperator); void checkGLError(const char* header); unsigned getQuadVertices(); - unsigned getSimpleProgram(); - unsigned getTexProgram(); GraphicsContext3D* m_context; struct State; WTF::Vector<State> m_stateStack; State* m_state; unsigned m_quadVertices; - unsigned m_simpleProgram; - unsigned m_texProgram; - int m_simpleMatrixLocation; - int m_simpleColorLocation; - int m_simplePositionLocation; - int m_texMatrixLocation; - int m_texTexMatrixLocation; - int m_texSamplerLocation; - int m_texAlphaLocation; - int m_texPositionLocation; + OwnPtr<SolidFillShader> m_solidFillShader; + OwnPtr<TexShader> m_texShader; AffineTransform m_flipMatrix; TextureHashMap m_textures; CompositeOperator m_lastCompositeOp; // This is the one last set, not necessarily the one in the state stack. @@ -110,6 +100,4 @@ private: } -#endif - #endif // GLES2Canvas_h diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 3553878..6519f1f 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -109,7 +109,7 @@ LayerChromium::SharedValues::SharedValues() "uniform vec4 color; \n" "void main() \n" "{ \n" - " gl_FragColor = color; \n" + " gl_FragColor = vec4(color.xyz * color.w, color.w);\n" "} \n"; m_borderShaderProgram = createShaderProgram(borderVertexShaderString, borderFragmentShaderString); @@ -431,6 +431,37 @@ void LayerChromium::drawDebugBorder() GLC(glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short)))); } +const FloatRect LayerChromium::getDrawRect() const +{ + // Form the matrix used by the shader to map the corners of the layer's + // bounds into the view space. + TransformationMatrix renderMatrix = drawTransform(); + renderMatrix.scale3d(bounds().width(), bounds().height(), 1); + + FloatRect layerRect(-0.5, -0.5, 1, 1); + FloatRect mappedRect = renderMatrix.mapRect(layerRect); + return mappedRect; +} + +// Draws the layer with a single colored shader. This method is used to do +// quick draws into the stencil buffer. +void LayerChromium::drawAsMask() +{ + ASSERT(layerRenderer()); + const SharedValues* sv = layerRenderer()->layerSharedValues(); + ASSERT(sv && sv->initialized()); + layerRenderer()->useShader(sv->borderShaderProgram()); + + // We reuse the border shader here as all we need a single colored shader pass. + // The color specified here is only for debug puproses as typically when we call this + // method, writes to the color channels are disabled. + GLC(glUniform4f(sv->borderShaderColorLocation(), 0, 1 , 0, 0.7)); + + drawTexturedQuad(layerRenderer()->projectionMatrix(), drawTransform(), + bounds().width(), bounds().height(), drawOpacity(), + sv->borderShaderMatrixLocation(), -1); +} + // static void LayerChromium::prepareForDraw(const SharedValues* sv) { diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 0d0d362..ba15088 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -151,6 +151,9 @@ public: bool contentsDirty() { return m_contentsDirty; } + // Returns the rect containtaining this layer in the current view's coordinate system. + const FloatRect getDrawRect() const; + // These methods typically need to be overwritten by derived classes. virtual bool drawsContent() { return false; } virtual void updateContents() { }; @@ -158,6 +161,9 @@ public: void drawDebugBorder(); + // Draws the layer without a texture. This is used for stencil operations. + void drawAsMask(); + // Stores values that are shared between instances of this class that are // associated with the same LayerRendererChromium (and hence the same GL // context). diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index cf23871..50338d2 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -183,9 +183,11 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& // 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(glDisable(GL_DEPTH_TEST)); GLC(glDisable(GL_CULL_FACE)); GLC(glDepthFunc(GL_LEQUAL)); + GLC(glClearStencil(0)); if (m_scrollPosition == IntPoint(-1, -1)) m_scrollPosition = scrollPosition; @@ -299,14 +301,23 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& for (i = 0; i < sublayers.size(); i++) updateLayersRecursive(sublayers[i].get(), matrix, opacity); + m_rootVisibleRect = visibleRect; + // Enable scissoring to avoid rendering composited layers over the scrollbars. GLC(glEnable(GL_SCISSOR_TEST)); - GLC(glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height())); + FloatRect scissorRect(contentRect); + // The scissorRect should not include the scroll offset. + scissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); + scissorToRect(scissorRect); + + // Clear the stencil buffer to 0. + GLC(glClear(GL_STENCIL_BUFFER_BIT)); + // Disable writes to the stencil buffer. + GLC(glStencilMask(0)); // Traverse the layer tree one more time to draw the layers. - m_visibleRect = visibleRect; for (i = 0; i < sublayers.size(); i++) - drawLayersRecursive(sublayers[i].get()); + drawLayersRecursive(sublayers[i].get(), scissorRect); GLC(glDisable(GL_SCISSOR_TEST)); @@ -419,13 +430,35 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr layer->setLayerRenderer(this); } +// Does a quick draw of the given layer into the stencil buffer. If decrement +// is true then it decrements the current stencil values otherwise it increments them. +void LayerRendererChromium::drawLayerIntoStencilBuffer(LayerChromium* layer, bool decrement) +{ + // Enable writes to the stencil buffer and increment the stencil values + // by one for every pixel under the current layer. + GLC(glStencilMask(0xff)); + GLC(glStencilFunc(GL_ALWAYS, 1, 0xff)); + GLenum stencilOp = (decrement ? GL_DECR : GL_INCR); + GLC(glStencilOp(stencilOp, stencilOp, stencilOp)); + + GLC(glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE)); + + layer->drawAsMask(); + + // Disable writes to the stencil buffer. + GLC(glStencilMask(0)); + GLC(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); +} + // Recursively walk the layer tree and draw the layers. -void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) +void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer, const FloatRect& scissorRect) { static bool depthTestEnabledForSubtree = false; + static int currentStencilValue = 0; // Check if the layer falls within the visible bounds of the page. - bool layerVisible = isLayerVisible(layer, layer->drawTransform(), m_visibleRect); + FloatRect layerRect = layer->getDrawRect(); + bool isLayerVisible = scissorRect.intersects(layerRect); // Enable depth testing for this layer and all its descendants if preserves3D is set. bool mustClearDepth = false; @@ -439,9 +472,50 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) } } - if (layerVisible) + if (isLayerVisible) drawLayer(layer); + // FIXME: We should check here if the layer has descendants that draw content + // before we setup for clipping. + FloatRect currentScissorRect = scissorRect; + bool mustResetScissorRect = false; + bool didStencilDraw = false; + if (layer->masksToBounds()) { + // If the layer isn't rotated then we can use scissoring otherwise we need + // to clip using the stencil buffer. + if (layer->drawTransform().isIdentityOrTranslation()) { + currentScissorRect.intersect(layerRect); + if (currentScissorRect != scissorRect) { + scissorToRect(currentScissorRect); + mustResetScissorRect = true; + } + } else if (currentStencilValue < ((1 << m_numStencilBits) - 1)) { + // Clipping using the stencil buffer works as follows: When we encounter + // a clipping layer we increment the stencil buffer values for all the pixels + // the layer touches. As a result 1's will be stored in the stencil buffer for pixels under + // the first clipping layer found in a traversal, 2's for pixels in the intersection + // of two nested clipping layers, etc. When the sublayers of a clipping layer are drawn + // we turn on stencil testing to render only pixels that have the correct stencil + // value (one that matches the value of currentStencilValue). As the recursion unravels, + // we decrement the stencil buffer values for each clipping layer. When the entire layer tree + // is rendered, the stencil values should be all back to zero. An 8 bit stencil buffer + // will allow us up to 255 nested clipping layers which is hopefully enough. + if (!currentStencilValue) + GLC(glEnable(GL_STENCIL_TEST)); + + drawLayerIntoStencilBuffer(layer, false); + + currentStencilValue++; + didStencilDraw = true; + } + } + // Sublayers will render only if the value in the stencil buffer is equal to + // currentStencilValue. + if (didStencilDraw) { + // The sublayers will render only if the stencil test passes. + GLC(glStencilFunc(GL_EQUAL, currentStencilValue, 0xff)); + } + // If we're using depth testing then we need to sort the children in Z to // get the transparency to work properly. if (depthTestEnabledForSubtree) { @@ -456,11 +530,27 @@ void LayerRendererChromium::drawLayersRecursive(LayerChromium* layer) std::stable_sort(sublayerList.begin(), sublayerList.end(), compareLayerZ); for (i = 0; i < sublayerList.size(); i++) - drawLayersRecursive(sublayerList[i]); + drawLayersRecursive(sublayerList[i], currentScissorRect); } else { const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); i++) - drawLayersRecursive(sublayers[i].get()); + drawLayersRecursive(sublayers[i].get(), currentScissorRect); + } + + if (didStencilDraw) { + // Draw into the stencil buffer subtracting 1 for every pixel hit + // effectively removing this mask + drawLayerIntoStencilBuffer(layer, true); + currentStencilValue--; + if (!currentStencilValue) { + // Disable stencil testing. + GLC(glDisable(GL_STENCIL_TEST)); + GLC(glStencilFunc(GL_ALWAYS, 0, 0xff)); + } + } + + if (mustResetScissorRect) { + scissorToRect(scissorRect); } if (mustClearDepth) { @@ -494,6 +584,15 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) 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::scissorToRect(const FloatRect& scissorRect) +{ + // Compute the lower left corner of the scissor rect. + float bottom = std::max((float)m_rootVisibleRect.height() - scissorRect.bottom(), 0.f); + GLC(glScissor(scissorRect.x(), bottom, scissorRect.width(), scissorRect.height())); +} + bool LayerRendererChromium::makeContextCurrent() { return m_gles2Context->makeCurrent(); @@ -565,6 +664,9 @@ bool LayerRendererChromium::initializeSharedObjects() // Get the max texture size supported by the system. GLC(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize)); + // Get the number of bits available in the stencil buffer. + GLC(glGetIntegerv(GL_STENCIL_BITS, &m_numStencilBits)); + m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues()); m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues()); m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues()); diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 24bbe65..8f44afe 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -93,12 +93,16 @@ public: private: void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity); - void drawLayersRecursive(LayerChromium*); + void drawLayersRecursive(LayerChromium*, const FloatRect& scissorRect); void drawLayer(LayerChromium*); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); + void drawLayerIntoStencilBuffer(LayerChromium*, bool decrement); + + void scissorToRect(const FloatRect&); + bool makeContextCurrent(); bool initializeSharedObjects(); @@ -135,10 +139,12 @@ private: IntSize m_rootLayerCanvasSize; - IntRect m_visibleRect; + IntRect m_rootVisibleRect; int m_maxTextureSize; + int m_numStencilBits; + // 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 diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/cocoa/FontPlatformData.h index dc876a8..034e23b 100644 --- a/WebCore/platform/graphics/mac/FontPlatformData.h +++ b/WebCore/platform/graphics/cocoa/FontPlatformData.h @@ -42,7 +42,13 @@ typedef const struct __CTFont* CTFontRef; #include <wtf/Forward.h> #include <wtf/RetainPtr.h> +#if PLATFORM(CHROMIUM) && OS(DARWIN) +#include "CrossProcessFontLoading.h" +#endif + + typedef UInt32 ATSUFontID; +typedef UInt32 ATSFontRef; namespace WebCore { @@ -133,6 +139,15 @@ class FontPlatformData { private: static NSFont *hashTableDeletedFontValue() { return reinterpret_cast<NSFont *>(-1); } + + // Load various data about the font specified by |nsFont| with the size fontSize into the following output paramters: + // Note: Callers should always take into account that for the Chromium port, |outNSFont| isn't necessarily the same + // font as |nsFont|. This because the sandbox may block loading of the original font. + // * outNSFont - The font that was actually loaded, for the Chromium port this may be different than nsFont. + // The caller is responsible for calling CFRelease() on this parameter when done with it. + // * cgFont - CGFontRef representing the input font at the specified point size. + // * fontID - ID of loaded font. + void loadFont(NSFont* nsFont, float fontSize, NSFont*& outNSFont, CGFontRef& cgFont, ATSUFontID& fontID); NSFont *m_font; @@ -147,8 +162,12 @@ private: #endif bool m_isColorBitmapFont; + +#if PLATFORM(CHROMIUM) && OS(DARWIN) + RefPtr<MemoryActivatedFont> m_inMemoryFont; +#endif }; -} +} // namespace WebCore #endif diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm index d905b62..bd49dcc 100644 --- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm +++ b/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm @@ -2,6 +2,7 @@ * This file is part of the internal font implementation. * * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (c) 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -29,11 +30,27 @@ namespace WebCore { +#if PLATFORM(MAC) +void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFontRef& cgFont, ATSUFontID& fontID) +{ + outNSFont = nsFont; +#ifndef BUILDING_ON_TIGER + cgFont = CTFontCopyGraphicsFont(toCTFontRef(nsFont), 0); + fontID = CTFontGetPlatformFont(toCTFontRef(nsFont), 0); +#else + cgFont = wkGetCGFontFromNSFont(nsFont); + fontID = wkGetNSFontATSUFontId(nsFont); +#endif +} +#endif // PLATFORM(MAC) + FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool syntheticOblique) : m_syntheticBold(syntheticBold) , m_syntheticOblique(syntheticOblique) , m_font(nsFont) #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + // FIXME: Chromium: The following code isn't correct for the Chromium port since the sandbox might + // have blocked font loading, in which case we'll only have the real loaded font file after the call to loadFont(). , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait) #else , m_isColorBitmapFont(false) @@ -41,14 +58,18 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool synt { ASSERT_ARG(nsFont, nsFont); - CFRetain(nsFont); m_size = [nsFont pointSize]; + + CGFontRef cgFont = 0; + loadFont(nsFont, m_size, m_font, cgFont, m_atsuFontID); + + if (m_font) + CFRetain(m_font); + #ifndef BUILDING_ON_TIGER - m_cgFont.adoptCF(CTFontCopyGraphicsFont(toCTFontRef(nsFont), 0)); - m_atsuFontID = CTFontGetPlatformFont(toCTFontRef(nsFont), 0); + m_cgFont.adoptCF(cgFont); #else - m_cgFont = wkGetCGFontFromNSFont(nsFont); - m_atsuFontID = wkGetNSFontATSUFontId(nsFont); + m_cgFont = cgFont; #endif } @@ -65,6 +86,9 @@ FontPlatformData::FontPlatformData(const FontPlatformData& f) #if USE(CORE_TEXT) m_CTFont = f.m_CTFont; #endif +#if PLATFORM(CHROMIUM) && OS(DARWIN) + m_inMemoryFont = f.m_inMemoryFont; +#endif } FontPlatformData:: ~FontPlatformData() @@ -91,6 +115,9 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) #if USE(CORE_TEXT) m_CTFont = f.m_CTFont; #endif +#if PLATFORM(CHROMIUM) && OS(DARWIN) + m_inMemoryFont = f.m_inMemoryFont; +#endif return *this; } @@ -107,15 +134,28 @@ void FontPlatformData::setFont(NSFont *font) CFRelease(m_font); m_font = font; m_size = [font pointSize]; + + CGFontRef cgFont = 0; + NSFont* loadedFont = 0; + loadFont(m_font, m_size, loadedFont, cgFont, m_atsuFontID); + +#if PLATFORM(CHROMIUM) && OS(DARWIN) + // If loadFont replaced m_font with a fallback font, then release the + // previous font to counter the retain above. Then retain the new font. + if (loadedFont != m_font) { + CFRelease(m_font); + CFRetain(loadedFont); + m_font = loadedFont; + } +#endif + #ifndef BUILDING_ON_TIGER - m_cgFont.adoptCF(CTFontCopyGraphicsFont(toCTFontRef(font), 0)); - m_atsuFontID = CTFontGetPlatformFont(toCTFontRef(font), 0); + m_cgFont.adoptCF(cgFont); #else - m_cgFont = wkGetCGFontFromNSFont(font); - m_atsuFontID = wkGetNSFontATSUFontId(font); + m_cgFont = cgFont; #endif #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(font)) & kCTFontColorGlyphsTrait; + m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(m_font)) & kCTFontColorGlyphsTrait; #endif #if USE(CORE_TEXT) m_CTFont = 0; diff --git a/WebCore/platform/graphics/gpu/Shader.cpp b/WebCore/platform/graphics/gpu/Shader.cpp new file mode 100644 index 0000000..59c50a7 --- /dev/null +++ b/WebCore/platform/graphics/gpu/Shader.cpp @@ -0,0 +1,111 @@ +/* + * 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 "Shader.h" + +#include "AffineTransform.h" +#include "GraphicsContext3D.h" + +#include <wtf/text/CString.h> + +namespace WebCore { + +// static +void Shader::affineTo3x3(const AffineTransform& transform, float mat[9]) +{ + mat[0] = transform.a(); + mat[1] = transform.b(); + mat[2] = 0.0f; + mat[3] = transform.c(); + mat[4] = transform.d(); + mat[5] = 0.0f; + mat[6] = transform.e(); + mat[7] = transform.f(); + mat[8] = 1.0f; +} + +// static +unsigned Shader::loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource) +{ + unsigned shader = context->createShader(type); + if (!shader) + return 0; + + String shaderSourceStr(shaderSource); + context->shaderSource(shader, shaderSourceStr); + context->compileShader(shader); + int compileStatus; + context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compileStatus); + if (!compileStatus) { + String infoLog = context->getShaderInfoLog(shader); + LOG_ERROR("%s", infoLog.utf8().data()); + context->deleteShader(shader); + return 0; + } + return shader; +} + +// static +unsigned Shader::loadProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource) +{ + unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource); + if (!vertexShader) + return 0; + unsigned fragmentShader = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShaderSource); + if (!fragmentShader) + return 0; + unsigned program = context->createProgram(); + if (!program) + return 0; + context->attachShader(program, vertexShader); + context->attachShader(program, fragmentShader); + context->linkProgram(program); + int linkStatus; + context->getProgramiv(program, GraphicsContext3D::LINK_STATUS, &linkStatus); + if (!linkStatus) + context->deleteProgram(program); + context->deleteShader(vertexShader); + context->deleteShader(fragmentShader); + return program; +} + +Shader::Shader(GraphicsContext3D* context, unsigned program) + : m_context(context) + , m_program(program) +{ +} + +Shader::~Shader() +{ + m_context->deleteProgram(m_program); +} + +} diff --git a/WebCore/platform/graphics/gpu/Shader.h b/WebCore/platform/graphics/gpu/Shader.h new file mode 100644 index 0000000..e5bd8de --- /dev/null +++ b/WebCore/platform/graphics/gpu/Shader.h @@ -0,0 +1,58 @@ +/* + * 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 Shader_h +#define Shader_h + +#include <wtf/Noncopyable.h> +#include <wtf/PassOwnPtr.h> + +namespace WebCore { + +class AffineTransform; +class GraphicsContext3D; +class Color; + +class Shader : public Noncopyable { +protected: + Shader(GraphicsContext3D*, unsigned program); + ~Shader(); + + static void affineTo3x3(const AffineTransform&, float mat[9]); + static unsigned loadShader(GraphicsContext3D*, unsigned type, const char* shaderSource); + static unsigned loadProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource); + + GraphicsContext3D* m_context; + unsigned m_program; +}; + +} + +#endif // Shader_h diff --git a/WebCore/platform/graphics/gpu/SolidFillShader.cpp b/WebCore/platform/graphics/gpu/SolidFillShader.cpp new file mode 100644 index 0000000..bbc4792 --- /dev/null +++ b/WebCore/platform/graphics/gpu/SolidFillShader.cpp @@ -0,0 +1,86 @@ +/* + * 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 "SolidFillShader.h" + +#include "Color.h" +#include "GraphicsContext3D.h" + +namespace WebCore { + +SolidFillShader::SolidFillShader(GraphicsContext3D* context, unsigned program) + : Shader(context, program) +{ + m_matrixLocation = context->getUniformLocation(program, "matrix"); + m_colorLocation = context->getUniformLocation(program, "color"); + m_positionLocation = context->getAttribLocation(program, "position"); +} + +PassOwnPtr<SolidFillShader> SolidFillShader::create(GraphicsContext3D* context) +{ + static const char* vertexShaderSource = + "uniform mat3 matrix;\n" + "uniform vec4 color;\n" + "attribute vec3 position;\n" + "void main() {\n" + " gl_Position = vec4(matrix * position, 1.0);\n" + "}\n"; + static const char* fragmentShaderSource = + "precision mediump float;\n" + "uniform mat3 matrix;\n" + "uniform vec4 color;\n" + "void main() {\n" + " gl_FragColor = color;\n" + "}\n"; + unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource); + if (!program) + return 0; + return new SolidFillShader(context, program); +} + +void SolidFillShader::use(const AffineTransform& transform, const Color& color) +{ + m_context->useProgram(m_program); + + float rgba[4]; + color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]); + m_context->uniform4f(m_colorLocation, rgba[0] * rgba[3], rgba[1] * rgba[3], rgba[2] * rgba[3], rgba[3]); + + float matrix[9]; + affineTo3x3(transform, matrix); + m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/); + + m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_positionLocation); +} + +} diff --git a/WebCore/platform/graphics/gpu/SolidFillShader.h b/WebCore/platform/graphics/gpu/SolidFillShader.h new file mode 100644 index 0000000..1071e73 --- /dev/null +++ b/WebCore/platform/graphics/gpu/SolidFillShader.h @@ -0,0 +1,53 @@ +/* + * 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 SolidFillShader_h +#define SolidFillShader_h + +#include "Shader.h" + +namespace WebCore { + +class SolidFillShader : public Shader { +public: + static PassOwnPtr<SolidFillShader> create(GraphicsContext3D* context); + void use(const AffineTransform& transform, const Color& color); + +private: + SolidFillShader(GraphicsContext3D* context, unsigned program); + + int m_matrixLocation; + int m_colorLocation; + int m_positionLocation; +}; + +} + +#endif // SolidFillShader_h diff --git a/WebCore/platform/graphics/gpu/TexShader.cpp b/WebCore/platform/graphics/gpu/TexShader.cpp new file mode 100644 index 0000000..ba3ecdd --- /dev/null +++ b/WebCore/platform/graphics/gpu/TexShader.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: + * + * * 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 "TexShader.h" + +#include "GraphicsContext3D.h" + +namespace WebCore { + +TexShader::TexShader(GraphicsContext3D* context, unsigned program) + : Shader(context, program) +{ + m_matrixLocation = context->getUniformLocation(program, "matrix"); + m_texMatrixLocation = context->getUniformLocation(program, "texMatrix"); + m_alphaLocation = context->getUniformLocation(program, "alpha"); + m_positionLocation = context->getAttribLocation(program, "position"); + m_samplerLocation = context->getUniformLocation(program, "sampler"); +} + +PassOwnPtr<TexShader> TexShader::create(GraphicsContext3D* context) +{ + static const char* vertexShaderSource = + "uniform mat3 matrix;\n" + "uniform mat3 texMatrix;\n" + "attribute vec3 position;\n" + "varying vec3 texCoord;\n" + "void main() {\n" + " texCoord = texMatrix * position;\n" + " gl_Position = vec4(matrix * position, 1.0);\n" + "}\n"; + static const char* fragmentShaderSource = + "precision mediump float;\n" + "uniform sampler2D sampler;\n" + "uniform float alpha;\n" + "varying vec3 texCoord;\n" + "void main() {\n" + " gl_FragColor = texture2D(sampler, texCoord.xy)* vec4(alpha);\n" + "}\n"; + unsigned program = loadProgram(context, vertexShaderSource, fragmentShaderSource); + if (!program) + return 0; + return new TexShader(context, program); +} + +void TexShader::use(const AffineTransform& transform, const AffineTransform& texTransform, int sampler, float alpha) +{ + m_context->useProgram(m_program); + float matrix[9]; + affineTo3x3(transform, matrix); + m_context->uniformMatrix3fv(m_matrixLocation, false /*transpose*/, matrix, 1 /*count*/); + + float texMatrix[9]; + affineTo3x3(texTransform, texMatrix); + m_context->uniformMatrix3fv(m_texMatrixLocation, false /*transpose*/, texMatrix, 1 /*count*/); + + m_context->uniform1i(m_samplerLocation, sampler); + m_context->uniform1f(m_alphaLocation, alpha); + + m_context->vertexAttribPointer(m_positionLocation, 3, GraphicsContext3D::FLOAT, false, 0, 0); + + m_context->enableVertexAttribArray(m_positionLocation); + +} + +} diff --git a/WebCore/platform/graphics/gpu/TexShader.h b/WebCore/platform/graphics/gpu/TexShader.h new file mode 100644 index 0000000..535997d --- /dev/null +++ b/WebCore/platform/graphics/gpu/TexShader.h @@ -0,0 +1,55 @@ +/* + * 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 TexShader_h +#define TexShader_h + +#include "Shader.h" + +namespace WebCore { + +class TexShader : public Shader { +public: + static PassOwnPtr<TexShader> create(GraphicsContext3D* context); + void use(const AffineTransform& transform, const AffineTransform& texTransform, int sampler, float alpha); + +private: + TexShader(GraphicsContext3D* context, unsigned program); + + int m_matrixLocation; + int m_texMatrixLocation; + int m_samplerLocation; + int m_alphaLocation; + int m_positionLocation; +}; + +} + +#endif // TexShader_h diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.cpp b/WebCore/platform/graphics/gpu/Texture.cpp index ae230db..557603c 100644 --- a/WebCore/platform/graphics/chromium/GLES2Texture.cpp +++ b/WebCore/platform/graphics/gpu/Texture.cpp @@ -30,9 +30,7 @@ #include "config.h" -#if USE(GLES2_RENDERING) - -#include "GLES2Texture.h" +#include "Texture.h" #include "GraphicsContext3D.h" #include "IntRect.h" @@ -41,7 +39,7 @@ namespace WebCore { -GLES2Texture::GLES2Texture(GraphicsContext3D* context, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize) +Texture::Texture(GraphicsContext3D* context, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize) : m_context(context) , m_format(format) , m_tiles(maxTextureSize, width, height, true) @@ -49,21 +47,21 @@ GLES2Texture::GLES2Texture(GraphicsContext3D* context, PassOwnPtr<Vector<unsigne { } -GLES2Texture::~GLES2Texture() +Texture::~Texture() { for (unsigned int i = 0; i < m_tileTextureIds->size(); i++) m_context->deleteTexture(m_tileTextureIds->at(i)); } -static void convertFormat(GraphicsContext3D* context, GLES2Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) +static void convertFormat(GraphicsContext3D* context, Texture::Format format, unsigned int* glFormat, unsigned int* glType, bool* swizzle) { *swizzle = false; switch (format) { - case GLES2Texture::RGBA8: + case Texture::RGBA8: *glFormat = GraphicsContext3D::RGBA; *glType = GraphicsContext3D::UNSIGNED_BYTE; break; - case GLES2Texture::BGRA8: + case Texture::BGRA8: if (context->supportsBGRA()) { *glFormat = GraphicsContext3D::BGRA_EXT; *glType = GraphicsContext3D::UNSIGNED_BYTE; @@ -79,7 +77,7 @@ static void convertFormat(GraphicsContext3D* context, GLES2Texture::Format forma } } -PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format format, int width, int height) +PassRefPtr<Texture> Texture::create(GraphicsContext3D* context, Format format, int width, int height) { int maxTextureSize = 0; context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize); @@ -101,7 +99,8 @@ PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(i); - unsigned int glFormat, glType; + unsigned int glFormat = 0; + unsigned int glType = 0; bool swizzle; convertFormat(context, format, &glFormat, &glType, &swizzle); context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId); @@ -110,7 +109,7 @@ PassRefPtr<GLES2Texture> GLES2Texture::create(GraphicsContext3D* context, Format tileBoundsWithBorder.height(), 0, glFormat, glType, 0); } - return adoptRef(new GLES2Texture(context, textureIds.leakPtr(), format, width, height, maxTextureSize)); + return adoptRef(new Texture(context, textureIds.leakPtr(), format, width, height, maxTextureSize)); } template <bool swizzle> @@ -135,10 +134,11 @@ static uint32_t* copySubRect(uint32_t* src, int srcX, int srcY, uint32_t* dst, i return dst; } -void GLES2Texture::load(void* pixels) +void Texture::load(void* pixels) { uint32_t* pixels32 = static_cast<uint32_t*>(pixels); - unsigned int glFormat, glType; + unsigned int glFormat = 0; + unsigned int glType = 0; bool swizzle; convertFormat(m_context, m_format, &glFormat, &glType, &swizzle); if (swizzle) { @@ -168,7 +168,7 @@ void GLES2Texture::load(void* pixels) } } -void GLES2Texture::bindTile(int tile) +void Texture::bindTile(int tile) { m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_tileTextureIds->at(tile)); m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); @@ -178,5 +178,3 @@ void GLES2Texture::bindTile(int tile) } } - -#endif diff --git a/WebCore/platform/graphics/chromium/GLES2Texture.h b/WebCore/platform/graphics/gpu/Texture.h index 43a4955..7e4a72b 100644 --- a/WebCore/platform/graphics/chromium/GLES2Texture.h +++ b/WebCore/platform/graphics/gpu/Texture.h @@ -28,10 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GLES2Texture_h -#define GLES2Texture_h - -#if USE(GLES2_RENDERING) +#ifndef Texture_h +#define Texture_h #include "RefCounted.h" #include "RefPtr.h" @@ -43,17 +41,17 @@ namespace WebCore { class GraphicsContext3D; -class GLES2Texture : public RefCounted<GLES2Texture> { +class Texture : public RefCounted<Texture> { public: - ~GLES2Texture(); + ~Texture(); enum Format { RGBA8, BGRA8 }; - static PassRefPtr<GLES2Texture> create(GraphicsContext3D*, Format, int width, int height); + static PassRefPtr<Texture> create(GraphicsContext3D*, Format, int width, int height); void bindTile(int tile); void load(void* pixels); Format format() const { return m_format; } const TilingData& tiles() const { return m_tiles; } private: - GLES2Texture(GraphicsContext3D*, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize); + Texture(GraphicsContext3D*, PassOwnPtr<Vector<unsigned int> > tileTextureIds, Format format, int width, int height, int maxTextureSize); GraphicsContext3D* m_context; Format m_format; TilingData m_tiles; @@ -62,6 +60,4 @@ private: } -#endif - -#endif // GLES2Texture_h +#endif // Texture_h diff --git a/WebCore/platform/graphics/chromium/TilingData.cpp b/WebCore/platform/graphics/gpu/TilingData.cpp index 4da242b..4da242b 100755..100644 --- a/WebCore/platform/graphics/chromium/TilingData.cpp +++ b/WebCore/platform/graphics/gpu/TilingData.cpp diff --git a/WebCore/platform/graphics/chromium/TilingData.h b/WebCore/platform/graphics/gpu/TilingData.h index f12e66e..f12e66e 100755..100644 --- a/WebCore/platform/graphics/chromium/TilingData.h +++ b/WebCore/platform/graphics/gpu/TilingData.h diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp index 96a639b..e1efdd4 100644 --- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp +++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp @@ -115,13 +115,17 @@ bool GStreamerGWorld::enterFullscreen() GstQuery* query = gst_query_new_segment(GST_FORMAT_TIME); gboolean queryResult = gst_element_query(m_pipeline, query); - // See https://bugzilla.gnome.org/show_bug.cgi?id=620490. #if GST_CHECK_VERSION(0, 10, 30) if (!queryResult) { gst_query_unref(query); gst_object_unref(GST_OBJECT(srcPad)); return true; } +#else + // GStreamer < 0.10.30 doesn't set the query result correctly, so + // just ignore it to avoid a compilation warning. + // See https://bugzilla.gnome.org/show_bug.cgi?id=620490. + (void) queryResult; #endif GstFormat format; diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h index 3d6d74a..9288df9 100644 --- a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h @@ -51,7 +51,6 @@ class ImageGStreamer : public RefCounted<ImageGStreamer> { #if PLATFORM(CAIRO) ImageGStreamer(GstBuffer*&, IntSize, cairo_format_t&); - cairo_surface_t* m_surface; #endif #if PLATFORM(MAC) diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp index 6f975a4..aeaee19 100644 --- a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp @@ -49,13 +49,12 @@ PassRefPtr<ImageGStreamer> ImageGStreamer::createImage(GstBuffer* buffer) ImageGStreamer::ImageGStreamer(GstBuffer*& buffer, IntSize size, cairo_format_t& cairoFormat) : m_image(0) - , m_surface(0) { - m_surface = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), cairoFormat, + cairo_surface_t* surface = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), cairoFormat, size.width(), size.height(), cairo_format_stride_for_width(cairoFormat, size.width())); - ASSERT(cairo_surface_status(m_surface) == CAIRO_STATUS_SUCCESS); - m_image = BitmapImage::create(m_surface); + ASSERT(cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS); + m_image = BitmapImage::create(surface); } ImageGStreamer::~ImageGStreamer() @@ -64,9 +63,4 @@ ImageGStreamer::~ImageGStreamer() m_image.clear(); m_image = 0; - - if (m_surface && cairo_surface_get_reference_count(m_surface)) - cairo_surface_destroy(m_surface); - - m_surface = 0; } diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index d9d2d97..5628eb3 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -1239,6 +1239,7 @@ static HashSet<String> mimeTypeCache() for (GList* iterator = factories; iterator; iterator = iterator->next) { GstTypeFindFactory* factory = GST_TYPE_FIND_FACTORY(iterator->data); GstCaps* caps = gst_type_find_factory_get_caps(factory); + gchar** extensions; if (!caps) continue; @@ -1316,6 +1317,16 @@ static HashSet<String> mimeTypeCache() g_strfreev(mimetype); } + + // As a last resort try some special cases depending + // on the file extensions registered with the typefind + // factory. + if (!cached && (extensions = gst_type_find_factory_get_extensions(factory))) { + for (int index = 0; extensions[index]; index++) { + if (g_str_equal(extensions[index], "m4v")) + cache.add(String("video/x-m4v")); + } + } } } diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h index 83dc5dd..8d99f05 100644 --- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindow.h @@ -22,14 +22,10 @@ #if ENABLE(VIDEO) +#include "Widget.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#if PLATFORM(GTK) -#include <gtk/gtk.h> -typedef GtkWidget PlatformWindowType; -#endif - namespace WebCore { class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> { @@ -39,13 +35,13 @@ class PlatformVideoWindow : public RefCounted<PlatformVideoWindow> { PlatformVideoWindow(); ~PlatformVideoWindow(); - PlatformWindowType* window() const { return m_window; } - gulong videoWindowId() const { return m_videoWindowId; } + PlatformWidget window() const { return m_window; } + unsigned long videoWindowId() const { return m_videoWindowId; } private: - gulong m_videoWindowId; - PlatformWindowType* m_videoWindow; - PlatformWindowType* m_window; + unsigned long m_videoWindowId; + PlatformWidget m_videoWindow; + PlatformWidget m_window; }; } diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp new file mode 100644 index 0000000..5c0e6ea --- /dev/null +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowEfl.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "PlatformVideoWindow.h" + +#include "NotImplemented.h" + +using namespace WebCore; + +PlatformVideoWindow::PlatformVideoWindow() +{ + notImplemented(); +} + +PlatformVideoWindow::~PlatformVideoWindow() +{ + notImplemented(); +} diff --git a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp index 185f535..c5f835c 100644 --- a/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp +++ b/WebCore/platform/graphics/gstreamer/PlatformVideoWindowGtk.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "PlatformVideoWindow.h" +#include <gtk/gtk.h> #ifdef GDK_WINDOWING_X11 #include <gdk/gdkx.h> // for GDK_WINDOW_XID #endif diff --git a/WebCore/platform/graphics/gtk/CairoUtilities.h b/WebCore/platform/graphics/gtk/CairoUtilities.h index 89eb458..594abc0 100644 --- a/WebCore/platform/graphics/gtk/CairoUtilities.h +++ b/WebCore/platform/graphics/gtk/CairoUtilities.h @@ -26,8 +26,6 @@ #ifndef CairoUtilities_h #define CairoUtilities_h -typedef struct _cairo_surface cairo_surface_t; -typedef struct _GdkPixbuf GdkPixbuf; GdkPixbuf* cairoImageSurfaceToGdkPixbuf(cairo_surface_t* surface); #endif // CairoUtilities_h diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index 92f8816..489bad7 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -241,11 +241,11 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F float red, green, blue, alpha; // Text shadow, inspired by FontMac - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && - context->getShadow(shadowSize, shadowBlur, shadowColor); + context->getShadow(shadowOffset, shadowBlur, shadowColor); // TODO: Blur support if (hasShadow) { @@ -257,7 +257,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F shadowFillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); - cairo_translate(cr, shadowSize.width(), shadowSize.height()); + cairo_translate(cr, shadowOffset.width(), shadowOffset.height()); if (partialRegion) { gdk_cairo_region(cr, partialRegion); @@ -290,7 +290,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F // Re-enable the platform shadow we disabled earlier if (hasShadow) - context->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace); + context->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace); // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 6561c11..252abd7 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -248,7 +248,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr drawLine(origin, endPoint); } -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint&, int width, TextCheckingLineStyle) { if (paintingDisabled()) return; diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm index db77402..33a930b 100644 --- a/WebCore/platform/graphics/mac/FontMac.mm +++ b/WebCore/platform/graphics/mac/FontMac.mm @@ -135,11 +135,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons CGContextSetFontSize(cgContext, platformData.m_size); - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; ColorSpace fillColorSpace = context->fillColorSpace(); - context->getShadow(shadowSize, shadowBlur, shadowColor); + context->getShadow(shadowOffset, shadowBlur, shadowColor); bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont(); if (hasSimpleShadow) { @@ -148,10 +148,10 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons Color fillColor = context->fillColor(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); context->setFillColor(shadowFillColor, fillColorSpace); - CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height()); + CGContextSetTextPosition(cgContext, point.x() + shadowOffset.width(), point.y() + shadowOffset.height()); showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->syntheticBoldOffset()) { - CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + shadowSize.height()); + CGContextSetTextPosition(cgContext, point.x() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + shadowOffset.height()); showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } context->setFillColor(fillColor, fillColorSpace); @@ -165,7 +165,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons } if (hasSimpleShadow) - context->setShadow(shadowSize, shadowBlur, shadowColor, fillColorSpace); + context->setShadow(shadowOffset, shadowBlur, shadowColor, fillColorSpace); if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing) CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing); diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm index 5f111f6..f3301d8 100644 --- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm @@ -119,7 +119,7 @@ static NSColor* createPatternColor(NSString* name, NSColor* defaultColor, bool& } // WebKit on Mac is a standard platform component, so it must use the standard platform artwork for underline. -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint& point, int width, TextCheckingLineStyle style) { if (paintingDisabled()) return; @@ -127,23 +127,41 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, // These are the same for misspelling or bad grammar. int patternHeight = cMisspellingLineThickness; int patternWidth = cMisspellingLinePatternWidth; - + bool usingDot; NSColor *patternColor; - if (grammar) { - // Constants for grammar pattern color. - static bool usingDotForGrammar = false; - DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, grammarPatternColor, (createPatternColor(@"GrammarDot", [NSColor greenColor], usingDotForGrammar))); - - usingDot = usingDotForGrammar; - patternColor = grammarPatternColor.get(); - } else { - // Constants for spelling pattern color. - static bool usingDotForSpelling = false; - DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling))); - - usingDot = usingDotForSpelling; - patternColor = spellingPatternColor.get(); + switch (style) { + case TextCheckingSpellingLineStyle: + { + // Constants for spelling pattern color. + static bool usingDotForSpelling = false; + DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling))); + usingDot = usingDotForSpelling; + patternColor = spellingPatternColor.get(); + break; + } + case TextCheckingGrammarLineStyle: + { + // Constants for grammar pattern color. + static bool usingDotForGrammar = false; + DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, grammarPatternColor, (createPatternColor(@"GrammarDot", [NSColor greenColor], usingDotForGrammar))); + usingDot = usingDotForGrammar; + patternColor = grammarPatternColor.get(); + break; + } +#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + case TextCheckingReplacementLineStyle: + { + // Constants for spelling pattern color. + static bool usingDotForSpelling = false; + DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"CorrectionDot", [NSColor blueColor], usingDotForSpelling))); + usingDot = usingDotForSpelling; + patternColor = spellingPatternColor.get(); + break; + } +#endif + default: + return; } // Make sure to draw only complete dots. diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 435e56e..7b0e7af 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -82,6 +82,7 @@ SOFT_LINK_POINTER(QTKit, QTMediaTypeSound, NSString *) SOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *) SOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *) +SOFT_LINK_POINTER(QTKit, QTMovieLoopsAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *) @@ -118,6 +119,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *) #define QTMediaTypeText getQTMediaTypeText() #define QTMediaTypeVideo getQTMediaTypeVideo() #define QTMovieAskUnresolvedDataRefsAttribute getQTMovieAskUnresolvedDataRefsAttribute() +#define QTMovieLoopsAttribute getQTMovieLoopsAttribute() #define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute() #define QTMovieDidEndNotification getQTMovieDidEndNotification() #define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute() @@ -153,6 +155,10 @@ enum { }; #endif +@interface FakeQTMovieView : NSObject +- (WebCoreMovieObserver *)delegate; +@end + using namespace WebCore; using namespace std; @@ -243,6 +249,7 @@ void MediaPlayerPrivate::createQTMovie(const String& url) [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute, [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute, [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute, + [NSNumber numberWithBool:NO], QTMovieLoopsAttribute, #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute", #endif @@ -254,8 +261,41 @@ void MediaPlayerPrivate::createQTMovie(const String& url) createQTMovie(cocoaURL, movieAttributes); } +static void disableComponentsOnce() +{ + static bool sComponentsDisabled = false; + if (sComponentsDisabled) + return; + sComponentsDisabled = true; + + // eat/PDF and grip/PDF components must be disabled twice since they are registered twice + // with different flags. However, there is currently a bug in 64-bit QTKit (<rdar://problem/8378237>) + // which causes subsequent disable component requests of exactly the same type to be ignored if + // QTKitServer has not yet started. As a result, we must pass in exactly the flags we want to + // disable per component. As a failsafe, if in the future these flags change, we will disable the + // PDF components for a third time with a wildcard flags field: + uint32_t componentsToDisable[11][5] = { + {'eat ', 'TEXT', 'text', 0, 0}, + {'eat ', 'TXT ', 'text', 0, 0}, + {'eat ', 'utxt', 'text', 0, 0}, + {'eat ', 'TEXT', 'tx3g', 0, 0}, + {'eat ', 'PDF ', 'vide', 0x44802, 0}, + {'eat ', 'PDF ', 'vide', 0x45802, 0}, + {'eat ', 'PDF ', 'vide', 0, 0}, + {'grip', 'PDF ', 'appl', 0x844a00, 0}, + {'grip', 'PDF ', 'appl', 0x845a00, 0}, + {'grip', 'PDF ', 'appl', 0, 0}, + {'imdc', 'pdf ', 'appl', 0, 0}, + }; + + for (size_t i = 0; i < sizeof(componentsToDisable)/sizeof(componentsToDisable[0]); ++i) + wkQTMovieDisableComponent(componentsToDisable[i]); +} + void MediaPlayerPrivate::createQTMovie(NSURL *url, NSDictionary *movieAttributes) { + disableComponentsOnce(); + [[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()]; bool recreating = false; @@ -315,11 +355,12 @@ void MediaPlayerPrivate::createQTMovie(NSURL *url, NSDictionary *movieAttributes static void mainThreadSetNeedsDisplay(id self, SEL) { - id movieView = [self superview]; - ASSERT(!movieView || [movieView isKindOfClass:[QTMovieView class]]); - if (!movieView || ![movieView isKindOfClass:[QTMovieView class]]) + id view = [self superview]; + ASSERT(!view || [view isKindOfClass:[QTMovieView class]]); + if (!view || ![view isKindOfClass:[QTMovieView class]]) return; + FakeQTMovieView *movieView = static_cast<FakeQTMovieView *>(view); WebCoreMovieObserver* delegate = [movieView delegate]; ASSERT(!delegate || [delegate isKindOfClass:[WebCoreMovieObserver class]]); if (!delegate || ![delegate isKindOfClass:[WebCoreMovieObserver class]]) @@ -1382,6 +1423,7 @@ void MediaPlayerPrivate::disableUnsupportedTracks() allowedTrackTypes->add("sdsm"); // MPEG-4 scene description stream allowedTrackTypes->add("tmcd"); // timecode allowedTrackTypes->add("tc64"); // timcode-64 + allowedTrackTypes->add("tmet"); // timed metadata } NSArray *tracks = [m_qtMovie.get() tracks]; diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 126ef2d..94fcc5e 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -101,11 +101,11 @@ static NSString *webFallbackFontFamily(void) } #if !ERROR_DISABLED -#ifdef __LP64__ +#if defined(__LP64__) || (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)) static NSString* pathFromFont(NSFont*) { - // FMGetATSFontRefFromFont is not available in 64-bit. As pathFromFont is only used for debugging - // purposes, returning nil is acceptable. + // FMGetATSFontRefFromFont is not available. As pathFromFont is only used for debugging purposes, + // returning nil is acceptable. return nil; } #else diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp index 0faf3ce..37fd8ad 100644 --- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp @@ -273,7 +273,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr UNUSED_PARAM(printing); } -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width, TextCheckingLineStyle style) { if (paintingDisabled()) return; @@ -281,7 +281,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, notImplemented(); UNUSED_PARAM(origin); UNUSED_PARAM(width); - UNUSED_PARAM(grammar); + UNUSED_PARAM(style); } FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 41c9759..c9c74dd 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -845,7 +845,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool) drawLine(origin, endPoint); } -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int, bool) +void GraphicsContext::drawLineForTextChecking(const IntPoint&, int, TextCheckingLineStyle) { if (paintingDisabled()) return; @@ -889,7 +889,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const if (m_common->state.shadowsIgnoreTransforms) { // Meaning that this graphics context is associated with a CanvasRenderingContext // We flip the height since CG and HTML5 Canvas have opposite Y axis - m_common->state.shadowSize = FloatSize(size.width(), -size.height()); + m_common->state.shadowOffset = FloatSize(size.width(), -size.height()); m_data->shadow = ContextShadow(color, blur, size.width(), -size.height()); } else { m_data->shadow = ContextShadow(color, blur, size.width(), size.height()); diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index e0ac574..c0cfae4 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -190,12 +190,12 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, QPainter::CompositionMode lastCompositionMode = painter->compositionMode(); painter->setCompositionMode(compositionMode); - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (ctxt->getShadow(shadowSize, shadowBlur, shadowColor)) { + if (ctxt->getShadow(shadowOffset, shadowBlur, shadowColor)) { FloatRect shadowImageRect(normalizedDst); - shadowImageRect.move(shadowSize.width(), shadowSize.height()); + shadowImageRect.move(shadowOffset.width(), shadowOffset.height()); QImage shadowImage(QSize(static_cast<int>(normalizedSrc.width()), static_cast<int>(normalizedSrc.height())), QImage::Format_ARGB32_Premultiplied); QPainter p(&shadowImage); diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp index 9c6acab..3038356 100644 --- a/WebCore/platform/graphics/qt/StillImageQt.cpp +++ b/WebCore/platform/graphics/qt/StillImageQt.cpp @@ -76,12 +76,12 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, ctxt->setCompositeOperation(op); - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - if (ctxt->getShadow(shadowSize, shadowBlur, shadowColor)) { + if (ctxt->getShadow(shadowOffset, shadowBlur, shadowColor)) { FloatRect shadowImageRect(normalizedDst); - shadowImageRect.move(shadowSize.width(), shadowSize.height()); + shadowImageRect.move(shadowOffset.width(), shadowOffset.height()); QImage shadowImage(QSize(static_cast<int>(normalizedSrc.width()), static_cast<int>(normalizedSrc.height())), QImage::Format_ARGB32_Premultiplied); QPainter p(&shadowImage); diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index 61039f2..c503307 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -44,28 +44,40 @@ bool GraphicsContext3D::getImageData(Image* image, bool premultiplyAlpha, Vector<uint8_t>& outputVector) { - if (!image || !image->data()) + if (!image) return false; - ImageSource decoder(false); - decoder.setData(image->data(), true); - if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) - return false; - bool hasAlpha = decoder.frameHasAlphaAtIndex(0); - OwnPtr<NativeImageSkia> pixels(decoder.createFrameAtIndex(0)); - if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height()) - return false; - SkBitmap::Config skiaConfig = pixels->config(); - if (skiaConfig != SkBitmap::kARGB_8888_Config) + OwnPtr<NativeImageSkia> pixels; + NativeImageSkia* skiaImage = 0; + AlphaOp neededAlphaOp = kAlphaDoNothing; + if (image->data()) { + ImageSource decoder(false); + decoder.setData(image->data(), true); + if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) + return false; + bool hasAlpha = decoder.frameHasAlphaAtIndex(0); + pixels = decoder.createFrameAtIndex(0); + if (!pixels.get() || !pixels->isDataComplete() || !pixels->width() || !pixels->height()) + return false; + SkBitmap::Config skiaConfig = pixels->config(); + if (skiaConfig != SkBitmap::kARGB_8888_Config) + return false; + skiaImage = pixels.get(); + if (hasAlpha && premultiplyAlpha) + neededAlphaOp = kAlphaDoPremultiply; + } else { + // This is a special case for texImage2D with HTMLCanvasElement input. + skiaImage = image->nativeImageForCurrentFrame(); + if (!premultiplyAlpha) + neededAlphaOp = kAlphaDoUnmultiply; + } + if (!skiaImage) return false; - SkBitmap& skiaImageRef = *pixels; + SkBitmap& skiaImageRef = *skiaImage; SkAutoLockPixels lock(skiaImageRef); - ASSERT(pixels->rowBytes() == pixels->width() * 4); - outputVector.resize(pixels->rowBytes() * pixels->height()); - AlphaOp neededAlphaOp = kAlphaDoNothing; - if (hasAlpha && premultiplyAlpha) - neededAlphaOp = kAlphaDoPremultiply; - return packPixels(reinterpret_cast<const uint8_t*>(pixels->getPixels()), - kSourceFormatBGRA8, pixels->width(), pixels->height(), 0, + ASSERT(skiaImage->rowBytes() == skiaImage->width() * 4); + outputVector.resize(skiaImage->rowBytes() * skiaImage->height()); + return packPixels(reinterpret_cast<const uint8_t*>(skiaImage->getPixels()), + kSourceFormatBGRA8, skiaImage->width(), skiaImage->height(), 0, format, type, neededAlphaOp, outputVector.data()); } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 1b20e26..1c80d49 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -34,6 +34,7 @@ #include "AffineTransform.h" #include "Color.h" #include "FloatRect.h" +#include "GLES2Canvas.h" #include "Gradient.h" #include "GraphicsContextPlatformPrivate.h" #include "GraphicsContextPrivate.h" @@ -55,10 +56,6 @@ #include <wtf/MathExtras.h> #include <wtf/UnusedParam.h> -#if USE(GLES2_RENDERING) -#include "GLES2Canvas.h" -#endif - using namespace std; namespace WebCore { @@ -248,10 +245,8 @@ void GraphicsContext::savePlatformState() if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) platformContext()->gpuCanvas()->save(); -#endif // Save our private State. platformContext()->save(); @@ -262,10 +257,8 @@ void GraphicsContext::restorePlatformState() if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) platformContext()->gpuCanvas()->restore(); -#endif // Restore our private State. platformContext()->restore(); @@ -345,13 +338,11 @@ void GraphicsContext::clearRect(const FloatRect& rect) if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) { platformContext()->prepareForHardwareDraw(); platformContext()->gpuCanvas()->clearRect(rect); return; } -#endif platformContext()->prepareForSoftwareDraw(); @@ -459,10 +450,8 @@ void GraphicsContext::concatCTM(const AffineTransform& affine) if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) platformContext()->gpuCanvas()->concatCTM(affine); -#endif platformContext()->canvas()->concat(affine); } @@ -626,9 +615,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) platformContext()->canvas()->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint); } -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& pt, - int width, - bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint& pt, int width, TextCheckingLineStyle style) { if (paintingDisabled()) return; @@ -780,13 +767,11 @@ void GraphicsContext::fillRect(const FloatRect& rect) ClipRectToCanvas(*platformContext()->canvas(), r, &r); } -#if USE(GLES2_RENDERING) if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient && !platformContext()->getDrawLooper()) { platformContext()->prepareForHardwareDraw(); platformContext()->gpuCanvas()->fillRect(rect); return; } -#endif platformContext()->save(); @@ -804,13 +789,11 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU() && !m_common->state.fillPattern && !m_common->state.fillGradient) { platformContext()->prepareForHardwareDraw(); platformContext()->gpuCanvas()->fillRect(rect, color, colorSpace); return; } -#endif platformContext()->prepareForSoftwareDraw(); @@ -932,10 +915,8 @@ void GraphicsContext::scale(const FloatSize& size) if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) platformContext()->gpuCanvas()->scale(size); -#endif platformContext()->canvas()->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar(size.height())); @@ -945,10 +926,10 @@ void GraphicsContext::setAlpha(float alpha) { if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) + if (platformContext()->useGPU()) platformContext()->gpuCanvas()->setAlpha(alpha); -#endif + platformContext()->setAlpha(alpha); } @@ -956,10 +937,10 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op) { if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) + if (platformContext()->useGPU()) platformContext()->gpuCanvas()->setCompositeOperation(op); -#endif + platformContext()->setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); } @@ -1046,10 +1027,9 @@ void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorS { if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) + if (platformContext()->useGPU()) platformContext()->gpuCanvas()->setFillColor(color, colorSpace); -#endif platformContext()->setFillColor(color.rgb()); } @@ -1241,10 +1221,8 @@ void GraphicsContext::rotate(float angleInRadians) if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) platformContext()->gpuCanvas()->rotate(angleInRadians); -#endif platformContext()->canvas()->rotate(WebCoreFloatToSkScalar( angleInRadians * (180.0f / 3.14159265f))); @@ -1255,10 +1233,8 @@ void GraphicsContext::translate(float w, float h) if (paintingDisabled()) return; -#if USE(GLES2_RENDERING) if (platformContext()->useGPU()) platformContext()->gpuCanvas()->translate(w, h); -#endif platformContext()->canvas()->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h)); @@ -1266,19 +1242,12 @@ void GraphicsContext::translate(float w, float h) void GraphicsContext::setGraphicsContext3D(GraphicsContext3D* context3D, const IntSize& size) { -#if USE(GLES2_RENDERING) platformContext()->setGraphicsContext3D(context3D, size); -#else - UNUSED_PARAM(context3D); - UNUSED_PARAM(size); -#endif } void GraphicsContext::syncSoftwareCanvas() { -#if USE(GLES2_RENDERING) platformContext()->syncSoftwareCanvas(); -#endif } } // namespace WebCore diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index 1ff87cc..aed289f 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -36,22 +36,20 @@ #include "ChromiumBridge.h" #include "FloatConversion.h" #include "FloatRect.h" +#include "GLES2Canvas.h" +#include "GLES2Context.h" #include "GraphicsContext.h" #include "Logging.h" #include "NativeImageSkia.h" #include "PlatformContextSkia.h" #include "PlatformString.h" -#include "SkiaUtils.h" +#include "SkPixelRef.h" #include "SkRect.h" #include "SkShader.h" +#include "SkiaUtils.h" #include "skia/ext/image_operations.h" #include "skia/ext/platform_canvas.h" -#if USE(GLES2_RENDERING) -#include "GLES2Canvas.h" -#include "GLES2Context.h" -#include "SkPixelRef.h" -#endif namespace WebCore { @@ -409,23 +407,21 @@ void Image::drawPattern(GraphicsContext* context, context->platformContext()->paintSkPaint(destRect, paint); } -#if USE(GLES2_RENDERING) static void drawBitmapGLES2(GraphicsContext* ctxt, NativeImageSkia* bitmap, const FloatRect& srcRect, const FloatRect& dstRect, ColorSpace styleColorSpace, CompositeOperator compositeOp) { ctxt->platformContext()->prepareForHardwareDraw(); GLES2Canvas* gpuCanvas = ctxt->platformContext()->gpuCanvas(); - GLES2Texture* texture = gpuCanvas->getTexture(bitmap); + Texture* texture = gpuCanvas->getTexture(bitmap); if (!texture) { ASSERT(bitmap->config() == SkBitmap::kARGB_8888_Config); ASSERT(bitmap->rowBytes() == bitmap->width() * 4); - texture = gpuCanvas->createTexture(bitmap, GLES2Texture::BGRA8, bitmap->width(), bitmap->height()); + texture = gpuCanvas->createTexture(bitmap, Texture::BGRA8, bitmap->width(), bitmap->height()); SkAutoLockPixels lock(*bitmap); ASSERT(bitmap->getPixels()); texture->load(bitmap->getPixels()); } gpuCanvas->drawTexturedRect(texture, srcRect, dstRect, styleColorSpace, compositeOp); } -#endif // ================================================ // BitmapImage Class @@ -472,12 +468,11 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. -#if USE(GLES2_RENDERING) if (ctxt->platformContext()->useGPU()) { drawBitmapGLES2(ctxt, bm, normSrcRect, normDstRect, colorSpace, compositeOp); return; } -#endif + ctxt->platformContext()->prepareForSoftwareDraw(); paintSkBitmap(ctxt->platformContext(), @@ -501,12 +496,10 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt, if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. -#if USE(GLES2_RENDERING) if (ctxt->platformContext()->useGPU()) { drawBitmapGLES2(ctxt, &m_nativeImage, srcRect, dstRect, styleColorSpace, compositeOp); return; } -#endif ctxt->platformContext()->prepareForSoftwareDraw(); diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index b9de0a2..3b1d015 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -34,11 +34,13 @@ #include "AffineTransform.h" #include "CanvasLayerChromium.h" +#include "GLES2Canvas.h" #include "GraphicsContext.h" +#include "GraphicsContext3D.h" #include "ImageBuffer.h" #include "NativeImageSkia.h" -#include "PlatformContextSkia.h" #include "SkiaUtils.h" +#include "Texture.h" #include "TilingData.h" #include "skia/ext/image_operations.h" @@ -46,14 +48,8 @@ #include "SkBitmap.h" #include "SkColorPriv.h" -#include "SkShader.h" #include "SkDashPathEffect.h" - -#if USE(GLES2_RENDERING) -#include "GraphicsContext3D.h" -#include "GLES2Canvas.h" -#include "GLES2Texture.h" -#endif +#include "SkShader.h" #include <wtf/MathExtras.h> #include <wtf/OwnArrayPtr.h> @@ -210,11 +206,9 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas) #if OS(WINDOWS) , m_drawingToImageBuffer(false) #endif -#if USE(GLES2_RENDERING) , m_useGPU(false) , m_gpuCanvas(0) , m_backingStoreState(None) -#endif { m_stateStack.append(State()); m_state = &m_stateStack.last(); @@ -222,7 +216,7 @@ PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas) PlatformContextSkia::~PlatformContextSkia() { -#if USE(GLES2_RENDERING) && USE(ACCELERATED_COMPOSITING) +#if USE(ACCELERATED_COMPOSITING) if (m_gpuCanvas) { CanvasLayerChromium* layer = static_cast<CanvasLayerChromium*>(m_gpuCanvas->context()->platformLayer()); layer->setPrepareTextureCallback(0); @@ -684,7 +678,6 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) m_canvas->restore(); } -#if USE(GLES2_RENDERING) #if USE(ACCELERATED_COMPOSITING) class PrepareTextureCallbackImpl : public CanvasLayerChromium::PrepareTextureCallback { public: @@ -793,7 +786,7 @@ void PlatformContextSkia::uploadSoftwareToHardware(CompositeOperator op) const SkAutoLockPixels lock(bitmap); GraphicsContext3D* context = m_gpuCanvas->context(); if (!m_uploadTexture || m_uploadTexture->tiles().totalSizeX() < bitmap.width() || m_uploadTexture->tiles().totalSizeY() < bitmap.height()) - m_uploadTexture = GLES2Texture::create(context, GLES2Texture::BGRA8, bitmap.width(), bitmap.height()); + m_uploadTexture = Texture::create(context, Texture::BGRA8, bitmap.width(), bitmap.height()); m_uploadTexture->load(bitmap.getPixels()); IntRect rect(0, 0, bitmap.width(), bitmap.height()); AffineTransform identity; @@ -823,5 +816,4 @@ void PlatformContextSkia::readbackHardwareToSoftware() const } } -#endif } // namespace WebCore diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index 6c84797..82edc16 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -35,22 +35,20 @@ #include "Noncopyable.h" #include "SkDashPathEffect.h" -#include "SkDrawLooper.h" #include "SkDeque.h" -#include "skia/ext/platform_canvas.h" +#include "SkDrawLooper.h" #include "SkPaint.h" #include "SkPath.h" +#include "skia/ext/platform_canvas.h" #include <wtf/Vector.h> namespace WebCore { -#if USE(GLES2_RENDERING) enum CompositeOperator; class GLES2Canvas; -class GLES2Texture; +class Texture; class GraphicsContext3D; -#endif // This class holds the platform-specific state for GraphicsContext. We put // most of our Skia wrappers on this class. In theory, a lot of this stuff could @@ -182,24 +180,16 @@ public: void setImageResamplingHint(const IntSize& srcSize, const FloatSize& dstSize); void clearImageResamplingHint(); bool hasImageResamplingHint() const; -#if USE(GLES2_RENDERING) bool useGPU() { return m_useGPU; } void setGraphicsContext3D(GraphicsContext3D*, const IntSize&); GLES2Canvas* gpuCanvas() const { return m_gpuCanvas.get(); } -#endif -#if USE(GLES2_RENDERING) // Call these before making a call that manipulates the underlying // skia::PlatformCanvas or WebCore::GLES2Canvas void prepareForSoftwareDraw() const; void prepareForHardwareDraw() const; // Call to force the skia::PlatformCanvas to contain all rendering results. void syncSoftwareCanvas() const; -#else - void prepareForSoftwareDraw() const {} - void prepareForHardwareDraw() const {} - void syncSoftwareCanvas() const {} -#endif private: #if OS(LINUX) || OS(WINDOWS) @@ -209,10 +199,8 @@ private: #endif void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths); -#if USE(GLES2_RENDERING) void uploadSoftwareToHardware(CompositeOperator) const; void readbackHardwareToSoftware() const; -#endif // Defines drawing style. struct State; @@ -237,12 +225,10 @@ private: #if OS(WINDOWS) bool m_drawingToImageBuffer; #endif -#if USE(GLES2_RENDERING) bool m_useGPU; OwnPtr<GLES2Canvas> m_gpuCanvas; mutable enum { None, Software, Mixed, Hardware } m_backingStoreState; - mutable RefPtr<GLES2Texture> m_uploadTexture; -#endif + mutable RefPtr<Texture> m_uploadTexture; }; } diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp index 44003bb..9edb775 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -222,11 +222,11 @@ void SkiaWinOutlineCache::removePathsForFont(HFONT hfont) bool windowsCanHandleDrawTextShadow(GraphicsContext *context) { - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - bool hasShadow = context->getShadow(shadowSize, shadowBlur, shadowColor); + bool hasShadow = context->getShadow(shadowOffset, shadowBlur, shadowColor); return (hasShadow && (shadowBlur == 0) && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255)); } diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp index 34f9b07..c6437f2 100644 --- a/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/WebCore/platform/graphics/win/FontCGWin.cpp @@ -140,11 +140,11 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer(); if (!drawIntoBitmap) { - FloatSize size; + FloatSize offset; float blur; Color color; - graphicsContext->getShadow(size, blur, color); - drawIntoBitmap = !size.isEmpty() || blur; + graphicsContext->getShadow(offset, blur, color); + drawIntoBitmap = offset.width() || offset.height() || blur; } } @@ -349,10 +349,10 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo CGContextSetFontSize(cgContext, platformData.size()); wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI()); - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur; Color shadowColor; - graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor); + graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor); bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur; if (hasSimpleShadow) { @@ -361,10 +361,10 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo Color fillColor = graphicsContext->fillColor(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); graphicsContext->setFillColor(shadowFillColor, DeviceColorSpace); - CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width(), point.y() + translation.height() + shadowSize.height()); + CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width(), point.y() + translation.height() + shadowOffset.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->syntheticBoldOffset()) { - CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowSize.height()); + CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height()); CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } graphicsContext->setFillColor(fillColor, DeviceColorSpace); @@ -378,7 +378,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo } if (hasSimpleShadow) - graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor, DeviceColorSpace); + graphicsContext->setShadow(shadowOffset, shadowBlur, shadowColor, DeviceColorSpace); wkRestoreFontSmoothingStyle(cgContext, oldFontSmoothingStyle); } diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp index 84c4ce0..7b65e96 100644 --- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp @@ -176,11 +176,14 @@ static const Color& grammarPatternColor() { return grammarColor; } -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint& point, int width, TextCheckingLineStyle style) { if (paintingDisabled()) return; + if (style != TextCheckingSpellingLineStyle && style != TextCheckingGrammarLineStyle) + return; + // These are the same for misspelling or bad grammar const int patternHeight = 3; // 3 rows ASSERT(cMisspellingLineThickness == patternHeight); @@ -201,7 +204,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, CGContextRef context = platformContext(); CGContextSaveGState(context); - const Color& patternColor = grammar ? grammarPatternColor() : spellingPatternColor(); + const Color& patternColor = style == TextCheckingGrammarLineStyle ? grammarPatternColor() : spellingPatternColor(); setCGStrokeColor(context, patternColor); wkSetPatternPhaseInUserSpace(context, point); diff --git a/WebCore/platform/graphics/win/QTMovie.cpp b/WebCore/platform/graphics/win/QTMovie.cpp index 032b446..cc1349a 100644 --- a/WebCore/platform/graphics/win/QTMovie.cpp +++ b/WebCore/platform/graphics/win/QTMovie.cpp @@ -240,6 +240,9 @@ void QTMoviePrivate::createMovieController() m_movieController = NewMovieController(m_movie, &bounds, flags); if (!m_movieController) return; + + // Disable automatic looping. + MCDoAction(m_movieController, mcActionSetLooping, 0); } void QTMoviePrivate::cacheMovieScale() diff --git a/WebCore/platform/graphics/wince/FontPlatformData.h b/WebCore/platform/graphics/wince/FontPlatformData.h index 0b973b8..4a174f0 100644 --- a/WebCore/platform/graphics/wince/FontPlatformData.h +++ b/WebCore/platform/graphics/wince/FontPlatformData.h @@ -26,9 +26,9 @@ #define FontPlatformData_h #include "FontDescription.h" -#include "StringImpl.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> +#include <wtf/text/StringImpl.h> typedef struct tagTEXTMETRICW TEXTMETRIC; typedef struct tagLOGFONTW LOGFONT; diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index e4466c8..990a31d 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -1062,7 +1062,7 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr setStrokeStyle(oldStyle); } -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint&, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint&, int width, TextCheckingLineStyle style) { notImplemented(); } @@ -1260,15 +1260,15 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to if (!m_data->m_dc) return; - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur = 0; Color shadowColor; - getShadow(shadowSize, shadowBlur, shadowColor); + getShadow(shadowOffset, shadowBlur, shadowColor); IntRect dstRect = fillRect; - dstRect.move(stableRound(shadowSize.width()), stableRound(shadowSize.height())); + dstRect.move(stableRound(shadowOffset.width()), stableRound(shadowOffset.height())); dstRect.inflate(stableRound(shadowBlur)); dstRect = m_data->mapRect(dstRect); @@ -1548,11 +1548,6 @@ AffineTransform GraphicsContext::getCTM() const return m_data->m_transform; } -void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) -{ - notImplemented(); -} - void GraphicsContext::fillRect(const FloatRect& rect) { savePlatformState(); @@ -1687,17 +1682,17 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer return; } - FloatSize shadowSize; + FloatSize shadowOffset; float shadowBlur = 0; Color shadowColor; bool hasShadow = textDrawingMode() == cTextFill - && getShadow(shadowSize, shadowBlur, shadowColor) + && getShadow(shadowOffset, shadowBlur, shadowColor) && shadowColor.alpha(); COLORREF shadowRGBColor; FloatPoint trShadowPoint; if (hasShadow) { shadowRGBColor = RGB(shadowColor.red(), shadowColor.green(), shadowColor.blue()); - trShadowPoint = m_data->mapPoint(startPoint + shadowSize); + trShadowPoint = m_data->mapPoint(startPoint + shadowOffset); } HGDIOBJ hOldFont = SelectObject(m_data->m_dc, hFont); diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp index 1a25f4f..10e502d 100644 --- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp +++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp @@ -95,12 +95,33 @@ GraphicsContext* ImageBuffer::context() const return m_context.get(); } -Image* ImageBuffer::image() const +bool ImageBuffer::drawsUsingCopy() const { - if (!m_image) - m_image = adoptRef(new BufferedImage(&m_data)); + return true; +} + +PassRefPtr<Image> ImageBuffer::copyImage() const +{ + return adoptRef(new BufferedImage(&m_data)); +} + +void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const +{ + notImplemented(); +} + +void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, + CompositeOperator op , bool useLowQualityScale) +{ + RefPtr<Image> imageCopy = copyImage(); + context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale); +} - return m_image.get(); +void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) +{ + RefPtr<Image> imageCopy = copyImage(); + imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect); } template <bool premultiplied> PassRefPtr<ImageData> diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 2428e7e..a39404a 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -357,14 +357,18 @@ void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool pr m_data->context->DrawLine(origin.x(), origin.y(), endPoint.x(), endPoint.y()); } - -void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar) +void GraphicsContext::drawLineForTextChecking(const IntPoint& origin, int width, TextCheckingLineStyle style) { - if (grammar) - m_data->context->SetPen(wxPen(*wxGREEN, 2, wxLONG_DASH)); - else + switch (style) { + case TextCheckingSpellingLineStyle: m_data->context->SetPen(wxPen(*wxRED, 2, wxLONG_DASH)); - + break; + case TextCheckingGrammarLineStyle: + m_data->context->SetPen(wxPen(*wxGREEN, 2, wxLONG_DASH)); + break; + default: + return; + } m_data->context->DrawLine(origin.x(), origin.y(), origin.x() + width, origin.y()); } |