diff options
Diffstat (limited to 'WebCore/platform/graphics')
65 files changed, 933 insertions, 304 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp index 62f29cf..2805b21 100644 --- a/WebCore/platform/graphics/BitmapImage.cpp +++ b/WebCore/platform/graphics/BitmapImage.cpp @@ -155,6 +155,11 @@ IntSize BitmapImage::currentFrameSize() const return m_source.frameSizeAtIndex(m_currentFrame); } +bool BitmapImage::getHotSpot(IntPoint& hotSpot) const +{ + return m_source.getHotSpot(hotSpot); +} + bool BitmapImage::dataChanged(bool allDataReceived) { // Because we're modifying the current frame, clear its (now possibly diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h index e4261e2..e5591ec 100644 --- a/WebCore/platform/graphics/BitmapImage.h +++ b/WebCore/platform/graphics/BitmapImage.h @@ -118,6 +118,7 @@ public: virtual IntSize size() const; IntSize currentFrameSize() const; + virtual bool getHotSpot(IntPoint&) const; virtual bool dataChanged(bool allDataReceived); virtual String filenameExtension() const; diff --git a/WebCore/platform/graphics/Color.cpp b/WebCore/platform/graphics/Color.cpp index 17a5d38..2f2a357 100644 --- a/WebCore/platform/graphics/Color.cpp +++ b/WebCore/platform/graphics/Color.cpp @@ -31,7 +31,7 @@ #include <wtf/Assertions.h> #include <wtf/MathExtras.h> -#include "ColorData.c" +#include "ColorData.cpp" using namespace std; using namespace WTF; diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 7682011..6414147 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -38,7 +38,6 @@ using namespace Unicode; namespace WebCore { -#if USE(FONT_FAST_PATH) const uint8_t Font::gRoundingHackCharacterTable[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/, @@ -51,7 +50,6 @@ const uint8_t Font::gRoundingHackCharacterTable[256] = { }; Font::CodePath Font::s_codePath = Auto; -#endif // ============================================================================================ // Font Implementation (Cross-Platform Portion) @@ -151,10 +149,8 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi } #endif -#if USE(FONT_FAST_PATH) if (codePath(run) != Complex) return drawSimpleText(context, run, point, from, to); -#endif return drawComplexText(context, run, point, from, to); } @@ -166,7 +162,6 @@ float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallb return floatWidthUsingSVGFont(run); #endif -#if USE(FONT_FAST_PATH) CodePath codePathToUse = codePath(run); if (codePathToUse != Complex) { // If the complex text implementation cannot return fallback fonts, avoid @@ -174,7 +169,6 @@ float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallb static bool returnFallbackFonts = canReturnFallbackFontsForComplexText(); return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow ? glyphOverflow : 0); } -#endif return floatWidthForComplexText(run, fallbackFonts, glyphOverflow); } @@ -191,10 +185,8 @@ float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsCo charsConsumed = run.length(); glyphName = ""; -#if USE(FONT_FAST_PATH) if (codePath(run) != Complex) return floatWidthForSimpleText(run, 0); -#endif return floatWidthForComplexText(run); } @@ -208,10 +200,8 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, to = (to == -1 ? run.length() : to); -#if USE(FONT_FAST_PATH) if (codePath(run) != Complex) return selectionRectForSimpleText(run, point, h, from, to); -#endif return selectionRectForComplexText(run, point, h, from, to); } @@ -223,10 +213,8 @@ int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs); #endif -#if USE(FONT_FAST_PATH) if (codePath(run) != Complex) return offsetForPositionForSimpleText(run, x, includePartialGlyphs); -#endif return offsetForPositionForComplexText(run, x, includePartialGlyphs); } @@ -268,4 +256,79 @@ bool Font::shouldUseSmoothing() return shouldUseFontSmoothing; } +void Font::setCodePath(CodePath p) +{ + s_codePath = p; +} + +Font::CodePath Font::codePath() +{ + return s_codePath; +} + +Font::CodePath Font::codePath(const TextRun& run) const +{ + if (s_codePath != Auto) + return s_codePath; + +#if PLATFORM(QT) + if (run.padding() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing()) + return Complex; +#endif + + // Start from 0 since drawing and highlighting also measure the characters before run->from + for (int i = 0; i < run.length(); i++) { + const UChar c = run[i]; + if (c < 0x300) // U+0300 through U+036F Combining diacritical marks + continue; + if (c <= 0x36F) + return Complex; + + if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha + continue; + if (c <= 0x05CF) + return Complex; + + if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar + continue; + if (c <= 0x1059) + return Complex; + + if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A) + continue; + if (c <= 0x11FF) + return Complex; + + if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian + continue; + if (c <= 0x18AF) + return Complex; + + if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) + continue; + if (c <= 0x194F) + return Complex; + + if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics + continue; + if (c <= 0x2000) + return SimpleWithGlyphOverflow; + + if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols + continue; + if (c <= 0x20FF) + return Complex; + + if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks + continue; + if (c <= 0xFE2F) + return Complex; + } + + if (typesettingFeatures()) + return Complex; + + return Simple; +} + } diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index 6633a50..2b36cca 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -151,9 +151,7 @@ public: static void setShouldUseSmoothing(bool); static bool shouldUseSmoothing(); -#if USE(FONT_FAST_PATH) enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow }; -#endif private: #if ENABLE(SVG_FONTS) @@ -164,8 +162,6 @@ private: int offsetForPositionForTextUsingSVGFont(const TextRun&, int position, bool includePartialGlyphs) const; #endif -#if USE(FONT_FAST_PATH) - CodePath codePath(const TextRun&) const; void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const; @@ -174,8 +170,8 @@ private: FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const; static bool canReturnFallbackFontsForComplexText(); -#endif + CodePath codePath(const TextRun&) const; void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const; @@ -185,7 +181,6 @@ private: public: // Useful for debugging the different font rendering code paths. -#if USE(FONT_FAST_PATH) static void setCodePath(CodePath); static CodePath codePath(); static CodePath s_codePath; @@ -195,7 +190,6 @@ public: { return (((c & ~0xFF) == 0 && gRoundingHackCharacterTable[c])); } -#endif FontSelector* fontSelector() const; static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; } diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index f57ae5b..b863e83 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -180,76 +180,6 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap return data; } -void Font::setCodePath(CodePath p) -{ - s_codePath = p; -} - -Font::CodePath Font::codePath() -{ - return s_codePath; -} - -Font::CodePath Font::codePath(const TextRun& run) const -{ - if (s_codePath != Auto) - return s_codePath; - - // Start from 0 since drawing and highlighting also measure the characters before run->from - for (int i = 0; i < run.length(); i++) { - const UChar c = run[i]; - if (c < 0x300) // U+0300 through U+036F Combining diacritical marks - continue; - if (c <= 0x36F) - return Complex; - - if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha - continue; - if (c <= 0x05CF) - return Complex; - - if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar - continue; - if (c <= 0x1059) - return Complex; - - if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A) - continue; - if (c <= 0x11FF) - return Complex; - - if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian - continue; - if (c <= 0x18AF) - return Complex; - - if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) - continue; - if (c <= 0x194F) - return Complex; - - if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics - continue; - if (c <= 0x2000) - return SimpleWithGlyphOverflow; - - if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols - continue; - if (c <= 0x20FF) - return Complex; - - if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks - continue; - if (c <= 0xFE2F) - return Complex; - } - - if (typesettingFeatures()) - return Complex; - - return Simple; -} - void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { // This glyph buffer holds our glyphs+advances+font data for each glyph. diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp index 0e961ad..198b41a 100644 --- a/WebCore/platform/graphics/Gradient.cpp +++ b/WebCore/platform/graphics/Gradient.cpp @@ -202,7 +202,11 @@ void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTra setPlatformGradientSpaceTransform(gradientSpaceTransformation); } +<<<<<<< HEAD:WebCore/platform/graphics/Gradient.cpp #if !(PLATFORM(SKIA) && !PLATFORM(ANDROID)) +======= +#if !PLATFORM(SKIA) && !PLATFORM(CAIRO) +>>>>>>> Webkit.org at r61121:WebCore/platform/graphics/Gradient.cpp void Gradient::setPlatformGradientSpaceTransform(const AffineTransform&) { } diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index 2c877af..b526e51 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -93,12 +93,14 @@ namespace WebCore { void getColor(float value, float* r, float* g, float* b, float* a) const; + bool isRadial() const { return m_radial; } + bool isZeroSize() const { return m_p0.x() == m_p1.x() && m_p0.y() == m_p1.y(); } + #if OS(WINCE) && !PLATFORM(QT) const FloatPoint& p0() const { return m_p0; } const FloatPoint& p1() const { return m_p1; } float r0() const { return m_r0; } float r1() const { return m_r1; } - bool isRadial() const { return m_radial; } const Vector<ColorStop>& getStops() const; #else #if PLATFORM(ANDROID) diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp index 0105c53..629d100 100644 --- a/WebCore/platform/graphics/GraphicsContext.cpp +++ b/WebCore/platform/graphics/GraphicsContext.cpp @@ -129,7 +129,7 @@ void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace) setPlatformStrokeColor(color, colorSpace); } -void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setShadow(const IntSize& size, float blur, const Color& color, ColorSpace colorSpace) { m_common->state.shadowSize = size; m_common->state.shadowBlur = blur; @@ -145,7 +145,7 @@ void GraphicsContext::clearShadow() clearPlatformShadow(); } -bool GraphicsContext::getShadow(IntSize& size, int& blur, Color& color) const +bool GraphicsContext::getShadow(IntSize& size, float& blur, Color& color) const { size = m_common->state.shadowSize; blur = m_common->state.shadowBlur; diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index caa0a7c..b857546 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -298,8 +298,8 @@ namespace WebCore { void beginTransparencyLayer(float opacity); void endTransparencyLayer(); - void setShadow(const IntSize&, int blur, const Color&, ColorSpace); - bool getShadow(IntSize&, int&, Color&) const; + void setShadow(const IntSize&, float blur, const Color&, ColorSpace); + bool getShadow(IntSize&, float&, Color&) const; void clearShadow(); void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&); @@ -314,7 +314,7 @@ namespace WebCore { #if PLATFORM(CAIRO) float getAlpha(); void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize); - static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur); + static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, float shadowBlur); #endif void setCompositeOperation(CompositeOperator); @@ -444,7 +444,7 @@ namespace WebCore { void setPlatformShouldAntialias(bool b); - void setPlatformShadow(const IntSize&, int blur, const Color&, ColorSpace); + void setPlatformShadow(const IntSize&, float blur, const Color&, ColorSpace); void clearPlatformShadow(); static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&); diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index 97465e2..a5ca8c7 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -54,7 +54,8 @@ bool GraphicsContext3D::extractImageData(Image* image, image->height(), flipY, alphaOp); - *internalFormat = (hasAlphaChannel ? RGBA : RGB); + // For GLES2 tex functions, internalformat has to match format. + *internalFormat = *format; return true; } diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index b62f52c..8d5c286 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -45,8 +45,8 @@ const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0; typedef GLuint Platform3DObject; const Platform3DObject NullPlatform3DObject = 0; #elif PLATFORM(QT) -#include <QtOpenGL/QtOpenGL> - +class QPainter; +class QRect; typedef void* PlatformGraphicsContext3D; const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0; typedef int Platform3DObject; @@ -63,7 +63,7 @@ namespace WebCore { class ArrayBufferView; class WebGLBuffer; class Uint8Array; - class FloatArray; + class Float32Array; class WebGLFramebuffer; class Int32Array; class WebGLProgram; @@ -390,7 +390,11 @@ namespace WebCore { FRAMEBUFFER_BINDING = 0x8CA6, RENDERBUFFER_BINDING = 0x8CA7, MAX_RENDERBUFFER_SIZE = 0x84E8, - INVALID_FRAMEBUFFER_OPERATION = 0x0506 + INVALID_FRAMEBUFFER_OPERATION = 0x0506, + + // WebGL-specific enums + UNPACK_FLIP_Y_WEBGL = 0x9240, + UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241 }; // Context creation attributes. @@ -398,7 +402,7 @@ namespace WebCore { Attributes() : alpha(true) , depth(true) - , stencil(true) + , stencil(false) , antialias(true) , premultipliedAlpha(true) { diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h index 1980337..baa3392 100644 --- a/WebCore/platform/graphics/GraphicsContextPrivate.h +++ b/WebCore/platform/graphics/GraphicsContextPrivate.h @@ -73,7 +73,7 @@ namespace WebCore { bool paintingDisabled; IntSize shadowSize; - unsigned shadowBlur; + float shadowBlur; Color shadowColor; bool shadowsIgnoreTransforms; diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h index 212175c..3230df5 100644 --- a/WebCore/platform/graphics/Image.h +++ b/WebCore/platform/graphics/Image.h @@ -109,6 +109,7 @@ public: IntRect rect() const { return IntRect(IntPoint(), size()); } int width() const { return size().width(); } int height() const { return size().height(); } + virtual bool getHotSpot(IntPoint&) const { return false; } bool setData(PassRefPtr<SharedBuffer> data, bool allDataReceived); virtual bool dataChanged(bool /*allDataReceived*/) { return false; } diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h index 9163523..9f9ba7e 100644 --- a/WebCore/platform/graphics/ImageBuffer.h +++ b/WebCore/platform/graphics/ImageBuffer.h @@ -43,7 +43,7 @@ namespace WebCore { class IntPoint; class IntRect; class String; - + enum ImageColorSpace { Unknown, DeviceRGB, // like sRGB @@ -82,8 +82,8 @@ namespace WebCore { void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint); void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint); - - String toDataURL(const String& mimeType, double quality = 1.0) const; + + String toDataURL(const String& mimeType, const double* quality = 0) const; #if !PLATFORM(CG) AffineTransform baseTransform() const { return AffineTransform(); } void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace); diff --git a/WebCore/platform/graphics/ImageSource.cpp b/WebCore/platform/graphics/ImageSource.cpp index c2366c1..7f6d323 100644 --- a/WebCore/platform/graphics/ImageSource.cpp +++ b/WebCore/platform/graphics/ImageSource.cpp @@ -37,6 +37,10 @@ namespace WebCore { +#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) +unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024; +#endif + ImageSource::ImageSource() : m_decoder(0) { @@ -75,11 +79,8 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) if (!m_decoder) { m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data)); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) -#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS -#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024) -#endif - if (m_decoder) - m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS); + if (m_decoder && s_maxPixelsPerDecodedImage) + m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage); #endif } @@ -107,6 +108,11 @@ IntSize ImageSource::frameSizeAtIndex(size_t index) const return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize(); } +bool ImageSource::getHotSpot(IntPoint&) const +{ + return false; +} + int ImageSource::repetitionCount() { return m_decoder ? m_decoder->repetitionCount() : cAnimationNone; diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h index d9bfa25..716566b 100644 --- a/WebCore/platform/graphics/ImageSource.h +++ b/WebCore/platform/graphics/ImageSource.h @@ -61,6 +61,7 @@ class BBitmap; namespace WebCore { +class IntPoint; class IntSize; class SharedBuffer; class String; @@ -172,6 +173,7 @@ public: bool isSizeAvailable(); IntSize size() const; IntSize frameSizeAtIndex(size_t) const; + bool getHotSpot(IntPoint&) const; int repetitionCount(); @@ -185,10 +187,18 @@ public: bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha. bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded. +<<<<<<< HEAD:WebCore/platform/graphics/ImageSource.h #if PLATFORM(ANDROID) void clearURL(); void setURL(const String& url); #endif +======= +#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) + static unsigned maxPixelsPerDecodedImage() { return s_maxPixelsPerDecodedImage; } + static void setMaxPixelsPerDecodedImage(unsigned maxPixels) { s_maxPixelsPerDecodedImage = maxPixels; } +#endif + +>>>>>>> Webkit.org at r61121:WebCore/platform/graphics/ImageSource.h private: #if PLATFORM(ANDROID) // FIXME: This is protected only to allow ImageSourceSkia to set ICO decoder @@ -196,6 +206,9 @@ private: protected: #endif NativeImageSourcePtr m_decoder; +#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) + static unsigned s_maxPixelsPerDecodedImage; +#endif }; } diff --git a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp index 79b32b4..fceeea1 100644 --- a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp @@ -21,7 +21,9 @@ #include "config.h" #include "FontCache.h" +#include "CString.h" #include "Font.h" +#include "GOwnPtrCairo.h" #include "SimpleFontData.h" #include <wtf/Assertions.h> @@ -81,8 +83,57 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne { } +static bool isWellKnownFontName(const AtomicString family) +{ + // Fonts that are used by layout tests included. The fact that + // they are used in Layout Tests indicate web compatibility issues + // if we do not handle them correctly. + if (equalIgnoringCase(family, "sans-serif") || equalIgnoringCase(family, "serif") + || equalIgnoringCase(family, "monospace") || equalIgnoringCase(family, "cursive") + || equalIgnoringCase(family, "fantasy") || equalIgnoringCase(family, "Times") + || equalIgnoringCase(family, "Courier") || equalIgnoringCase(family, "Helvetica") + || equalIgnoringCase(family, "Arial") || equalIgnoringCase(family, "Lucida Grande") + || equalIgnoringCase(family, "Ahem") || equalIgnoringCase(family, "Georgia") + || equalIgnoringCase(family, "Times New Roman")) + return true; + + return false; +} + FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) { +#if defined(USE_FREETYPE) + // Handle generic family types specially, because fontconfig does not know them, but we have + // code to fallback correctly in our platform data implementation. + if (!family.length() || family.startsWith("-webkit-") + || (fontDescription.genericFamily() != FontDescription::NoFamily) + || isWellKnownFontName(family)) + return new FontPlatformData(fontDescription, family); + + // First check the font exists. + CString familyNameString = family.string().utf8(); + const char* fcfamily = familyNameString.data(); + + GOwnPtr<FcPattern> pattern(FcPatternCreate()); + if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) + return 0; + + FcConfigSubstitute(0, pattern.get(), FcMatchPattern); + FcDefaultSubstitute(pattern.get()); + + GOwnPtr<FcObjectSet> objectSet(FcObjectSetCreate()); + if (!FcObjectSetAdd(objectSet.get(), FC_FAMILY)) + return 0; + + GOwnPtr<FcFontSet> fontSet(FcFontList(0, pattern.get(), objectSet.get())); + + if (!fontSet) + return 0; + + if (!fontSet->fonts) + return 0; +#endif + return new FontPlatformData(fontDescription, family); } diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index 71a2430..2a2d4a7 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -71,7 +71,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons // Text shadow, inspired by FontMac IntSize shadowSize; - int shadowBlur = 0; + float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && context->getShadow(shadowSize, shadowBlur, shadowColor); diff --git a/WebCore/platform/graphics/cairo/GOwnPtrCairo.cpp b/WebCore/platform/graphics/cairo/GOwnPtrCairo.cpp new file mode 100644 index 0000000..12df3cf --- /dev/null +++ b/WebCore/platform/graphics/cairo/GOwnPtrCairo.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "GOwnPtrCairo.h" + +#if defined(USE_FREETYPE) +#include <cairo-ft.h> +#include <fontconfig/fcfreetype.h> +#endif + +namespace WTF { + +#if defined(USE_FREETYPE) +template <> void freeOwnedGPtr<FcPattern>(FcPattern* ptr) +{ + if (ptr) + FcPatternDestroy(ptr); +} + +template <> void freeOwnedGPtr<FcObjectSet>(FcObjectSet* ptr) +{ + if (ptr) + FcObjectSetDestroy(ptr); +} + +template <> void freeOwnedGPtr<FcFontSet>(FcFontSet* ptr) +{ + if (ptr) + FcFontSetDestroy(ptr); +} +#endif + +} // namespace WTF diff --git a/WebCore/platform/graphics/cairo/GOwnPtrCairo.h b/WebCore/platform/graphics/cairo/GOwnPtrCairo.h new file mode 100644 index 0000000..b099707 --- /dev/null +++ b/WebCore/platform/graphics/cairo/GOwnPtrCairo.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GOwnPtrCairo_h +#define GOwnPtrCairo_h + +#include "GOwnPtr.h" + +#if defined(USE_FREETYPE) +typedef struct _FcPattern FcPattern; +typedef struct _FcObjectSet FcObjectSet; +typedef struct _FcFontSet FcFontSet; +#endif + +namespace WTF { + +#if defined(USE_FREETYPE) +template <> void freeOwnedGPtr<FcPattern>(FcPattern*); +template <> void freeOwnedGPtr<FcObjectSet>(FcObjectSet*); +template <> void freeOwnedGPtr<FcFontSet>(FcFontSet*); +#endif + +} // namespace WTF + +#endif diff --git a/WebCore/platform/graphics/cairo/GradientCairo.cpp b/WebCore/platform/graphics/cairo/GradientCairo.cpp index 0aada55..4e6ed07 100644 --- a/WebCore/platform/graphics/cairo/GradientCairo.cpp +++ b/WebCore/platform/graphics/cairo/GradientCairo.cpp @@ -76,6 +76,15 @@ cairo_pattern_t* Gradient::platformGradient() return m_gradient; } +void Gradient::setPlatformGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation) +{ + if (m_gradient) { + cairo_matrix_t matrix = gradientSpaceTransformation; + cairo_matrix_invert(&matrix); + cairo_pattern_set_matrix(m_gradient, &matrix); + } +} + void Gradient::fill(GraphicsContext* context, const FloatRect& rect) { cairo_t* cr = context->platformContext(); diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index a2dcbaf..083497f 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -143,7 +143,7 @@ static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr) cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr)); } -void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, int shadowBlur) +void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, float shadowBlur) { #if ENABLE(FILTERS) // calculate the kernel size according to the HTML5 canvas shadow specification @@ -162,7 +162,7 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva { #if ENABLE(FILTERS) IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) return; @@ -560,7 +560,7 @@ static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& { #if ENABLE(FILTERS) IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) @@ -841,7 +841,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer notImplemented(); } -void GraphicsContext::setPlatformShadow(IntSize const& size, int, Color const&, ColorSpace) +void GraphicsContext::setPlatformShadow(IntSize const& size, float, Color const&, ColorSpace) { // Cairo doesn't support shadows natively, they are drawn manually in the draw* // functions diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index 85a4179..c298e18 100644 --- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -284,7 +284,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un return CAIRO_STATUS_SUCCESS; } -String ImageBuffer::toDataURL(const String& mimeType, double) const +String ImageBuffer::toDataURL(const String& mimeType, const double*) const { cairo_surface_t* image = cairo_get_target(context()->platformContext()); if (!image) diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index e74c495..92394b3 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -135,7 +135,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo // Draw the shadow #if ENABLE(FILTERS) IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { IntSize shadowBufferSize; diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 2e3f829..c69f222 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -764,7 +764,7 @@ void GraphicsContext::endTransparencyLayer() m_data->m_userToDeviceTransformKnownToBeIdentity = false; } -void GraphicsContext::setPlatformShadow(const IntSize& offset, int blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setPlatformShadow(const IntSize& offset, float blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp index ce11499..fe7f83a 100644 --- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -250,6 +250,14 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size); } +static inline CFStringRef jpegUTI() +{ +#if PLATFORM(WIN) + static const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg"); +#endif + return kUTTypeJPEG; +} + static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) { #if PLATFORM(MAC) @@ -261,13 +269,12 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) // FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found. // For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>. static const CFStringRef kUTTypePNG = CFSTR("public.png"); - static const CFStringRef kUTTypeJPEG = CFSTR("public.jpeg"); static const CFStringRef kUTTypeGIF = CFSTR("com.compuserve.gif"); if (equalIgnoringCase(mimeType, "image/png")) return kUTTypePNG; if (equalIgnoringCase(mimeType, "image/jpeg")) - return kUTTypeJPEG; + return jpegUTI(); if (equalIgnoringCase(mimeType, "image/gif")) return kUTTypeGIF; @@ -276,7 +283,7 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) #endif } -String ImageBuffer::toDataURL(const String& mimeType, double) const +String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); @@ -288,11 +295,23 @@ String ImageBuffer::toDataURL(const String& mimeType, double) const if (!data) return "data:,"; - RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), utiFromMIMEType(mimeType).get(), 1, 0)); + RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType); + ASSERT(uti); + + RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), uti.get(), 1, 0)); if (!destination) return "data:,"; - CGImageDestinationAddImage(destination.get(), image.get(), 0); + RetainPtr<CFDictionaryRef> imageProperties = 0; + if (CFEqual(uti.get(), jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) { + // Apply the compression quality to the image destination. + RetainPtr<CFNumberRef> compressionQuality(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, quality)); + const void* key = kCGImageDestinationLossyCompressionQuality; + const void* value = compressionQuality.get(); + imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + } + + CGImageDestinationAddImage(destination.get(), image.get(), imageProperties.get()); CGImageDestinationFinalize(destination.get()); Vector<char> out; diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index 9ad3166..4a7aecc 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -29,6 +29,7 @@ #if PLATFORM(CG) #include "ImageSourceCG.h" +#include "IntPoint.h" #include "IntSize.h" #include "MIMETypeRegistry.h" #include "SharedBuffer.h" @@ -196,6 +197,28 @@ IntSize ImageSource::size() const return frameSizeAtIndex(0); } +bool ImageSource::getHotSpot(IntPoint& hotSpot) const +{ + RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions())); + if (!properties) + return false; + + int x = -1, y = -1; + CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotX")); + if (!num || !CFNumberGetValue(num, kCFNumberIntType, &x)) + return false; + + num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotY")); + if (!num || !CFNumberGetValue(num, kCFNumberIntType, &y)) + return false; + + if (x < 0 || y < 0) + return false; + + hotSpot = IntPoint(x, y); + return true; +} + int ImageSource::repetitionCount() { int result = cAnimationLoopOnce; // No property means loop once. diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index 9538a8d..48cf9d2 100644 --- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -274,7 +274,7 @@ 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. IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (m_graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor)) { // If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow() @@ -484,7 +484,7 @@ 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. IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) { COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue())); diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 7b22bad..0a5aec5 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -143,6 +143,7 @@ void FontPlatformData::setupPaint(SkPaint* paint) const break; } + paint->setEmbeddedBitmapText(m_style.useBitmaps); paint->setTextSize(SkFloatToScalar(ts)); paint->setTypeface(m_typeface); paint->setFakeBoldText(m_fakeBold); diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp index 8dba49e..78170a9 100644 --- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007, 2008, Google Inc. All rights reserved. + * Copyright (c) 2006, 2007, 2008, 2009, 2010, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -44,6 +44,25 @@ namespace WebCore { namespace { +bool isFontPresent(const UChar* fontName) +{ + HFONT hfont = CreateFont(12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + fontName); + if (!hfont) + return false; + HDC dc = GetDC(0); + HGDIOBJ oldFont = static_cast<HFONT>(SelectObject(dc, hfont)); + WCHAR actualFontName[LF_FACESIZE]; + GetTextFace(dc, LF_FACESIZE, actualFontName); + actualFontName[LF_FACESIZE - 1] = 0; + SelectObject(dc, oldFont); + DeleteObject(hfont); + ReleaseDC(0, dc); + // We don't have to worry about East Asian fonts with locale-dependent + // names here for now. + return !wcscmp(fontName, actualFontName); +} + // A simple mapping from UScriptCode to family name. This is a sparse array, // which works well since the range of UScriptCode values is small. typedef const UChar* ScriptToFontMap[USCRIPT_CODE_LIMIT]; @@ -55,10 +74,14 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap) const UChar* family; }; - const static FontMap fontMap[] = { + static const FontMap fontMap[] = { {USCRIPT_LATIN, L"times new roman"}, {USCRIPT_GREEK, L"times new roman"}, {USCRIPT_CYRILLIC, L"times new roman"}, + // FIXME: Consider trying new Vista fonts before XP fonts for CJK. + // Some Vista users do want to use Vista cleartype CJK fonts. If we + // did, the results of tests with CJK characters would have to be + // regenerated for Vista. {USCRIPT_SIMPLIFIED_HAN, L"simsun"}, {USCRIPT_TRADITIONAL_HAN, L"pmingliu"}, {USCRIPT_HIRAGANA, L"ms pgothic"}, @@ -72,32 +95,81 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap) {USCRIPT_BENGALI, L"vrinda"}, {USCRIPT_GURMUKHI, L"raavi"}, {USCRIPT_GUJARATI, L"shruti"}, - {USCRIPT_ORIYA, L"kalinga"}, {USCRIPT_TAMIL, L"latha"}, {USCRIPT_TELUGU, L"gautami"}, {USCRIPT_KANNADA, L"tunga"}, - {USCRIPT_MALAYALAM, L"kartika"}, - {USCRIPT_LAO, L"dokchampa"}, - {USCRIPT_TIBETAN, L"microsoft himalaya"}, {USCRIPT_GEORGIAN, L"sylfaen"}, {USCRIPT_ARMENIAN, L"sylfaen"}, - {USCRIPT_ETHIOPIC, L"nyala"}, + {USCRIPT_THAANA, L"mv boli"}, {USCRIPT_CANADIAN_ABORIGINAL, L"euphemia"}, {USCRIPT_CHEROKEE, L"plantagenet cherokee"}, - {USCRIPT_YI, L"microsoft yi balti"}, - {USCRIPT_SINHALA, L"iskoola pota"}, - {USCRIPT_SYRIAC, L"estrangelo edessa"}, - {USCRIPT_KHMER, L"daunpenh"}, - {USCRIPT_THAANA, L"mv boli"}, {USCRIPT_MONGOLIAN, L"mongolian balti"}, - {USCRIPT_MYANMAR, L"padauk"}, // For USCRIPT_COMMON, we map blocks to scripts when // that makes sense. }; - + + struct ScriptToFontFamilies { + UScriptCode script; + const UChar** families; + }; + + // Kartika on Vista or earlier lacks the support for Chillu + // letters added to Unicode 5.1. + // Try AnjaliOldLipi (a very widely used Malaylalam font with the full + // Unicode 5.x support) before falling back to Kartika. + static const UChar* malayalamFonts[] = {L"AnjaliOldLipi", L"Lohit Malayalam", L"Kartika", L"Rachana", 0}; + // Try Khmer OS before Vista fonts because 'Khmer OS' goes along better + // with Latin and looks better/larger for the same size. + static const UChar* khmerFonts[] = {L"Khmer OS", L"MoolBoran", L"DaunPenh", L"Code2000", 0}; + // For the following 6 scripts, two or fonts are listed. The fonts in + // the 1st slot are not available on Windows XP. To support these + // scripts on XP, listed in the rest of slots are widely used + // fonts. + static const UChar* ethiopicFonts[] = {L"Nyala", L"Abyssinica SIL", L"Ethiopia Jiret", L"Visual Geez Unicode", L"GF Zemen Unicode", 0}; + static const UChar* oriyaFonts[] = {L"Kalinga", L"ori1Uni", L"Lohit Oriya", 0}; + static const UChar* laoFonts[] = {L"DokChampa", L"Saysettha OT", L"Phetsarath OT", L"Code2000", 0}; + static const UChar* tibetanFonts[] = {L"Microsoft Himalaya", L"Jomolhari", L"Tibetan Machine Uni", 0}; + static const UChar* sinhalaFonts[] = {L"Iskoola Pota", L"AksharUnicode", 0}; + static const UChar* yiFonts[] = {L"Microsoft Yi Balti", L"Nuosu SIL", L"Code2000", 0}; + // http://www.bethmardutho.org/support/meltho/download/index.php + static const UChar* syriacFonts[] = {L"Estrangelo Edessa", L"Estrangelo Nisibin", L"Code2000", 0}; + // No Myanmar/Burmese font is shipped with Windows, yet. Try a few + // widely available/used ones that supports Unicode 5.1 or later. + static const UChar* myanmarFonts[] = {L"Padauk", L"Parabaik", L"Myanmar3", L"Code2000", 0}; + + static const ScriptToFontFamilies scriptToFontFamilies[] = { + {USCRIPT_MALAYALAM, malayalamFonts}, + {USCRIPT_KHMER, khmerFonts}, + {USCRIPT_ETHIOPIC, ethiopicFonts}, + {USCRIPT_ORIYA, oriyaFonts}, + {USCRIPT_LAO, laoFonts}, + {USCRIPT_TIBETAN, tibetanFonts}, + {USCRIPT_SINHALA, sinhalaFonts}, + {USCRIPT_YI, yiFonts}, + {USCRIPT_SYRIAC, syriacFonts}, + {USCRIPT_MYANMAR, myanmarFonts}, + }; + for (int i = 0; i < sizeof(fontMap) / sizeof(fontMap[0]); ++i) scriptFontMap[fontMap[i].script] = fontMap[i].family; + // FIXME: Instead of scanning the hard-coded list, we have to + // use EnumFont* to 'inspect' fonts to pick up fonts covering scripts + // when it's possible (e.g. using OS/2 table). If we do that, this + // had better be pulled out of here. + for (int i = 0; i < sizeof(scriptToFontFamilies) / sizeof(scriptToFontFamilies[0]); ++i) { + UScriptCode script = scriptToFontFamilies[i].script; + scriptFontMap[script] = 0; + const UChar** familyPtr = scriptToFontFamilies[i].families; + while (*familyPtr) { + if (isFontPresent(*familyPtr)) { + scriptFontMap[script] = *familyPtr; + break; + } + ++familyPtr; + } + } + // Initialize the locale-dependent mapping. // Since Chrome synchronizes the ICU default locale with its UI locale, // this ICU locale tells the current UI locale of Chrome. @@ -198,7 +270,7 @@ struct FontData { // in the 1st pass. Need to experiment further. typedef HashMap<String, FontData> FontDataCache; -} // namespace +} // namespace // FIXME: this is font fallback code version 0.1 // - Cover all the scripts @@ -363,4 +435,4 @@ int getStyleFromLogfont(const LOGFONT* logfont) (logfont->lfWeight >= 700 ? FontStyleBold : FontStyleNormal); } -} // namespace WebCore +} // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 37ea485..23aeefa 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -474,7 +474,50 @@ void GraphicsLayerChromium::updateBackfaceVisibility() void GraphicsLayerChromium::updateLayerPreserves3D() { - // FIXME: implement + if (m_preserves3D && !m_transformLayer) { + // Create the transform layer. + m_transformLayer = LayerChromium::create(LayerChromium::TransformLayer, this); + + // Copy the position from this layer. + updateLayerPosition(); + updateLayerSize(); + updateAnchorPoint(); + updateTransform(); + updateChildrenTransform(); + + m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f)); + + m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f)); + TransformationMatrix identity; + m_layer->setTransform(identity); + + // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer. + m_layer->setOpacity(1); + + // Move this layer to be a child of the transform layer. + if (m_layer->superlayer()) + m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get()); + m_transformLayer->addSublayer(m_layer.get()); + + updateSublayerList(); + } else if (!m_preserves3D && m_transformLayer) { + // Relace the transformLayer in the parent with this layer. + m_layer->removeFromSuperlayer(); + m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get()); + + // Release the transform layer. + m_transformLayer = 0; + + updateLayerPosition(); + updateLayerSize(); + updateAnchorPoint(); + updateTransform(); + updateChildrenTransform(); + + updateSublayerList(); + } + + updateOpacityOnLayer(); } void GraphicsLayerChromium::updateLayerDrawsContent() @@ -527,8 +570,7 @@ void GraphicsLayerChromium::updateContentsRect() if (!m_contentsLayer) return; - // The position of the layer is the center of quad. - m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x() + m_contentsRect.width() / 2, m_contentsRect.y() + m_contentsRect.height() / 2)); + m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y())); m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height())); } diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index b08df82..5e71e49 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -118,6 +118,10 @@ void LayerChromium::updateTextureContents(unsigned int textureId) OwnPtr<PlatformContextSkia> skiaContext; OwnPtr<GraphicsContext> graphicsContext; if (drawsContent()) { // Layer contents must be drawn into a canvas. + // Clip the dirtyRect to the size of the layer to avoid drawing outside + // the bounds of the backing texture. + dirtyRect.intersect(IntRect(IntPoint(0, 0), m_bounds)); + canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); skiaContext.set(new PlatformContextSkia(canvas.get())); @@ -135,8 +139,7 @@ void LayerChromium::updateTextureContents(unsigned int textureId) m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); skiaBitmap = &bitmap; - requiredTextureSize = IntSize(max(m_bounds.width(), dirtyRect.width()), - max(m_bounds.height(), dirtyRect.height())); + requiredTextureSize = m_bounds; } else { // Layer is a container. // The layer contains an Image. NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(contents()); diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 59952eb..7af7e9b 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -158,8 +158,16 @@ public: void setContents(NativeImagePtr contents); NativeImagePtr contents() const { return m_contents; } + void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } + const TransformationMatrix& drawTransform() const { return m_drawTransform; } + + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + float drawOpacity() const { return m_drawOpacity; } + bool drawsContent() { return m_owner && m_owner->drawsContent(); } + bool preserves3D() { return m_owner && m_owner->preserves3D(); } + void setLayerRenderer(LayerRendererChromium*); private: @@ -203,12 +211,16 @@ private: TransformationMatrix m_transform; TransformationMatrix m_sublayerTransform; + TransformationMatrix m_drawTransform; + uint32_t m_edgeAntialiasingMask; float m_opacity; float m_zPosition; float m_anchorPointZ; float m_borderWidth; + float m_drawOpacity; + unsigned int m_allocatedTextureId; IntSize m_allocatedTextureSize; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index dfb6078..73311be 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -156,6 +156,13 @@ static GLuint createLayerTexture() return textureId; } +static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b) +{ + const TransformationMatrix& transformA = a->drawTransform(); + const TransformationMatrix& transformB = b->drawTransform(); + + return transformA.m43() < transformB.m43(); +} PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(Page* page) { @@ -173,6 +180,7 @@ LayerRendererChromium::LayerRendererChromium(Page* page) , m_page(page) , m_rootLayerTextureWidth(0) , m_rootLayerTextureHeight(0) + , m_scrollPosition(IntPoint(-1, -1)) { m_quadVboIds[Vertices] = m_quadVboIds[LayerElements] = 0; m_hardwareCompositing = (initGL() && initializeSharedGLObjects()); @@ -284,6 +292,9 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); + if (m_scrollPosition == IntPoint(-1, -1)) + m_scrollPosition = scrollPosition; + IntPoint scrollDelta = toPoint(scrollPosition - m_scrollPosition); // Scroll only when the updateRect contains pixels for the newly uncovered region to avoid flashing. if ((scrollDelta.x() && updateRect.width() >= abs(scrollDelta.x()) && updateRect.height() >= contentRect.height()) @@ -358,19 +369,26 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& checkGLError(); - // FIXME: Sublayers need to be sorted in Z to get the correct transparency effect. - - // Enable scissoring to avoid rendering composited layers over the scrollbars. - glEnable(GL_SCISSOR_TEST); - glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height()); - // Translate all the composited layers by the scroll position. TransformationMatrix matrix; matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0); + float opacity = 1; + m_layerList.shrink(0); const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); for (size_t i = 0; i < sublayers.size(); i++) - compositeLayersRecursive(sublayers[i].get(), matrix, opacity, visibleRect); + updateLayersRecursive(sublayers[i].get(), matrix, opacity, visibleRect); + + // Sort layers by the z coordinate of their center so that layers further + // away get drawn first. + std::stable_sort(m_layerList.begin(), m_layerList.end(), compareLayerZ); + + // Enable scissoring to avoid rendering composited layers over the scrollbars. + glEnable(GL_SCISSOR_TEST); + glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height()); + + for (size_t j = 0; j < m_layerList.size(); j++) + drawLayer(m_layerList[j]); glDisable(GL_SCISSOR_TEST); @@ -464,65 +482,108 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform return mappedRect.intersects(FloatRect(-1, -1, 2, 2)); } -void LayerRendererChromium::compositeLayersRecursive(LayerChromium* layer, const TransformationMatrix& matrix, float opacity, const IntRect& visibleRect) +// Updates and caches the layer transforms and opacity values that will be used +// when rendering them. +void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity, const IntRect& visibleRect) { - static GLfloat glMatrix[16]; - // Compute the new matrix transformation that will be applied to this layer and - // all its sublayers. - // The basic transformation chain for the layer is (using the Matrix x Vector order): - // M = M[p] * T[l] * T[a] * M[l] * T[-a] + // all its sublayers. It's important to remember that the layer's position + // is the position of the layer's anchor point. Also, the coordinate system used + // assumes that the origin is at the lower left even though the coordinates the browser + // gives us for the layers are for the upper left corner. The Y flip happens via + // the orthographic projection applied at render time. + // The transformation chain for the layer is (using the Matrix x Vector order): + // M = M[p] * Tr[l] * M[l] * Tr[c] // Where M[p] is the parent matrix passed down to the function - // T[l] is the translation of the layer's center - // T[a] and T[-a] is a translation/inverse translation by the anchor point - // M[l] is the layer's matrix + // Tr[l] is the translation matrix locating the layer's anchor point + // Tr[c] is the translation offset between the anchor point and the center of the layer + // M[l] is the layer's matrix (applied at the anchor point) + // This transform creates a coordinate system whose origin is the center of the layer. // Note that the final matrix used by the shader for the layer is P * M * S . This final product - // is effectively computed in drawTexturedQuad(). + // is computed in drawTexturedQuad(). // Where: P is the projection matrix // M is the layer's matrix computed above // S is the scale adjustment (to scale up to the layer size) IntSize bounds = layer->bounds(); FloatPoint anchorPoint = layer->anchorPoint(); FloatPoint position = layer->position(); - float anchorX = (anchorPoint.x() - 0.5) * bounds.width(); - float anchorY = (0.5 - anchorPoint.y()) * bounds.height(); + + // Offset between anchor point and the center of the quad. + float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width(); + float centerOffsetY = (0.5 - anchorPoint.y()) * bounds.height(); // M = M[p] - TransformationMatrix localMatrix = matrix; - // M = M[p] * T[l] - localMatrix.translate3d(position.x(), position.y(), 0); - // M = M[p] * T[l] * T[a] - localMatrix.translate3d(anchorX, anchorY, 0); - // M = M[p] * T[l] * T[a] * M[l] + TransformationMatrix localMatrix = parentMatrix; + // M = M[p] * Tr[l] + localMatrix.translate3d(position.x(), position.y(), layer->anchorPointZ()); + // M = M[p] * Tr[l] * M[l] localMatrix.multLeft(layer->transform()); - // M = M[p] * T[l] * T[a] * M[l] * T[-a] - localMatrix.translate3d(-anchorX, -anchorY, 0); + // M = M[p] * Tr[l] * M[l] * Tr[c] + localMatrix.translate3d(centerOffsetX, centerOffsetY, -layer->anchorPointZ()); + + // Check if the layer falls within the visible bounds of the page. + bool layerVisible = isLayerVisible(layer, localMatrix, visibleRect); + + bool layerHasContent = layer->drawsContent() || layer->contents(); bool skipLayer = false; if (bounds.width() > 2048 || bounds.height() > 2048) { - LOG(LayerRenderer, "Skipping layer with size %d %d", bounds.width(), bounds.height()); + if (layerHasContent) + LOG(LayerRenderer, "Skipping layer with size %d %d", bounds.width(), bounds.height()); skipLayer = true; } // Calculate the layer's opacity. opacity *= layer->opacity(); - bool layerVisible = isLayerVisible(layer, localMatrix, visibleRect); + layer->setDrawTransform(localMatrix); + layer->setDrawOpacity(opacity); + if (layerVisible && !skipLayer) + m_layerList.append(layer); + + // Flatten to 2D if the layer doesn't preserve 3D. + if (!layer->preserves3D()) { + localMatrix.setM13(0); + localMatrix.setM23(0); + localMatrix.setM31(0); + localMatrix.setM32(0); + localMatrix.setM33(1); + localMatrix.setM34(0); + localMatrix.setM43(0); + } + + // Apply the sublayer transform at the center of the layer. + localMatrix.multLeft(layer->sublayerTransform()); + + // The origin of the sublayers is actually the bottom left corner of the layer + // (or top left when looking it it from the browser's pespective) instead of the center. + // The matrix passed down to the sublayers is therefore: + // M[s] = M * Tr[-center] + localMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0); + + const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); i++) + updateLayersRecursive(sublayers[i].get(), localMatrix, opacity, visibleRect); +} + +void LayerRendererChromium::drawLayer(LayerChromium* layer) +{ + const TransformationMatrix& localMatrix = layer->drawTransform(); + IntSize bounds = layer->bounds(); // Note that there are two types of layers: - // 1. Layers that have their own GraphicsContext and can draw their contents on demand (layer->drawsContent() == true). - // 2. Layers that are just containers of images/video/etc that don't own a GraphicsContext (layer->contents() == true). - if ((layer->drawsContent() || layer->contents()) && !skipLayer && layerVisible) { + // 1. Layers that draw their own content via the GraphicsContext (layer->drawsContent() == true). + // 2. Layers that are pure containers of images/video/etc whose content is simply + // copied into the backing texture (layer->contents() == true). + if (layer->drawsContent() || layer->contents()) { int textureId = getTextureId(layer); // If no texture has been created for the layer yet then create one now. if (textureId == -1) textureId = assignTextureForLayer(layer); // Redraw the contents of the layer if necessary. - if ((layer->drawsContent() || layer->contents()) && layer->contentsDirty()) { - // Update the contents of the layer before taking a snapshot. For layers that - // are simply containers, the following call just clears the dirty flag but doesn't - // actually do any draws/copies. + if (layer->contentsDirty()) { + // Update the backing texture contents for any dirty portion of the layer. layer->updateTextureContents(textureId); } @@ -533,22 +594,11 @@ void LayerRendererChromium::compositeLayersRecursive(LayerChromium* layer, const glBindTexture(GL_TEXTURE_2D, textureId); - drawTexturedQuad(localMatrix, bounds.width(), bounds.height(), opacity, false); + drawTexturedQuad(localMatrix, bounds.width(), bounds.height(), layer->drawOpacity(), false); } // Draw the debug border if there is one. drawDebugBorder(layer, localMatrix); - - // Apply the sublayer transform. - localMatrix.multLeft(layer->sublayerTransform()); - - // The origin of the sublayers is actually the left top corner of the layer - // instead of the center. The matrix passed down to the sublayers is therefore: - // M[s] = M * T[-center] - localMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0); - const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); - for (size_t i = 0; i < sublayers.size(); i++) - compositeLayersRecursive(sublayers[i].get(), localMatrix, opacity, visibleRect); } bool LayerRendererChromium::makeContextCurrent() @@ -590,8 +640,7 @@ bool LayerRendererChromium::initializeSharedGLObjects() " v_texCoord = a_texCoord; \n" "} \n"; char fragmentShaderString[] = - // FIXME: Re-introduce precision qualifier when we need GL ES shaders. - "//precision mediump float; \n" + "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" "uniform float alpha; \n" @@ -605,8 +654,7 @@ bool LayerRendererChromium::initializeSharedGLObjects() // from fragmentShaderString in that it doesn't swizzle the colors and doesn't // take an alpha value. char scrollFragmentShaderString[] = - // FIXME: Re-introduce precision qualifier when we need GL ES shaders. - "//precision mediump float; \n" + "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" "void main() \n" @@ -624,8 +672,7 @@ bool LayerRendererChromium::initializeSharedGLObjects() " gl_Position = matrix * a_position; \n" "} \n"; char borderFragmentShaderString[] = - // FIXME: Re-introduce precision qualifier when we need GL ES shaders. - "//precision mediump float; \n" + "precision mediump float; \n" "uniform vec4 color; \n" "void main() \n" "{ \n" diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index eb66dac..a2e3427 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -74,7 +74,9 @@ public: GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); } private: - void compositeLayersRecursive(LayerChromium*, const TransformationMatrix&, float opacity, const IntRect& visibleRect); + void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity, const IntRect& visibleRect); + + void drawLayer(LayerChromium*); void drawDebugBorder(LayerChromium*, const TransformationMatrix&); @@ -120,6 +122,8 @@ private: RefPtr<LayerChromium> m_rootLayer; + Vector<LayerChromium*> m_layerList; + bool m_needsDisplay; IntPoint m_scrollPosition; bool m_hardwareCompositing; diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index 29b83dc..2164db5 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -211,7 +211,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F // Text shadow, inspired by FontMac IntSize shadowSize; - int shadowBlur = 0; + float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && context->getShadow(shadowSize, shadowBlur, shadowColor); diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 8db512c..7350eeb 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -536,7 +536,7 @@ void GraphicsContext::clearPlatformShadow() notImplemented(); } -void GraphicsContext::setPlatformShadow(IntSize const&, int, Color const&, ColorSpace) +void GraphicsContext::setPlatformShadow(IntSize const&, float, Color const&, ColorSpace) { notImplemented(); } diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp index fdab656..c5de485 100644 --- a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp +++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp @@ -310,7 +310,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData(source, sourceRect, destPoint, m_data, m_size, true); } -String ImageBuffer::toDataURL(const String& mimeType, double) const +String ImageBuffer::toDataURL(const String& mimeType, const double*) const { if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) return "data:,"; diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm index 87057fa..100200a 100644 --- a/WebCore/platform/graphics/mac/FontMac.mm +++ b/WebCore/platform/graphics/mac/FontMac.mm @@ -136,7 +136,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; ColorSpace fillColorSpace = context->fillColorSpace(); context->getShadow(shadowSize, shadowBlur, shadowColor); diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 79a10dd..90678b2 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -35,7 +35,7 @@ #include "WebGLActiveInfo.h" #include "ArrayBufferView.h" #include "WebGLBuffer.h" -#include "FloatArray.h" +#include "Float32Array.h" #include "WebGLFramebuffer.h" #include "Int32Array.h" #include "WebGLProgram.h" diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp index 54cc7ee..7fe160a 100644 --- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp @@ -292,7 +292,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) return FloatRect(enclosingIntRect(m_data->transformation().mapRect(rect))); } -void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setPlatformShadow(const IntSize& size, float blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 2009424..d357a22 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -44,11 +44,15 @@ namespace WebCore { -static const QString fromRawDataWithoutRef(const String& string) +static const QString fromRawDataWithoutRef(const String& string, int start = 0, int len = -1) { + if (len < 0) + len = string.length() - start; + Q_ASSERT(start + len <= string.length()); + // We don't detach. This assumes the WebCore string data will stay valid for the // lifetime of the QString we pass back, since we don't ref the WebCore string. - return QString::fromRawData(reinterpret_cast<const QChar*>(string.characters()), string.length()); + return QString::fromRawData(reinterpret_cast<const QChar*>(string.characters() + start), len); } static QTextLine setupLayout(QTextLayout* layout, const TextRun& style) @@ -66,7 +70,7 @@ static QTextLine setupLayout(QTextLayout* layout, const TextRun& style) return line; } -void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const +static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText) { if (to < 0) to = run.length(); @@ -102,59 +106,72 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); + QPointF pt(point.x(), point.y()); // text shadow IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor); if (from > 0 || to < run.length()) { - QTextLayout layout(string, font()); - QTextLine line = setupLayout(&layout, run); - float x1 = line.cursorToX(from); - float x2 = line.cursorToX(to); - if (x2 < x1) - qSwap(x1, x2); - - QFontMetrics fm(font()); - int ascent = fm.ascent(); - QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height()); - - if (hasShadow) { - // TODO: when blur support is added, the clip will need to account - // for the blur radius - qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0; - if (shadowSize.width() > 0) - dx2 = shadowSize.width(); - else - dx1 = -shadowSize.width(); - if (shadowSize.height() > 0) - dy2 = shadowSize.height(); - else - dy1 = -shadowSize.height(); - // expand the clip rect to include the text shadow as well - clip.adjust(dx1, dx2, dy1, dy2); - } - p->save(); - p->setClipRect(clip.toRect(), Qt::IntersectClip); - QPointF pt(point.x(), point.y() - ascent); - if (hasShadow) { + if (isComplexText) { + QTextLayout layout(string, font); + QTextLine line = setupLayout(&layout, run); + float x1 = line.cursorToX(from); + float x2 = line.cursorToX(to); + if (x2 < x1) + qSwap(x1, x2); + + QFontMetrics fm(font); + int ascent = fm.ascent(); + QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height()); + + if (hasShadow) { + // TODO: when blur support is added, the clip will need to account + // for the blur radius + qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0; + if (shadowSize.width() > 0) + dx2 = shadowSize.width(); + else + dx1 = -shadowSize.width(); + if (shadowSize.height() > 0) + dy2 = shadowSize.height(); + else + dy1 = -shadowSize.height(); + // expand the clip rect to include the text shadow as well + clip.adjust(dx1, dx2, dy1, dy2); + } p->save(); - p->setPen(QColor(shadowColor)); - p->translate(shadowSize.width(), shadowSize.height()); + p->setClipRect(clip.toRect(), Qt::IntersectClip); + pt.setY(pt.y() - ascent); + if (hasShadow) { + p->save(); + p->setPen(QColor(shadowColor)); + p->translate(shadowSize.width(), shadowSize.height()); + line.draw(p, pt); + p->restore(); + } + p->setPen(textFillPen); line.draw(p, pt); p->restore(); + return; } - line.draw(p, pt); - p->restore(); - return; +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping); + pt.setX(pt.x() + skipWidth); + string = fromRawDataWithoutRef(sanitized, from, to - from); +#endif } - p->setFont(font()); + p->setFont(font); - QPointF pt(point.x(), point.y()); int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight; +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + // See QWebPagePrivate::QWebPagePrivate() where the default path is set to Complex for Qt 4.6 and earlier. + if (!isComplexText) + flags |= Qt::TextBypassShaping; +#endif if (hasShadow) { // TODO: text shadow blur support p->save(); @@ -165,7 +182,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float } if (ctx->textDrawingMode() & cTextStroke) { QPainterPath path; - path.addText(pt, font(), string); + path.addText(pt, font, string); p->setPen(textStrokePen); p->strokePath(path, p->pen()); } @@ -175,6 +192,42 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float } } +void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false); +#else + Q_ASSERT(false); +#endif +} + +void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const +{ + drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */true); +} + +float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + if (!run.length()) + return 0; + + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString string = fromRawDataWithoutRef(sanitized); + + int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping); + + // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) + if (treatAsSpace(run[0])) + w -= m_wordSpacing; + + return w + run.padding(); +#else + Q_ASSERT(false); + return 0.0f; +#endif +} + float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const { if (!run.length()) @@ -194,6 +247,34 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return w + run.padding(); } +int Font::offsetForPositionForSimpleText(const TextRun& run, int position, bool includePartialGlyphs) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString string = fromRawDataWithoutRef(sanitized); + + QFontMetrics fm(font()); + float delta = (float)position; + int curPos = 0; + do { + float charWidth = fm.width(string[curPos]); + delta -= charWidth; + if (includePartialGlyphs) { + if (delta + charWidth / 2 <= 0) + break; + } else { + if (delta + charWidth <= 0) + break; + } + } while (++curPos < string.size()); + + return curPos; +#else + Q_ASSERT(false); + return 0; +#endif +} + int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const { String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); @@ -204,6 +285,23 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool return line.xToCursor(position); } +FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString wholeText = fromRawDataWithoutRef(sanitized); + QString selectedText = fromRawDataWithoutRef(sanitized, from, to - from); + + int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping); + int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping); + + return FloatRect(pt.x() + startX, pt.y(), width, h); +#else + Q_ASSERT(false); + return FloatRect(); +#endif +} + FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const { String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); @@ -220,6 +318,11 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h); } +bool Font::canReturnFallbackFontsForComplexText() +{ + return false; +} + QFont Font::font() const { QFont f = primaryFont()->getQtFont(); diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index ad43908..e0a785e 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -30,7 +30,7 @@ #include "WebGLActiveInfo.h" #include "ArrayBufferView.h" #include "WebGLBuffer.h" -#include "FloatArray.h" +#include "Float32Array.h" #include "WebGLFramebuffer.h" #include "Int32Array.h" #include "WebGLProgram.h" @@ -40,6 +40,7 @@ #include "WebGLTexture.h" #include "Uint8Array.h" #include <QAbstractScrollArea> +#include <QGLContext> #include <wtf/UnusedParam.h> #include <wtf/text/CString.h> @@ -1620,6 +1621,11 @@ bool GraphicsContext3D::getImageData(Image* image, AlphaOp* neededAlphaOp, unsigned int* format) { + if (!image) + return false; + QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + if (!nativePixmap) + return false; *hasAlphaChannel = true; *format = GraphicsContext3D::RGBA; @@ -1627,8 +1633,7 @@ bool GraphicsContext3D::getImageData(Image* image, *neededAlphaOp = kAlphaDoNothing; if (!premultiplyAlpha && *hasAlphaChannel) *neededAlphaOp = kAlphaDoUnmultiply; - - QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + QImage nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32); outputVector.append(nativeImage.rgbSwapped().bits(), nativeImage.byteCount()); diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index bdb810a..2a7db4e 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -334,7 +334,7 @@ void GraphicsContext::drawRect(const IntRect& rect) if (m_common->state.shadowColor.isValid()) { IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (getShadow(shadowSize, shadowBlur, shadowColor)) { IntRect shadowRect = rect; @@ -372,7 +372,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) adjustLineToPixelBoundaries(p1, p2, width, style); IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) { p->save(); @@ -474,7 +474,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp p->setRenderHint(QPainter::Antialiasing, true); IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; startAngle *= 16; angleSpan *= 16; @@ -509,7 +509,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points p->save(); p->setRenderHint(QPainter::Antialiasing, shouldAntialias); IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (getShadow(shadowSize, shadowBlur, shadowColor)) { p->save(); @@ -540,7 +540,7 @@ QPen GraphicsContext::pen() static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath& path) { IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { p->translate(shadowSize.width(), shadowSize.height()); @@ -587,7 +587,7 @@ void GraphicsContext::strokePath() if (m_common->state.strokePattern || m_common->state.strokeGradient || strokeColor().alpha()) { IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (getShadow(shadowSize, shadowBlur, shadowColor)) { QTransform t(p->worldTransform()); @@ -619,7 +619,7 @@ void GraphicsContext::strokePath() static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* p, const FloatRect& rect) { IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { FloatRect shadowRect(rect); @@ -820,7 +820,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect) return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin); } -void GraphicsContext::setPlatformShadow(const IntSize& size, int, const Color&, ColorSpace) +void GraphicsContext::setPlatformShadow(const IntSize& size, float, const Color&, ColorSpace) { // Qt doesn't support shadows natively, they are drawn manually in the draw* // functions @@ -1011,7 +1011,8 @@ void GraphicsContext::clipOut(const Path& path) newClip.addPath(clippedOut); p->setClipPath(newClip, Qt::IntersectClip); } else { - newClip.addRect(p->window()); + QRect windowRect = p->transform().inverted().mapRect(p->window()); + newClip.addRect(windowRect); newClip.addPath(clippedOut.intersected(newClip)); p->setClipPath(newClip); } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index be54735..8ed0d89 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -59,7 +59,12 @@ public: // (a) We don't need the QBrush abstraction - we always end up using QGraphicsItem::paint // from the mask layer. // (b) QGraphicsOpacityEffect detaches the pixmap, which is inefficient on OpenGL. - QPixmap maskPixmap(sourceBoundingRect().toAlignedRect().size()); + const QSize maskSize = sourceBoundingRect().toAlignedRect().size(); + if (!maskSize.isValid() || maskSize.isEmpty()) { + drawSource(painter); + return; + } + QPixmap maskPixmap(maskSize); // We need to do this so the pixmap would have hasAlpha(). maskPixmap.fill(Qt::transparent); @@ -334,7 +339,7 @@ const GraphicsLayerQtImpl* GraphicsLayerQtImpl::rootLayer() const QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) { - if (!m_layer->drawsContent()) + if (!m_layer->drawsContent() || m_size.isEmpty() ||!m_size.isValid()) return QPixmap(); QRegion region = regionToUpdate; @@ -361,6 +366,7 @@ QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) // Render the actual contents into the cache painter.setCompositionMode(QPainter::CompositionMode_SourceOver); m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); + painter.end(); m_backingStoreKey = QPixmapCache::insert(pixmap); return pixmap; @@ -665,7 +671,9 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform #ifndef QT_NO_GRAPHICSEFFECT if (m_maskEffect) m_maskEffect.data()->update(); - else if (m_changeMask & DisplayChange) { + else +#endif + if (m_changeMask & DisplayChange) { // Recache now: all the content is ready and we don't want to wait until the paint event. // We only need to do this for HTML content, there's no point in caching directly composited // content like images or solid rectangles. @@ -674,7 +682,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform update(m_pendingContent.regionToUpdate.boundingRect()); m_pendingContent.regionToUpdate = QRegion(); } -#endif if ((m_changeMask & BackgroundColorChange) && (m_pendingContent.backgroundColor != m_currentContent.backgroundColor)) diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index bee15f2..e46913c 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -276,10 +276,9 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so // We get a mimeType here but QImageWriter does not support mimetypes but // only formats (png, gif, jpeg..., xpm). So assume we get image/ as image // mimetypes and then remove the image/ to get the Qt format. -String ImageBuffer::toDataURL(const String& mimeType, double quality) const +String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); - ASSERT(0.0 <= quality && quality <= 1.0); if (!mimeType.startsWith("image/")) return "data:,"; @@ -289,9 +288,16 @@ String ImageBuffer::toDataURL(const String& mimeType, double quality) const QBuffer buffer(&data); buffer.open(QBuffer::WriteOnly); - if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), quality * 100 + 0.5)) { - buffer.close(); - return "data:,"; + if (quality && *quality >= 0.0 && *quality <= 1.0) { + if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), *quality * 100 + 0.5)) { + buffer.close(); + return "data:,"; + } + } else { + if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), 100)) { + buffer.close(); + return "data:,"; + } } buffer.close(); diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index db12738..0d23738 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -187,6 +187,23 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, if (!image->hasAlpha() && painter->compositionMode() == QPainter::CompositionMode_SourceOver) painter->setCompositionMode(QPainter::CompositionMode_Source); + IntSize shadowSize; + float shadowBlur; + Color shadowColor; + if (ctxt->getShadow(shadowSize, shadowBlur, shadowColor)) { + FloatRect shadowImageRect(dst); + shadowImageRect.move(shadowSize.width(), shadowSize.height()); + + QImage shadowImage(QSize(static_cast<int>(src.width()), static_cast<int>(src.height())), QImage::Format_ARGB32_Premultiplied); + QPainter p(&shadowImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(shadowImage.rect(), shadowColor); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.drawPixmap(dst, *image, src); + p.end(); + painter->drawImage(shadowImageRect, shadowImage, src); + } + // Test using example site at // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html painter->drawPixmap(dst, *image, src); diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index a7351a0..8f1f912 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -72,6 +72,10 @@ Path& Path::operator=(const Path& other) // Check whether a point is on the border bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) { + // null border doesn't contain points + if (border.isEmpty()) + return false; + QPointF p1 = border.at(0); QPointF p2; @@ -186,6 +190,15 @@ void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) { + // Make sure there is a subpath for p1, the behavior depend on the last element of the subpath. + // When the user agent is to ensure there is a subpath for a coordinate (x, y), the user agent must + // check to see if the context has any subpaths, and if it does not, then the user agent must create + // a new subpath with the point (x, y) as its first (and only) point, as if the moveTo() method had been called. + if (!m_path.elementCount()) { + m_path.moveTo(p1); + return; + } + FloatPoint p0(m_path.currentPosition()); if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || radius == 0.f) { @@ -286,22 +299,34 @@ void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool antic double width = radius*2; double height = radius*2; - if (!anticlockwise && (ea < sa)) - span += 360; - else if (anticlockwise && (sa < ea)) - span -= 360; - - // this is also due to switched coordinate system - // we would end up with a 0 span instead of 360 - if (!(qFuzzyCompare(span + (ea - sa) + 1, 1.0) && - qFuzzyCompare(qAbs(span), 360.0))) { - span += ea - sa; + if ((!anticlockwise && (ea - sa >= 360)) || (anticlockwise && (sa - ea >= 360))) + // If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2*PI, or, if the + // anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2*PI, then the arc is the whole + // circumference of this circle. + span = 360; + else { + if (!anticlockwise && (ea < sa)) + span += 360; + else if (anticlockwise && (sa < ea)) + span -= 360; + + // this is also due to switched coordinate system + // we would end up with a 0 span instead of 360 + if (!(qFuzzyCompare(span + (ea - sa) + 1, 1.0) + && qFuzzyCompare(qAbs(span), 360.0))) { + // mod 360 + span += (ea - sa) - (static_cast<int>((ea - sa) / 360)) * 360; + } } // If the path is empty, move to where the arc will start to avoid painting a line from (0,0) // NOTE: QPainterPath::isEmpty() won't work here since it ignores a lone MoveToElement if (!m_path.elementCount()) m_path.arcMoveTo(xs, ys, width, height, sa); + else if (!radius) { + m_path.lineTo(xc, yc); + return; + } m_path.arcTo(xs, ys, width, height, sa, span); @@ -413,7 +438,16 @@ void Path::apply(void* info, PathApplierFunction function) const void Path::transform(const AffineTransform& transform) { - m_path = QTransform(transform).map(m_path); + QTransform qTransform(transform); +#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) + // Workaround for http://bugreports.qt.nokia.com/browse/QTBUG-11264 + // QTransform.map doesn't handle the MoveTo element because of the isEmpty issue + if (m_path.isEmpty() && m_path.elementCount()) { + QPointF point = qTransform.map(m_path.currentPosition()); + m_path.moveTo(point); + } else +#endif + m_path = qTransform.map(m_path); } } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 9de21e0..6ef38f0 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -978,7 +978,7 @@ void GraphicsContext::setPlatformFillPattern(Pattern* pattern) } void GraphicsContext::setPlatformShadow(const IntSize& size, - int blurInt, + float blurFloat, const Color& color, ColorSpace colorSpace) { @@ -986,14 +986,14 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, return; // Detect when there's no effective shadow and clear the looper. - if (!size.width() && !size.height() && !blurInt) { + if (!size.width() && !size.height() && !blurFloat) { platformContext()->setDrawLooper(0); return; } double width = size.width(); double height = size.height(); - double blur = blurInt; + double blur = blurFloat; // TODO(tc): This still does not address the issue that shadows // within canvas elements should ignore transforms. diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 1b03694..912fd12 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -261,7 +261,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size); } -String ImageBuffer::toDataURL(const String&, double) const +String ImageBuffer::toDataURL(const String&, const double*) const { // Encode the image into a vector. Vector<unsigned char> pngEncodedData; diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index d1fb647..d1d1692 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -66,6 +66,16 @@ enum ResamplingMode { static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight) { + if (platformContext->hasImageResamplingHint()) { + IntSize srcSize; + FloatSize dstSize; + platformContext->getImageResamplingHint(&srcSize, &dstSize); + srcWidth = srcSize.width(); + srcHeight = srcSize.height(); + destWidth = dstSize.width(); + destHeight = dstSize.height(); + } + int destIWidth = static_cast<int>(destWidth); int destIHeight = static_cast<int>(destHeight); @@ -188,7 +198,7 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm if (!destBitmapSubsetSkI.intersect(resizedImageRect)) return; // Resized image does not intersect. - if (srcIsFull || bitmap.shouldCacheResampling( + if (srcIsFull && bitmap.shouldCacheResampling( resizedImageRect.width(), resizedImageRect.height(), destBitmapSubsetSkI.width(), diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 7ec403c..15bd9b4 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -101,6 +101,7 @@ struct PlatformContextSkia::State { WTF::Vector<SkPath> m_antiAliasClipPaths; WebCore::InterpolationQuality m_interpolationQuality; + PlatformContextSkia::State cloneInheritedProperties(); private: // Not supported. void operator=(const State&); @@ -149,6 +150,7 @@ PlatformContextSkia::State::State(const State& other) , m_imageBufferClip(other.m_imageBufferClip) , m_clip(other.m_clip) #endif + , m_antiAliasClipPaths(other.m_antiAliasClipPaths) , m_interpolationQuality(other.m_interpolationQuality) { // Up the ref count of these. saveRef does nothing if 'this' is NULL. @@ -166,6 +168,17 @@ PlatformContextSkia::State::~State() m_strokeShader->safeUnref(); } +// Returns a new State with all of this object's inherited properties copied. +PlatformContextSkia::State PlatformContextSkia::State::cloneInheritedProperties() +{ + PlatformContextSkia::State state(*this); + + // Everything is inherited except for the clip paths. + state.m_antiAliasClipPaths.clear(); + + return state; +} + SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const { int s = roundf(m_alpha * 256); @@ -214,7 +227,9 @@ bool PlatformContextSkia::isDrawingToImageBuffer() const void PlatformContextSkia::save() { - m_stateStack.append(*m_state); + ASSERT(!hasImageResamplingHint()); + + m_stateStack.append(m_state->cloneInheritedProperties()); m_state = &m_stateStack.last(); #if OS(LINUX) || OS(WINDOWS) @@ -576,6 +591,29 @@ bool PlatformContextSkia::isPrinting() return m_canvas->getTopPlatformDevice().IsVectorial(); } +void PlatformContextSkia::getImageResamplingHint(WebCore::IntSize* srcSize, WebCore::FloatSize* dstSize) const +{ + *srcSize = m_imageResamplingHintSrcSize; + *dstSize = m_imageResamplingHintDstSize; +} + +void PlatformContextSkia::setImageResamplingHint(const WebCore::IntSize& srcSize, const WebCore::FloatSize& dstSize) +{ + m_imageResamplingHintSrcSize = srcSize; + m_imageResamplingHintDstSize = dstSize; +} + +void PlatformContextSkia::clearImageResamplingHint() +{ + m_imageResamplingHintSrcSize = WebCore::IntSize(); + m_imageResamplingHintDstSize = WebCore::FloatSize(); +} + +bool PlatformContextSkia::hasImageResamplingHint() const +{ + return !m_imageResamplingHintSrcSize.isEmpty() && !m_imageResamplingHintDstSize.isEmpty(); +} + #if OS(LINUX) || OS(WINDOWS) void PlatformContextSkia::applyClipFromImage(const WebCore::FloatRect& rect, const SkBitmap& imageBuffer) { diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index 2f24646..88a8ec7 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -170,6 +170,11 @@ public: // possible quality. bool isPrinting(); + void getImageResamplingHint(WebCore::IntSize* srcSize, WebCore::FloatSize* dstSize) const; + void setImageResamplingHint(const WebCore::IntSize& srcSize, const WebCore::FloatSize& dstSize); + void clearImageResamplingHint(); + bool hasImageResamplingHint() const; + private: #if OS(LINUX) || OS(WINDOWS) // Used when restoring and the state has an image clip. Only shows the pixels in @@ -194,6 +199,10 @@ private: // Current path in global coordinates. SkPath m_path; + // Stores image sizes for a hint to compute image resampling modes. + // Values are used in ImageSkia.cpp + WebCore::IntSize m_imageResamplingHintSrcSize; + WebCore::FloatSize m_imageResamplingHintDstSize; #if OS(WINDOWS) bool m_drawingToImageBuffer; #endif diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp index 4abf914..e0d2840 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -223,7 +223,7 @@ void SkiaWinOutlineCache::removePathsForFont(HFONT hfont) bool windowsCanHandleDrawTextShadow(WebCore::GraphicsContext *context) { IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; bool hasShadow = context->getShadow(shadowSize, shadowBlur, shadowColor); diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp index e4eb159..83178f3 100644 --- a/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/WebCore/platform/graphics/win/FontCGWin.cpp @@ -141,7 +141,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer(); if (!drawIntoBitmap) { IntSize size; - int blur; + float blur; Color color; graphicsContext->getShadow(size, blur, color); drawIntoBitmap = !size.isEmpty() || blur; @@ -350,7 +350,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI()); IntSize shadowSize; - int shadowBlur; + float shadowBlur; Color shadowColor; graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor); diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp index c6be087..2ca1a96 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp @@ -10,7 +10,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS “AS IS” + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h index d42f7f3..0a43a69 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h @@ -10,7 +10,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS “AS IS” + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS diff --git a/WebCore/platform/graphics/win/QTCFDictionary.cpp b/WebCore/platform/graphics/win/QTCFDictionary.cpp index ada1500..3c72792 100644 --- a/WebCore/platform/graphics/win/QTCFDictionary.cpp +++ b/WebCore/platform/graphics/win/QTCFDictionary.cpp @@ -52,9 +52,10 @@ CFDictionaryRef QTCFDictionaryCreateCopyWithDataCallback(CFAllocatorRef allocato ASSERT(callback); CFDataRef data = QTCFPropertyListCreateXMLData(kCFAllocatorDefault, dictionary); + if (!data) + return 0; CFDictionaryRef outputDictionary = callback(allocator, CFDataGetBytePtr(data), CFDataGetLength(data)); - if (data) - CFRelease(data); + CFRelease(data); return outputDictionary; } diff --git a/WebCore/platform/graphics/win/WKCAImageQueue.cpp b/WebCore/platform/graphics/win/WKCAImageQueue.cpp index b52b9a4..c2a178b 100644 --- a/WebCore/platform/graphics/win/WKCAImageQueue.cpp +++ b/WebCore/platform/graphics/win/WKCAImageQueue.cpp @@ -10,7 +10,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS “AS IS” + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS diff --git a/WebCore/platform/graphics/win/WKCAImageQueue.h b/WebCore/platform/graphics/win/WKCAImageQueue.h index 5c17575..3d25b48 100644 --- a/WebCore/platform/graphics/win/WKCAImageQueue.h +++ b/WebCore/platform/graphics/win/WKCAImageQueue.h @@ -10,7 +10,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS “AS IS” + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index a7bb695..5896f90 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -1250,7 +1250,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to return; IntSize shadowSize; - int shadowBlur = 0; + float shadowBlur = 0; Color shadowColor; getShadow(shadowSize, shadowBlur, shadowColor); @@ -1550,7 +1550,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) fillRect(rect, fillColor(), DeviceColorSpace); } -void GraphicsContext::setPlatformShadow(const IntSize&, int, const Color&, ColorSpace) +void GraphicsContext::setPlatformShadow(const IntSize&, float, const Color&, ColorSpace) { notImplemented(); } @@ -1673,7 +1673,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer } IntSize shadowSize; - int shadowBlur = 0; + float shadowBlur = 0; Color shadowColor; bool hasShadow = textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor) diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp index 0d5c8dd..4b739c8 100644 --- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp +++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp @@ -216,7 +216,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get()); } -String ImageBuffer::toDataURL(const String& mimeType, double) const +String ImageBuffer::toDataURL(const String& mimeType, const double*) const { if (!m_data.m_bitmap->bytes()) return "data:,"; diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 2298d6a..127bf07 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -554,7 +554,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) return; } -void GraphicsContext::setPlatformShadow(IntSize const&,int,Color const&, ColorSpace) +void GraphicsContext::setPlatformShadow(IntSize const&, float, Color const&, ColorSpace) { notImplemented(); } diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp index 1d37dfa..775e018 100644 --- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp +++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp @@ -76,7 +76,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so notImplemented(); } -String ImageBuffer::toDataURL(const String&, double) const +String ImageBuffer::toDataURL(const String&, const double*) const { notImplemented(); return String(); |