diff options
author | Ben Murdoch <benm@google.com> | 2009-08-11 17:01:47 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2009-08-11 18:21:02 +0100 |
commit | 0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch) | |
tree | 2943df35f62d885c89d01063cc528dd73b480fea /WebCore/platform/graphics/skia | |
parent | 7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff) | |
download | external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2 |
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/platform/graphics/skia')
-rw-r--r-- | WebCore/platform/graphics/skia/GradientSkia.cpp | 16 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/GraphicsContextSkia.cpp | 109 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/ImageBufferSkia.cpp | 22 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/ImageSkia.cpp | 6 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/ImageSourceSkia.cpp | 33 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/ImageSourceSkia.h | 60 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/PathSkia.cpp | 21 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/PatternSkia.cpp | 8 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/PlatformContextSkia.cpp | 120 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/PlatformContextSkia.h | 8 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/SkiaFontWin.cpp | 24 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/SkiaUtils.cpp | 52 | ||||
-rw-r--r-- | WebCore/platform/graphics/skia/SkiaUtils.h | 8 |
14 files changed, 244 insertions, 245 deletions
diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp index ac7366c..3bdddb2 100644 --- a/WebCore/platform/graphics/skia/GradientSkia.cpp +++ b/WebCore/platform/graphics/skia/GradientSkia.cpp @@ -158,15 +158,21 @@ SkShader* Gradient::platformGradient() // circle" (m_p1/m_r1). // See http://webkit.org/blog/175/introducing-css-gradients/ for a // description of the expected behavior. + + // The radius we give to Skia must be positive (and non-zero). If + // we're given a zero radius, just ask for a very small radius so + // Skia will still return an object. + SkScalar radius = m_r1 > 0 ? WebCoreFloatToSkScalar(m_r1) : SK_ScalarMin; m_gradient = SkGradientShader::CreateRadial(m_p1, - WebCoreFloatToSkScalar(m_r1), colors, pos, - static_cast<int>(countUsed), tile); + radius, colors, pos, static_cast<int>(countUsed), tile); } else { SkPoint pts[2] = { m_p0, m_p1 }; m_gradient = SkGradientShader::CreateLinear(pts, colors, pos, static_cast<int>(countUsed), tile); } + ASSERT(m_gradient); + SkMatrix matrix = m_gradientSpaceTransformation; m_gradient->setLocalMatrix(matrix); @@ -179,4 +185,10 @@ void Gradient::fill(GraphicsContext* context, const FloatRect& rect) context->fillRect(rect); } +void Gradient::setPlatformGradientSpaceTransform(const TransformationMatrix& matrix) +{ + if (m_gradient) + m_gradient->setLocalMatrix(m_gradientSpaceTransformation); +} + } // namespace WebCore diff --git a/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h b/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h index 29738f4..5e12ad6 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h +++ b/WebCore/platform/graphics/skia/GraphicsContextPlatformPrivate.h @@ -38,7 +38,7 @@ class PlatformContextSkia; namespace WebCore { // This class just holds onto a PlatformContextSkia for GraphicsContext. -class GraphicsContextPlatformPrivate : Noncopyable { +class GraphicsContextPlatformPrivate : public Noncopyable { public: GraphicsContextPlatformPrivate(PlatformContextSkia* platformContext) : m_context(platformContext) { } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 33ca23a..bbb42c9 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -331,7 +331,7 @@ void GraphicsContext::clearRect(const FloatRect& rect) SkPaint paint; platformContext()->setupPaintForFilling(&paint); - paint.setPorterDuffXfermode(SkPorterDuff::kClear_Mode); + paint.setXfermodeMode(SkXfermode::kClear_Mode); platformContext()->canvas()->drawRect(r, paint); } @@ -503,7 +503,7 @@ void GraphicsContext::drawFocusRing(const Color& color) paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); - paint.setColor(focusRingColor().rgb()); + paint.setColor(color.rgb()); paint.setStrokeWidth(focusRingOutset * 2); paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref(); focusRingRegion.getBoundaryPath(&path); @@ -530,16 +530,48 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) // probably worth the speed up of no square root, which also won't be exact. SkPoint disp = pts[1] - pts[0]; int length = SkScalarRound(disp.fX + disp.fY); - int width = roundf( - platformContext()->setupPaintForStroking(&paint, 0, length)); + platformContext()->setupPaintForStroking(&paint, 0, length); + int width = roundf(strokeThickness()); + bool isVerticalLine = pts[0].fX == pts[1].fX; + + if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) { + // Do a rect fill of our endpoints. This ensures we always have the + // appearance of being a border. We then draw the actual dotted/dashed line. + + SkRect r1, r2; + r1.set(pts[0].fX, pts[0].fY, pts[0].fX + width, pts[0].fY + width); + r2.set(pts[1].fX, pts[1].fY, pts[1].fX + width, pts[1].fY + width); + + if (isVerticalLine) { + r1.offset(-width / 2, 0); + r2.offset(-width / 2, -width); + } else { + r1.offset(0, -width / 2); + r2.offset(-width, -width / 2); + } + SkPaint fillPaint; + fillPaint.setColor(paint.getColor()); + platformContext()->canvas()->drawRect(r1, fillPaint); + platformContext()->canvas()->drawRect(r2, fillPaint); + + // Since we've already rendered the endcaps, adjust the endpoints to + // exclude them from the line itself. + if (isVerticalLine) { + pts[0].fY += width; + pts[1].fY -= width; + } else { + pts[0].fX += width; + pts[1].fX -= width; + } + } // "Borrowed" this comment and idea from GraphicsContextCG.cpp + // // For odd widths, we add in 0.5 to the appropriate x/y so that the float // arithmetic works out. For example, with a border width of 3, KHTML will // pass us (y1+y2)/2, e.g., (50+53)/2 = 103/2 = 51 when we want 51.5. It is // always true that an even width gave us a perfect position, but an odd // width gave us a position that is off by exactly 0.5. - bool isVerticalLine = pts[0].fX == pts[1].fX; if (width & 1) { // Odd. if (isVerticalLine) { @@ -687,13 +719,6 @@ void GraphicsContext::fillPath() SkPaint paint; platformContext()->setupPaintForFilling(&paint); - if (colorSpace == PatternColorSpace) { - SkShader* pat = state.fillPattern->createPlatformPattern(getCTM()); - paint.setShader(pat); - pat->unref(); - } else if (colorSpace == GradientColorSpace) - paint.setShader(state.fillGradient->platformGradient()); - platformContext()->canvas()->drawPath(path, paint); } @@ -713,14 +738,6 @@ void GraphicsContext::fillRect(const FloatRect& rect) SkPaint paint; platformContext()->setupPaintForFilling(&paint); - - if (colorSpace == PatternColorSpace) { - SkShader* pat = state.fillPattern->createPlatformPattern(getCTM()); - paint.setShader(pat); - pat->unref(); - } else if (colorSpace == GradientColorSpace) - paint.setShader(state.fillGradient->platformGradient()); - platformContext()->canvas()->drawRect(r, paint); } @@ -858,7 +875,7 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op) { if (paintingDisabled()) return; - platformContext()->setPorterDuffMode(WebCoreCompositeToSkiaComposite(op)); + platformContext()->setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); } void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) @@ -947,6 +964,24 @@ void GraphicsContext::setPlatformFillColor(const Color& color) platformContext()->setFillColor(color.rgb()); } +void GraphicsContext::setPlatformFillGradient(Gradient* gradient) +{ + if (paintingDisabled()) + return; + + platformContext()->setFillShader(gradient->platformGradient()); +} + +void GraphicsContext::setPlatformFillPattern(Pattern* pattern) +{ + if (paintingDisabled()) + return; + + SkShader* pat = pattern->createPlatformPattern(getCTM()); + platformContext()->setFillShader(pat); + pat->safeUnref(); +} + void GraphicsContext::setPlatformShadow(const IntSize& size, int blurInt, const Color& color) @@ -1015,6 +1050,24 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness) platformContext()->setStrokeThickness(thickness); } +void GraphicsContext::setPlatformStrokeGradient(Gradient* gradient) +{ + if (paintingDisabled()) + return; + + platformContext()->setStrokeShader(gradient->platformGradient()); +} + +void GraphicsContext::setPlatformStrokePattern(Pattern* pattern) +{ + if (paintingDisabled()) + return; + + SkShader* pat = pattern->createPlatformPattern(getCTM()); + platformContext()->setStrokeShader(pat); + pat->safeUnref(); +} + void GraphicsContext::setPlatformTextDrawingMode(int mode) { if (paintingDisabled()) @@ -1077,13 +1130,6 @@ void GraphicsContext::strokePath() SkPaint paint; platformContext()->setupPaintForStroking(&paint, 0, 0); - if (colorSpace == PatternColorSpace) { - SkShader* pat = state.strokePattern->createPlatformPattern(getCTM()); - paint.setShader(pat); - pat->unref(); - } else if (colorSpace == GradientColorSpace) - paint.setShader(state.strokeGradient->platformGradient()); - platformContext()->canvas()->drawPath(path, paint); } @@ -1102,13 +1148,6 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) platformContext()->setupPaintForStroking(&paint, 0, 0); paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); - if (colorSpace == PatternColorSpace) { - SkShader* pat = state.strokePattern->createPlatformPattern(getCTM()); - paint.setShader(pat); - pat->unref(); - } else if (colorSpace == GradientColorSpace) - paint.setShader(state.strokeGradient->platformGradient()); - platformContext()->canvas()->drawRect(rect, paint); } diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 600882d..7935ff1 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2008, Google Inc. All rights reserved. + * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -53,7 +54,7 @@ ImageBufferData::ImageBufferData(const IntSize& size) { } -ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success) +ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success) : m_data(size) , m_size(size) { @@ -71,7 +72,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success) // Make the background transparent. It would be nice if this wasn't // required, but the canvas is currently filled with the magic transparency // color. Can we have another way to manage this? - m_data.m_canvas.drawARGB(0, 0, 0, 0, SkPorterDuff::kClear_Mode); + m_data.m_canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); success = true; } @@ -100,6 +101,23 @@ Image* ImageBuffer::image() const return m_image.get(); } +void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) +{ + const SkBitmap& bitmap = *context()->platformContext()->bitmap(); + ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); + SkAutoLockPixels bitmapLock(bitmap); + for (int y = 0; y < m_size.height(); ++y) { + uint32_t* srcRow = bitmap.getAddr32(0, y); + for (int x = 0; x < m_size.width(); ++x) { + SkColor color = SkPMColorToColor(srcRow[x]); + srcRow[x] = SkPreMultiplyARGB(lookUpTable[SkColorGetA(color)], + lookUpTable[SkColorGetR(color)], + lookUpTable[SkColorGetG(color)], + lookUpTable[SkColorGetB(color)]); + } + } +} + PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const { ASSERT(context()); diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index cb089bb..45c3dcd 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -220,10 +220,10 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm } } -static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkPorterDuff::Mode& compOp) +static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { SkPaint paint; - paint.setPorterDuffXfermode(compOp); + paint.setXfermodeMode(compOp); paint.setFilterBitmap(true); int alpha = roundf(platformContext->getAlpha() * 256); if (alpha > 255) @@ -379,7 +379,7 @@ void Image::drawPattern(GraphicsContext* context, SkPaint paint; paint.setShader(shader)->unref(); - paint.setPorterDuffXfermode(WebCoreCompositeToSkiaComposite(compositeOp)); + paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp)); paint.setFilterBitmap(resampling == RESAMPLE_LINEAR); context->platformContext()->paintSkPaint(destRect, paint); diff --git a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp b/WebCore/platform/graphics/skia/ImageSourceSkia.cpp index b5f7e1d..1647b86 100644 --- a/WebCore/platform/graphics/skia/ImageSourceSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSourceSkia.cpp @@ -30,21 +30,21 @@ #include "config.h" -#include "ImageSourceSkia.h" +#include "ImageSource.h" #include "SharedBuffer.h" #include "GIFImageDecoder.h" +#include "ICOImageDecoder.h" #include "JPEGImageDecoder.h" #include "PNGImageDecoder.h" #include "BMPImageDecoder.h" #include "XBMImageDecoder.h" -#include "ICOImageDecoder.h" #include "SkBitmap.h" namespace WebCore { -ImageDecoder* createDecoder(const Vector<char>& data, const IntSize& preferredIconSize) +ImageDecoder* createDecoder(const Vector<char>& data) { // We need at least 4 bytes to figure out what kind of image we're dealing with. int length = data.size(); @@ -79,7 +79,7 @@ ImageDecoder* createDecoder(const Vector<char>& data, const IntSize& preferredIc // CURs begin with 2-byte 0 followed by 2-byte 2. if (!memcmp(contents, "\000\000\001\000", 4) || !memcmp(contents, "\000\000\002\000", 4)) - return new ICOImageDecoder(preferredIconSize); + return new ICOImageDecoder(); // XBMs require 8 bytes of info. if (length >= 8 && strncmp(contents, "#define ", 8) == 0) @@ -124,7 +124,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) // If insufficient bytes are available to determine the image type, no decoder plugin will be // made. if (!m_decoder) - m_decoder = createDecoder(data->buffer(), IntSize()); + m_decoder = createDecoder(data->buffer()); // CreateDecoder will return NULL if the decoder could not be created. Plus, // we should not send more data to a decoder which has already decided it @@ -150,10 +150,12 @@ IntSize ImageSource::size() const return m_decoder->size(); } -IntSize ImageSource::frameSizeAtIndex(size_t) const +IntSize ImageSource::frameSizeAtIndex(size_t index) const { - // TODO(brettw) do we need anything here? - return size(); + if (!m_decoder) + return IntSize(); + + return m_decoder->frameSizeAtIndex(index); } int ImageSource::repetitionCount() @@ -185,9 +187,8 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index) return 0; // Copy the bitmap. The pixel data is refcounted internally by SkBitmap, so - // this doesn't cost much. This pointer will be owned by the BitmapImage - // and freed in FrameData::clear(). - return new NativeImageSkia(buffer->bitmap()); + // this doesn't cost much. + return buffer->asNewNativeImage(); } bool ImageSource::frameIsCompleteAtIndex(size_t index) @@ -229,16 +230,6 @@ bool ImageSource::frameHasAlphaAtIndex(size_t index) return buffer->hasAlpha(); } -void ImageSourceSkia::setData(SharedBuffer* data, - bool allDataReceived, - const IntSize& preferredIconSize) -{ - if (!m_decoder) - m_decoder = createDecoder(data->buffer(), preferredIconSize); - - ImageSource::setData(data, allDataReceived); -} - String ImageSource::filenameExtension() const { return m_decoder ? m_decoder->filenameExtension() : String(); diff --git a/WebCore/platform/graphics/skia/ImageSourceSkia.h b/WebCore/platform/graphics/skia/ImageSourceSkia.h deleted file mode 100644 index 9cb4a95..0000000 --- a/WebCore/platform/graphics/skia/ImageSourceSkia.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ImageSource.h" - -namespace WebCore { - -class ImageSourceSkia : public ImageSource { -public: - // FIXME: This class is a hack to support Chromium's ICO decoder - // Currently our ICO decoder decodes all data during setData() instead of - // being lazy. In addition, it only decodes one frame (closest to the size - // passed to the decoder during createDecoder, called from setData) and - // discards all other data in the file. - // - // To fix this will require fixing the ICO decoder to be lazy, or to decode - // all frames. Apple's decoders (ImageIO) decode all frames, and return - // them all sorted in decreasing size. WebCore always draws the first frame. - // - // This is a special-purpose routine for the favicon decoder, which is used - // to specify a particular icon size for the ICOImageDecoder to prefer - // decoding. Note that not all favicons are ICOs, so this won't - // necessarily do anything differently than ImageSource::setData(). - // - // Passing an empty IntSize for |preferredIconSize| here is exactly - // equivalent to just calling ImageSource::setData(). See also comments in - // ICOImageDecoder.cpp. - void setData(SharedBuffer* data, - bool allDataReceived, - const IntSize& preferredIconSize); -}; - -} diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp index 9d9df52..5ac14b9 100644 --- a/WebCore/platform/graphics/skia/PathSkia.cpp +++ b/WebCore/platform/graphics/skia/PathSkia.cpp @@ -68,6 +68,11 @@ bool Path::isEmpty() const return m_path->isEmpty(); } +bool Path::hasCurrentPoint() const +{ + return m_path->getPoints(NULL, 0) != 0; +} + bool Path::contains(const FloatPoint& point, WindRule rule) const { return SkPathContainsPoint(m_path, point, @@ -81,15 +86,7 @@ void Path::translate(const FloatSize& size) FloatRect Path::boundingRect() const { - // FIXME: This #ifdef can go away once we're firmly using the new Skia. - // During the transition, this makes the code compatible with both versions. -#ifdef SK_USE_OLD_255_TO_256 return m_path->getBounds(); -#else - SkRect rect; - m_path->computeBounds(&rect, SkPath::kExact_BoundsType); - return rect; -#endif } void Path::moveTo(const FloatPoint& point) @@ -281,15 +278,7 @@ static FloatRect boundingBoxForCurrentStroke(const GraphicsContext* context) context->platformContext()->setupPaintForStroking(&paint, 0, 0); SkPath boundingPath; paint.getFillPath(context->platformContext()->currentPathInLocalCoordinates(), &boundingPath); - // FIXME: This #ifdef can go away once we're firmly using the new Skia. - // During the transition, this makes the code compatible with both versions. -#ifdef SK_USE_OLD_255_TO_256 return boundingPath.getBounds(); -#else - SkRect r; - boundingPath.computeBounds(&r, SkPath::kExact_BoundsType); - return r; -#endif } FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) diff --git a/WebCore/platform/graphics/skia/PatternSkia.cpp b/WebCore/platform/graphics/skia/PatternSkia.cpp index be8eb8a..11b5cf1 100644 --- a/WebCore/platform/graphics/skia/PatternSkia.cpp +++ b/WebCore/platform/graphics/skia/PatternSkia.cpp @@ -33,8 +33,10 @@ #include "NativeImageSkia.h" #include "TransformationMatrix.h" -#include "SkShader.h" #include "SkCanvas.h" +#include "SkColor.h" +#include "SkColorShader.h" +#include "SkShader.h" namespace WebCore { @@ -49,6 +51,10 @@ PlatformPatternPtr Pattern::createPlatformPattern(const TransformationMatrix& pa // LayoutTests/svg/W3C-SVG-1.1/pservers-grad-06-b.svg SkBitmap* bm = m_tileImage->nativeImageForCurrentFrame(); + // If we don't have a bitmap, return a transparent shader. + if (!bm) + return new SkColorShader(SkColorSetARGB(0, 0, 0, 0)); + if (m_repeatX && m_repeatY) return SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 74b2bfe..e0a292c 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -57,18 +57,18 @@ struct PlatformContextSkia::State { // Common shader state. float m_alpha; - SkPorterDuff::Mode m_porterDuffMode; - SkShader* m_gradient; - SkShader* m_pattern; + SkXfermode::Mode m_xferMode; bool m_useAntialiasing; SkDrawLooper* m_looper; // Fill. SkColor m_fillColor; + SkShader* m_fillShader; // Stroke. WebCore::StrokeStyle m_strokeStyle; SkColor m_strokeColor; + SkShader* m_strokeShader; float m_strokeThickness; int m_dashRatio; // Ratio of the length of a dash to its width. float m_miterLimit; @@ -98,15 +98,15 @@ private: // Note: Keep theses default values in sync with GraphicsContextState. PlatformContextSkia::State::State() : m_alpha(1) - , m_porterDuffMode(SkPorterDuff::kSrcOver_Mode) - , m_gradient(0) - , m_pattern(0) + , m_xferMode(SkXfermode::kSrcOver_Mode) , m_useAntialiasing(true) , m_looper(0) , m_fillColor(0xFF000000) + , m_fillShader(0) , m_strokeStyle(WebCore::SolidStroke) , m_strokeColor(WebCore::Color::black) , m_strokeThickness(0) + , m_strokeShader(0) , m_dashRatio(3) , m_miterLimit(4) , m_lineCap(SkPaint::kDefault_Cap) @@ -118,15 +118,15 @@ PlatformContextSkia::State::State() PlatformContextSkia::State::State(const State& other) : m_alpha(other.m_alpha) - , m_porterDuffMode(other.m_porterDuffMode) - , m_gradient(other.m_gradient) - , m_pattern(other.m_pattern) + , m_xferMode(other.m_xferMode) , m_useAntialiasing(other.m_useAntialiasing) , m_looper(other.m_looper) , m_fillColor(other.m_fillColor) + , m_fillShader(other.m_fillShader) , m_strokeStyle(other.m_strokeStyle) , m_strokeColor(other.m_strokeColor) , m_strokeThickness(other.m_strokeThickness) + , m_strokeShader(other.m_strokeShader) , m_dashRatio(other.m_dashRatio) , m_miterLimit(other.m_miterLimit) , m_lineCap(other.m_lineCap) @@ -141,16 +141,16 @@ PlatformContextSkia::State::State(const State& other) // Up the ref count of these. saveRef does nothing if 'this' is NULL. m_looper->safeRef(); m_dash->safeRef(); - m_gradient->safeRef(); - m_pattern->safeRef(); + m_fillShader->safeRef(); + m_strokeShader->safeRef(); } PlatformContextSkia::State::~State() { m_looper->safeUnref(); m_dash->safeUnref(); - m_gradient->safeUnref(); - m_pattern->safeUnref(); + m_fillShader->safeUnref(); + m_strokeShader->safeUnref(); } SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const @@ -170,7 +170,6 @@ SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const // Danger: canvas can be NULL. PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas) : m_canvas(canvas) - , m_stateStack(sizeof(State)) #if PLATFORM(WIN_OS) , m_drawingToImageBuffer(false) #endif @@ -274,8 +273,11 @@ void PlatformContextSkia::drawRect(SkRect rect) (m_state->m_strokeColor & 0xFF000000)) { // We do a fill of four rects to simulate the stroke of a border. SkColor oldFillColor = m_state->m_fillColor; - if (oldFillColor != m_state->m_strokeColor) - setFillColor(m_state->m_strokeColor); + + // setFillColor() will set the shader to NULL, so save a ref to it now. + SkShader* oldFillShader = m_state->m_fillShader; + oldFillShader->safeRef(); + setFillColor(m_state->m_strokeColor); setupPaintForFilling(&paint); SkRect topBorder = { rect.fLeft, rect.fTop, rect.fRight, rect.fTop + 1 }; canvas()->drawRect(topBorder, paint); @@ -285,8 +287,9 @@ void PlatformContextSkia::drawRect(SkRect rect) canvas()->drawRect(leftBorder, paint); SkRect rightBorder = { rect.fRight - 1, rect.fTop + 1, rect.fRight, rect.fBottom - 1 }; canvas()->drawRect(rightBorder, paint); - if (oldFillColor != m_state->m_strokeColor) - setFillColor(oldFillColor); + setFillColor(oldFillColor); + setFillShader(oldFillShader); + oldFillShader->safeUnref(); } } @@ -300,19 +303,15 @@ void PlatformContextSkia::setupPaintCommon(SkPaint* paint) const #endif paint->setAntiAlias(m_state->m_useAntialiasing); - paint->setPorterDuffXfermode(m_state->m_porterDuffMode); + paint->setXfermodeMode(m_state->m_xferMode); paint->setLooper(m_state->m_looper); - - if (m_state->m_gradient) - paint->setShader(m_state->m_gradient); - else if (m_state->m_pattern) - paint->setShader(m_state->m_pattern); } void PlatformContextSkia::setupPaintForFilling(SkPaint* paint) const { setupPaintCommon(paint); paint->setColor(m_state->applyAlpha(m_state->m_fillColor)); + paint->setShader(m_state->m_fillShader); } float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, int length) const @@ -321,6 +320,7 @@ float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, i float width = m_state->m_strokeThickness; paint->setColor(m_state->applyAlpha(m_state->m_strokeColor)); + paint->setShader(m_state->m_strokeShader); paint->setStyle(SkPaint::kStroke_Style); paint->setStrokeWidth(SkFloatToScalar(width)); paint->setStrokeCap(m_state->m_lineCap); @@ -338,20 +338,27 @@ float PlatformContextSkia::setupPaintForStroking(SkPaint* paint, SkRect* rect, i width = m_state->m_dashRatio * width; // Fall through. case WebCore::DottedStroke: - SkScalar dashLength; - if (length) { - // Determine about how many dashes or dots we should have. - float roundedWidth = roundf(width); - int numDashes = roundedWidth ? (length / roundedWidth) : length; - if (!(numDashes & 1)) - numDashes++; // Make it odd so we end on a dash/dot. - // Use the number of dashes to determine the length of a - // dash/dot, which will be approximately width - dashLength = SkScalarDiv(SkIntToScalar(length), SkIntToScalar(numDashes)); - } else - dashLength = SkFloatToScalar(width); - SkScalar intervals[2] = { dashLength, dashLength }; - paint->setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref(); + // Truncate the width, since we don't want fuzzy dots or dashes. + int dashLength = static_cast<int>(width); + // Subtract off the endcaps, since they're rendered separately. + int distance = length - 2 * static_cast<int>(m_state->m_strokeThickness); + int phase = 1; + if (dashLength > 1) { + // Determine how many dashes or dots we should have. + int numDashes = distance / dashLength; + int remainder = distance % dashLength; + // Adjust the phase to center the dashes within the line. + if (numDashes % 2 == 0) { + // Even: shift right half a dash, minus half the remainder + phase = (dashLength - remainder) / 2; + } else { + // Odd: shift right a full dash, minus half the remainder + phase = dashLength - remainder / 2; + } + } + SkScalar dashLengthSk = SkIntToScalar(dashLength); + SkScalar intervals[2] = { dashLengthSk, dashLengthSk }; + paint->setPathEffect(new SkDashPathEffect(intervals, 2, SkIntToScalar(phase)))->unref(); } } @@ -383,14 +390,15 @@ void PlatformContextSkia::setLineJoin(SkPaint::Join lj) m_state->m_lineJoin = lj; } -void PlatformContextSkia::setPorterDuffMode(SkPorterDuff::Mode pdm) +void PlatformContextSkia::setXfermodeMode(SkXfermode::Mode pdm) { - m_state->m_porterDuffMode = pdm; + m_state->m_xferMode = pdm; } void PlatformContextSkia::setFillColor(SkColor color) { m_state->m_fillColor = color; + setFillShader(NULL); } SkDrawLooper* PlatformContextSkia::getDrawLooper() const @@ -411,6 +419,7 @@ void PlatformContextSkia::setStrokeStyle(WebCore::StrokeStyle strokeStyle) void PlatformContextSkia::setStrokeColor(SkColor strokeColor) { m_state->m_strokeColor = strokeColor; + setStrokeShader(NULL); } float PlatformContextSkia::getStrokeThickness() const @@ -423,6 +432,15 @@ void PlatformContextSkia::setStrokeThickness(float thickness) m_state->m_strokeThickness = thickness; } +void PlatformContextSkia::setStrokeShader(SkShader* strokeShader) +{ + if (strokeShader != m_state->m_strokeShader) { + m_state->m_strokeShader->safeUnref(); + m_state->m_strokeShader = strokeShader; + m_state->m_strokeShader->safeRef(); + } +} + int PlatformContextSkia::getTextDrawingMode() const { return m_state->m_textDrawingMode; @@ -471,7 +489,8 @@ SkPath PlatformContextSkia::currentPathInLocalCoordinates() const SkPath localPath = m_path; const SkMatrix& matrix = m_canvas->getTotalMatrix(); SkMatrix inverseMatrix; - matrix.invert(&inverseMatrix); + if (!matrix.invert(&inverseMatrix)) + return SkPath(); localPath.transform(inverseMatrix); return localPath; } @@ -481,19 +500,12 @@ void PlatformContextSkia::setFillRule(SkPath::FillType fr) m_path.setFillType(fr); } -void PlatformContextSkia::setGradient(SkShader* gradient) -{ - if (gradient != m_state->m_gradient) { - m_state->m_gradient->safeUnref(); - m_state->m_gradient = gradient; - } -} - -void PlatformContextSkia::setPattern(SkShader* pattern) +void PlatformContextSkia::setFillShader(SkShader* fillShader) { - if (pattern != m_state->m_pattern) { - m_state->m_pattern->safeUnref(); - m_state->m_pattern = pattern; + if (fillShader != m_state->m_fillShader) { + m_state->m_fillShader->safeUnref(); + m_state->m_fillShader = fillShader; + m_state->m_fillShader->safeRef(); } } @@ -527,7 +539,7 @@ void PlatformContextSkia::applyClipFromImage(const WebCore::FloatRect& rect, con // NOTE: this assumes the image mask contains opaque black for the portions that are to be shown, as such we // only look at the alpha when compositing. I'm not 100% sure this is what WebKit expects for image clipping. SkPaint paint; - paint.setPorterDuffXfermode(SkPorterDuff::kDstIn_Mode); + paint.setXfermodeMode(SkXfermode::kDstIn_Mode); m_canvas->drawBitmap(imageBuffer, SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), &paint); } #endif diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index 25495aa..0c87fc2 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -60,7 +60,7 @@ // responsible for managing the painting state which is store in separate // SkPaint objects. This class provides the adaptor that allows the painting // state to be pushed and popped along with the bitmap. -class PlatformContextSkia : Noncopyable { +class PlatformContextSkia : public Noncopyable { public: // For printing, there shouldn't be any canvas. canvas can be NULL. If you // supply a NULL canvas, you can also call setCanvas later. @@ -115,15 +115,15 @@ public: void setLineCap(SkPaint::Cap); void setLineJoin(SkPaint::Join); void setFillRule(SkPath::FillType); - void setPorterDuffMode(SkPorterDuff::Mode); + void setXfermodeMode(SkXfermode::Mode); void setFillColor(SkColor); + void setFillShader(SkShader*); void setStrokeStyle(WebCore::StrokeStyle); void setStrokeColor(SkColor); void setStrokeThickness(float thickness); + void setStrokeShader(SkShader*); void setTextDrawingMode(int mode); void setUseAntialiasing(bool enable); - void setGradient(SkShader*); - void setPattern(SkShader*); void setDashPathEffect(SkDashPathEffect*); SkDrawLooper* getDrawLooper() const; diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp index 7f12508..f1c5cdc 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -267,21 +267,11 @@ static bool skiaDrawText(HFONT hfont, SkCanvas* canvas, const SkPoint& point, SkPaint* paint, - const TransformationMatrix& transformationMatrix, - Gradient* gradient, - Pattern* pattern, const WORD* glyphs, const int* advances, const GOFFSET* offsets, int numGlyphs) { - SkShader* shader = NULL; - if (gradient) - shader = gradient->platformGradient(); - else if (pattern) - shader = pattern->createPlatformPattern(transformationMatrix); - - paint->setShader(shader); float x = point.fX, y = point.fY; for (int i = 0; i < numGlyphs; i++) { @@ -326,14 +316,7 @@ bool paintSkiaText(GraphicsContext* context, bool didFill = false; if ((textMode & cTextFill) && SkColorGetA(paint.getColor())) { - Gradient* fillGradient = 0; - Pattern* fillPattern = 0; - if (context->fillColorSpace() == GradientColorSpace) - fillGradient = context->fillGradient(); - else if (context->fillColorSpace() == PatternColorSpace) - fillPattern = context->fillPattern(); if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint, - context->getCTM(), fillGradient, fillPattern, &glyphs[0], &advances[0], &offsets[0], numGlyphs)) return false; didFill = true; @@ -360,14 +343,7 @@ bool paintSkiaText(GraphicsContext* context, paint.setLooper(0)->safeUnref(); } - Gradient* strokeGradient = 0; - Pattern* strokePattern = 0; - if (context->strokeColorSpace() == GradientColorSpace) - strokeGradient = context->strokeGradient(); - else if (context->strokeColorSpace() == PatternColorSpace) - strokePattern = context->strokePattern(); if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint, - context->getCTM(), strokeGradient, strokePattern, &glyphs[0], &advances[0], &offsets[0], numGlyphs)) return false; } diff --git a/WebCore/platform/graphics/skia/SkiaUtils.cpp b/WebCore/platform/graphics/skia/SkiaUtils.cpp index a7a266d..dbbbdbf 100644 --- a/WebCore/platform/graphics/skia/SkiaUtils.cpp +++ b/WebCore/platform/graphics/skia/SkiaUtils.cpp @@ -42,6 +42,7 @@ namespace WebCore { +#ifdef MANUAL_MERGE_REQUIRED static const struct CompositOpToSkiaMode { uint8_t mCompositOp; uint8_t mMode; @@ -77,36 +78,39 @@ SkXfermode::Mode WebCoreCompositeToSkiaMode(CompositeOperator op) } static const struct CompositOpToPorterDuffMode { +#else // MANUAL_MERGE_REQUIRED +static const struct CompositOpToXfermodeMode { +#endif // MANUAL_MERGE_REQUIRED uint8_t mCompositOp; - uint8_t mPorterDuffMode; -} gMapCompositOpsToPorterDuffModes[] = { - { CompositeClear, SkPorterDuff::kClear_Mode }, - { CompositeCopy, SkPorterDuff::kSrc_Mode }, - { CompositeSourceOver, SkPorterDuff::kSrcOver_Mode }, - { CompositeSourceIn, SkPorterDuff::kSrcIn_Mode }, - { CompositeSourceOut, SkPorterDuff::kSrcOut_Mode }, - { CompositeSourceAtop, SkPorterDuff::kSrcATop_Mode }, - { CompositeDestinationOver, SkPorterDuff::kDstOver_Mode }, - { CompositeDestinationIn, SkPorterDuff::kDstIn_Mode }, - { CompositeDestinationOut, SkPorterDuff::kDstOut_Mode }, - { CompositeDestinationAtop, SkPorterDuff::kDstATop_Mode }, - { CompositeXOR, SkPorterDuff::kXor_Mode }, - { CompositePlusDarker, SkPorterDuff::kDarken_Mode }, - { CompositeHighlight, SkPorterDuff::kSrcOver_Mode }, // TODO - { CompositePlusLighter, SkPorterDuff::kAdd_Mode } + uint8_t m_xfermodeMode; +} gMapCompositOpsToXfermodeModes[] = { + { CompositeClear, SkXfermode::kClear_Mode }, + { CompositeCopy, SkXfermode::kSrc_Mode }, + { CompositeSourceOver, SkXfermode::kSrcOver_Mode }, + { CompositeSourceIn, SkXfermode::kSrcIn_Mode }, + { CompositeSourceOut, SkXfermode::kSrcOut_Mode }, + { CompositeSourceAtop, SkXfermode::kSrcATop_Mode }, + { CompositeDestinationOver, SkXfermode::kDstOver_Mode }, + { CompositeDestinationIn, SkXfermode::kDstIn_Mode }, + { CompositeDestinationOut, SkXfermode::kDstOut_Mode }, + { CompositeDestinationAtop, SkXfermode::kDstATop_Mode }, + { CompositeXOR, SkXfermode::kXor_Mode }, + { CompositePlusDarker, SkXfermode::kDarken_Mode }, + { CompositeHighlight, SkXfermode::kSrcOver_Mode }, // TODO + { CompositePlusLighter, SkXfermode::kPlus_Mode } }; -SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op) +SkXfermode::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op) { - const CompositOpToPorterDuffMode* table = gMapCompositOpsToPorterDuffModes; + const CompositOpToXfermodeMode* table = gMapCompositOpsToXfermodeModes; - for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToPorterDuffModes); i++) { + for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes); i++) { if (table[i].mCompositOp == op) - return (SkPorterDuff::Mode)table[i].mPorterDuffMode; + return (SkXfermode::Mode)table[i].m_xfermodeMode; } SkDEBUGF(("GraphicsContext::setCompositeOperation uknown CompositeOperator %d\n", op)); - return SkPorterDuff::kSrcOver_Mode; // fall-back + return SkXfermode::kSrcOver_Mode; // fall-back } Color SkPMColorToWebCoreColor(SkPMColor pm) @@ -168,8 +172,12 @@ bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath:: SkPath scaledPath; int scale = 1; +#ifdef MANUAL_MERGE_REQUIRED SkRect bounds; bounds = originalPath->getBounds(); +#else // MANUAL_MERGE_REQUIRED + SkRect bounds = originalPath->getBounds(); +#endif // MANUAL_MERGE_REQUIRED // We can immediately return false if the point is outside the bounding rect if (!bounds.contains(SkFloatToScalar(point.x()), SkFloatToScalar(point.y()))) @@ -208,7 +216,7 @@ GraphicsContext* scratchContext() { static ImageBuffer* scratch = 0; if (!scratch) - scratch = ImageBuffer::create(IntSize(1, 1), false).release(); + scratch = ImageBuffer::create(IntSize(1, 1)).release(); // We don't bother checking for failure creating the ImageBuffer, since our // ImageBuffer initializer won't fail. return scratch->context(); diff --git a/WebCore/platform/graphics/skia/SkiaUtils.h b/WebCore/platform/graphics/skia/SkiaUtils.h index aa4cd4d..a210cd3 100644 --- a/WebCore/platform/graphics/skia/SkiaUtils.h +++ b/WebCore/platform/graphics/skia/SkiaUtils.h @@ -36,16 +36,24 @@ #include <wtf/MathExtras.h> #include "GraphicsContext.h" #include "SkPath.h" +#ifdef MANUAL_MERGE_REQUIRED #include "SkPorterDuff.h" #include "SkXfermode.h" +#else // MANUAL_MERGE_REQUIRED +#include "SkXfermode.h" +#endif // MANUAL_MERGE_REQUIRED class SkCanvas; class SkRegion; namespace WebCore { +#ifdef MANUAL_MERGE_REQUIRED SkXfermode::Mode WebCoreCompositeToSkiaMode(CompositeOperator); SkPorterDuff::Mode WebCoreCompositeToSkiaComposite(CompositeOperator); +#else // MANUAL_MERGE_REQUIRED +SkXfermode::Mode WebCoreCompositeToSkiaComposite(CompositeOperator); +#endif // MANUAL_MERGE_REQUIRED // move this guy into SkColor.h SkColor SkPMColorToColor(SkPMColor); |